Skip to content

Commit a1fb628

Browse files
committed
better lock flow
1 parent 3cebcce commit a1fb628

File tree

4 files changed

+65
-26
lines changed

4 files changed

+65
-26
lines changed

bot/bot.go

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type bot struct {
2525
defaultNamespace string
2626
configurations map[string]Configuration
2727

28-
cacheLocker *sync.Mutex
28+
globalLocker *sync.Mutex
2929
namespaceMutexes *cache.Cache
3030
repoIssueMutexes *cache.Cache
3131
}
@@ -42,24 +42,32 @@ func (b *bot) getCurrentConfiguration(namespace string) (Configuration, error) {
4242
return configuration, nil
4343
}
4444

45-
func (b *bot) processRules(configuration Configuration, data EventData) *HandledEventResult {
46-
id := fmt.Sprintf("%s/%s#%d", data.GetOwner(), data.GetRepo(), data.GetNumber())
47-
util.Logger.Debug("acquire global lock during rules process")
48-
b.cacheLocker.Lock()
49-
locker, exists := b.repoIssueMutexes.Get(id)
45+
func (b *bot) processRules(
46+
namespaceLock *sync.Mutex,
47+
configuration Configuration,
48+
partial EventData,
49+
r *http.Request) *HandledEventResult {
50+
id := fmt.Sprintf("%s/%s#%d", partial.GetOwner(), partial.GetRepo(), partial.GetNumber())
51+
util.Logger.Debug("acquire namespace lock during rules process")
52+
issueLocker, exists := b.repoIssueMutexes.Get(id)
5053
if !exists {
51-
locker = &sync.Mutex{}
52-
b.repoIssueMutexes.Set(id, locker, cache.DefaultExpiration)
54+
issueLocker = &sync.Mutex{}
55+
b.repoIssueMutexes.Set(id, issueLocker, cache.DefaultExpiration)
5356
}
5457
util.Logger.Debug("acquire repo issue %s lock during rules process", id)
55-
locker.(*sync.Mutex).Lock()
56-
defer locker.(*sync.Mutex).Unlock()
57-
util.Logger.Debug("release global lock during rules process")
58-
b.cacheLocker.Unlock()
58+
issueLocker.(*sync.Mutex).Lock()
59+
defer issueLocker.(*sync.Mutex).Unlock()
60+
util.Logger.Debug("release namespace lock during rules process")
61+
namespaceLock.Unlock()
5962
applied := make([]Rule, 0)
6063
result := &HandledEventResult{
6164
AppliedRules: []string{},
6265
}
66+
data, ok := completeBuildFromRequest(configuration.GetClientConfig(), r)
67+
if !ok {
68+
util.Logger.Debug("Skipping rule processing for %s (couldn't build complete data)", id)
69+
return result
70+
}
6371
for _, rule := range configuration.GetRules() {
6472
if rule.Accept(data) {
6573
util.Logger.Debug("Accepting rule %s for '%s'", rule.Name(), data.GetTitle())
@@ -78,7 +86,7 @@ func (b *bot) processRules(configuration Configuration, data EventData) *Handled
7886

7987
func (b *bot) HandleEvent(r *http.Request) *HandledEventResult {
8088
namespace := r.URL.Query().Get("namespace")
81-
b.cacheLocker.Lock()
89+
b.globalLocker.Lock()
8290
util.Logger.Debug("acquire global lock during namespace process")
8391
locker, exists := b.namespaceMutexes.Get(namespace)
8492
if !exists {
@@ -88,7 +96,7 @@ func (b *bot) HandleEvent(r *http.Request) *HandledEventResult {
8896
util.Logger.Debug("acquire namespace %s lock", namespace)
8997
locker.(*sync.Mutex).Lock()
9098
util.Logger.Debug("release global lock during namespace process")
91-
b.cacheLocker.Unlock()
99+
b.globalLocker.Unlock()
92100
workingConfiguration, err := b.getCurrentConfiguration(namespace)
93101
if err != nil {
94102
locker.(*sync.Mutex).Unlock()
@@ -100,14 +108,13 @@ func (b *bot) HandleEvent(r *http.Request) *HandledEventResult {
100108
return &HandledEventResult{Message: "Skipping rules processing (could be not supported event type)"}
101109
}
102110
util.Logger.Debug("release namespace %s lock", namespace)
103-
locker.(*sync.Mutex).Unlock()
104-
return b.processRules(workingConfiguration, data)
111+
return b.processRules(locker.(*sync.Mutex), workingConfiguration, data, r)
105112
}
106113

107114
func New(configPaths ...string) (Bot, error) {
108115
b := &bot{
109116
configurations: make(map[string]Configuration),
110-
cacheLocker: &sync.Mutex{},
117+
globalLocker: &sync.Mutex{},
111118
namespaceMutexes: cache.New(time.Minute, 30*time.Second),
112119
repoIssueMutexes: cache.New(time.Minute, 20*time.Second),
113120
}

bot/bot_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ func (m *mockEventDataBuilder) BuildFromRequest(config ClientConfig, r *http.Req
1414
return &mockConditionEventData{Labels: m.Labels}, true, nil
1515
}
1616

17-
func (*mockEventDataBuilder) Build(config ClientConfig, json string) (EventData, error) {
18-
panic("implement me")
17+
func (m *mockEventDataBuilder) PartialBuildFromRequest(config ClientConfig, r *http.Request) (EventData, bool, error) {
18+
return &mockConditionEventData{Labels: m.Labels}, true, nil
1919
}
2020

2121
func buildRequest(t *testing.T, url string) *http.Request {

bot/connector/github/builder.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (builder *eventDataBuilder) checkProcessState() bool {
8686
return builder.data.state != "closed"
8787
}
8888

89-
func (builder *eventDataBuilder) BuildFromRequest(config bot.ClientConfig, r *http.Request) (bot.EventData, bool, error) {
89+
func (builder *eventDataBuilder) PartialBuildFromRequest(config bot.ClientConfig, r *http.Request) (bot.EventData, bool, error) {
9090
githubEvent := r.Header.Get("X-Github-Event")
9191
if githubEvent == "ping" {
9292
util.Logger.Message("Got GitHub 'ping' event")
@@ -114,15 +114,22 @@ func (builder *eventDataBuilder) BuildFromRequest(config bot.ClientConfig, r *ht
114114
}
115115
repo := pl.Repository.Name
116116
owner := pl.Repository.Owner.Login
117-
builder.client = newClient(config, owner, repo)
118-
builder.data = &eventData{client: builder.client, owner: owner, repo: repo}
117+
builder.data = &eventData{owner: owner, repo: repo}
119118
builder.readFromJson(pl)
120-
builder.readFromClient()
121119
return builder.data, builder.checkProcessState(), nil
122120
}
123121

124-
func (*eventDataBuilder) Build(config bot.ClientConfig, json string) (bot.EventData, error) {
125-
panic("implement me")
122+
func (builder *eventDataBuilder) BuildFromRequest(config bot.ClientConfig, r *http.Request) (bot.EventData, bool, error) {
123+
_, ok, err := builder.PartialBuildFromRequest(config, r)
124+
if !ok || err != nil {
125+
return nil, ok, err
126+
}
127+
repo := builder.data.repo
128+
owner := builder.data.owner
129+
builder.client = newClient(config, owner, repo)
130+
builder.data.client = builder.client
131+
builder.readFromClient()
132+
return builder.data, builder.checkProcessState(), nil
126133
}
127134

128135
func init() {

bot/data.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ type EventData interface {
3636
}
3737

3838
type EventDataBuilder interface {
39+
PartialBuildFromRequest(config ClientConfig, r *http.Request) (EventData, bool, error)
3940
BuildFromRequest(config ClientConfig, r *http.Request) (EventData, bool, error)
40-
Build(config ClientConfig, json string) (EventData, error)
4141
}
4242

4343
var builders map[string]EventDataBuilder = make(map[string]EventDataBuilder)
@@ -54,6 +54,31 @@ func RegisterNewBuilder(provider string, builder EventDataBuilder) {
5454
}
5555

5656
func buildFromRequest(config ClientConfig, r *http.Request) (EventData, bool) {
57+
var builder EventDataBuilder
58+
for name := range r.Header {
59+
for provider := range builders {
60+
if strings.Contains(strings.ToLower(name), provider) {
61+
builder = builders[provider]
62+
break
63+
}
64+
}
65+
if builder != nil {
66+
break
67+
}
68+
}
69+
if builder == nil {
70+
util.Logger.Error("No Builder to work with!")
71+
return nil, false
72+
}
73+
result, process, err := builder.PartialBuildFromRequest(config, r)
74+
if err != nil {
75+
util.Logger.Error("Unable to build from request. %s", err)
76+
return nil, false
77+
}
78+
return result, process
79+
}
80+
81+
func completeBuildFromRequest(config ClientConfig, r *http.Request) (EventData, bool) {
5782
var builder EventDataBuilder
5883
for name := range r.Header {
5984
for provider := range builders {

0 commit comments

Comments
 (0)