42 lines
1023 B
Go
42 lines
1023 B
Go
package advisorylock
|
|
|
|
import (
|
|
"context"
|
|
"runtime/debug"
|
|
"time"
|
|
|
|
"github.com/mudler/xlog"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// RunLeaderLoop runs fn on a fixed interval, guarded by a PostgreSQL advisory lock.
|
|
// Only one instance across the cluster executes fn at a time. If the lock is not
|
|
// acquired (another instance holds it), the tick is skipped.
|
|
// The loop stops when ctx is cancelled.
|
|
func RunLeaderLoop(ctx context.Context, db *gorm.DB, lockKey int64, interval time.Duration, fn func()) {
|
|
ticker := time.NewTicker(interval)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
func() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
xlog.Error("Leader loop callback panicked", "key", lockKey, "panic", r, "stack", string(debug.Stack()))
|
|
}
|
|
}()
|
|
_, err := TryWithLockCtx(ctx, db, lockKey, func() error {
|
|
fn()
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
xlog.Error("Leader loop advisory lock error", "key", lockKey, "error", err)
|
|
}
|
|
}()
|
|
}
|
|
}
|
|
}
|