mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-11-08 08:10:08 +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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -8,6 +9,7 @@ import (
|
||||||
"gopkg.in/irc.v4"
|
"gopkg.in/irc.v4"
|
||||||
|
|
||||||
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
"github.com/Luzifer/go_helpers/v2/fieldcollection"
|
||||||
|
"github.com/Luzifer/twitch-bot/v3/internal/locker"
|
||||||
"github.com/Luzifer/twitch-bot/v3/plugins"
|
"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) {
|
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 (
|
var (
|
||||||
ruleEventData = fieldcollection.NewFieldCollection()
|
ruleEventData = fieldcollection.NewFieldCollection()
|
||||||
preventCooldown bool
|
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