mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 03:41:16 +00:00
[core] Add locking to prevent concurrent rule executions
refs #59 ensures counter actions are not triggered concurrently by two persons Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
a01ce9aa5f
commit
5dd6a5323c
2 changed files with 55 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -8,6 +9,7 @@ import (
|
|||
"gopkg.in/irc.v4"
|
||||
|
||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||
"github.com/Luzifer/twitch-bot/v3/internal/locker"
|
||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
||||
)
|
||||
|
||||
|
@ -79,6 +81,9 @@ func handleMessage(c *irc.Client, m *irc.Message, event *string, eventData *fiel
|
|||
}
|
||||
|
||||
func handleMessageRuleExecution(c *irc.Client, m *irc.Message, r *plugins.Rule, eventData *fieldcollection.FieldCollection) {
|
||||
locker.LockByKey(path.Join("rule-execution", r.MatcherID()))
|
||||
defer locker.UnlockByKey(path.Join("rule-execution", r.MatcherID()))
|
||||
|
||||
var (
|
||||
ruleEventData = fieldcollection.NewFieldCollection()
|
||||
preventCooldown bool
|
||||
|
|
50
internal/locker/locker.go
Normal file
50
internal/locker/locker.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Package locker contains a way to interact with arbitrary locks
|
||||
package locker
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
locks = map[string]*sync.RWMutex{}
|
||||
locksOLocks sync.RWMutex
|
||||
)
|
||||
|
||||
// LockByKey takes a key to lock and locks the corresponding RWMutex
|
||||
func LockByKey(key string) { getLockByKey(key).Lock() }
|
||||
|
||||
// RLockByKey takes a key to lock and read-locks the corresponding RWMutex
|
||||
func RLockByKey(key string) { getLockByKey(key).RLock() }
|
||||
|
||||
// RUnlockByKey takes a key to lock and read-unlocks the corresponding RWMutex
|
||||
func RUnlockByKey(key string) { getLockByKey(key).RUnlock() }
|
||||
|
||||
// UnlockByKey takes a key to lock and unlocks the corresponding RWMutex
|
||||
func UnlockByKey(key string) { getLockByKey(key).Unlock() }
|
||||
|
||||
// WithLock takes a key to lock and a function to execute during the
|
||||
// lock of this key
|
||||
func WithLock(key string, fn func()) {
|
||||
LockByKey(key)
|
||||
defer UnlockByKey(key)
|
||||
|
||||
fn()
|
||||
}
|
||||
|
||||
// WithRLock takes a key to lock and a function to execute during the
|
||||
// read-lock of this key
|
||||
func WithRLock(key string, fn func()) {
|
||||
RLockByKey(key)
|
||||
defer RUnlockByKey(key)
|
||||
|
||||
fn()
|
||||
}
|
||||
|
||||
func getLockByKey(key string) *sync.RWMutex {
|
||||
locksOLocks.Lock()
|
||||
defer locksOLocks.Unlock()
|
||||
|
||||
if locks[key] == nil {
|
||||
locks[key] = new(sync.RWMutex)
|
||||
}
|
||||
|
||||
return locks[key]
|
||||
}
|
Loading…
Reference in a new issue