From 8b575f77713e60205e7b38d6f87b102ff00c7461 Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Thu, 1 Apr 2021 12:28:51 +0200 Subject: [PATCH] Fix: Concurrent access to map panic Signed-off-by: Knut Ahlers --- twitch.go | 4 ++-- twitchAPICache.go | 28 ++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/twitch.go b/twitch.go index f9eb942..79cf064 100644 --- a/twitch.go +++ b/twitch.go @@ -15,12 +15,12 @@ import ( var twitch = newTwitchClient() type twitchClient struct { - apiCache twitchAPICache + apiCache *twitchAPICache } func newTwitchClient() *twitchClient { return &twitchClient{ - apiCache: make(twitchAPICache), + apiCache: newTwitchAPICache(), } } diff --git a/twitchAPICache.go b/twitchAPICache.go index 894ad12..6812bf4 100644 --- a/twitchAPICache.go +++ b/twitchAPICache.go @@ -4,19 +4,32 @@ import ( "crypto/sha256" "fmt" "strings" + "sync" "time" ) type ( - twitchAPICache map[string]twitchAPICacheEntry + twitchAPICache struct { + data map[string]twitchAPICacheEntry + lock sync.RWMutex + } twitchAPICacheEntry struct { Data interface{} ValidUntil time.Time } ) -func (t twitchAPICache) Get(key []string) interface{} { - e := t[t.deriveKey(key)] +func newTwitchAPICache() *twitchAPICache { + return &twitchAPICache{ + data: make(map[string]twitchAPICacheEntry), + } +} + +func (t *twitchAPICache) Get(key []string) interface{} { + t.lock.RLock() + defer t.lock.RUnlock() + + e := t.data[t.deriveKey(key)] if e.ValidUntil.Before(time.Now()) { return nil } @@ -24,14 +37,17 @@ func (t twitchAPICache) Get(key []string) interface{} { return e.Data } -func (t twitchAPICache) Set(key []string, valid time.Duration, data interface{}) { - t[t.deriveKey(key)] = twitchAPICacheEntry{ +func (t *twitchAPICache) Set(key []string, valid time.Duration, data interface{}) { + t.lock.Lock() + defer t.lock.Unlock() + + t.data[t.deriveKey(key)] = twitchAPICacheEntry{ Data: data, ValidUntil: time.Now().Add(valid), } } -func (twitchAPICache) deriveKey(key []string) string { +func (*twitchAPICache) deriveKey(key []string) string { sha := sha256.New() fmt.Fprintf(sha, "%s", strings.Join(key, ":"))