Skip to content

Commit

Permalink
Add a mutex to org-channel map in off-thread org monitor
Browse files Browse the repository at this point in the history
A concurrent read and write (or just concurrent writes) panic with the map between org IDs and channels for monitoring quota for the org can happen when several requests to APIs belonging to the same organisation occur at the same time and there's no mapping yet. This is pretty easy to reproduce by launching a lot of simultaneus requests right before the gateway starts (e.g. with ab tool).

In addition to this, tyk.with_dash.conf template now ships with off-thread org processing disabled as there's no org session by default in on-prem installations.
  • Loading branch information
excieve authored and buger committed Mar 7, 2018
1 parent d778272 commit acf1065
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 6 deletions.
2 changes: 1 addition & 1 deletion install/data/tyk.with_dash.conf
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"close_connections": true,
"enable_non_transactional_rate_limiter": true,
"enable_sentinel_rate_limiter": false,
"experimental_process_org_off_thread": true,
"experimental_process_org_off_thread": false,
"local_session_cache": {
"disable_cached_session_state": false
},
Expand Down
15 changes: 10 additions & 5 deletions mw_organisation_activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import (
"github.com/TykTechnologies/tyk/config"
)

var orgChanMap = make(map[string]chan bool)
type orgChanMapMu struct {
sync.Mutex
channels map[string](chan bool)
}

var orgChanMap = orgChanMapMu{channels: map[string](chan bool){}}
var orgActiveMap sync.Map

// RateLimitAndQuotaCheck will check the incomming request and key whether it is within it's quota and
Expand Down Expand Up @@ -104,13 +108,14 @@ func (k *OrganizationMonitor) SetOrgSentinel(orgChan chan bool, orgId string) {
}

func (k *OrganizationMonitor) ProcessRequestOffThread(r *http.Request) (error, int) {

orgChan, ok := orgChanMap[k.Spec.OrgID]
orgChanMap.Lock()
orgChan, ok := orgChanMap.channels[k.Spec.OrgID]
if !ok {
orgChanMap[k.Spec.OrgID] = make(chan bool)
orgChan = orgChanMap[k.Spec.OrgID]
orgChan = make(chan bool)
orgChanMap.channels[k.Spec.OrgID] = orgChan
go k.SetOrgSentinel(orgChan, k.Spec.OrgID)
}
orgChanMap.Unlock()
active, found := orgActiveMap.Load(k.Spec.OrgID)

go k.AllowAccessNext(orgChan, r.URL.Path, requestIP(r), r)
Expand Down

0 comments on commit acf1065

Please sign in to comment.