package election import ( "context" "errors" "log/slog" "time" "github.com/bsm/redislock" ) var defaultLeaderElectionOptions = leaderElectionOptions{ lockKey: "ibd-leader-election", lockTTL: 10 * time.Second, } func RunOrDie( ctx context.Context, client redislock.RedisClient, onLeader func(context.Context), opts ...LeaderElectionOption, ) { o := defaultLeaderElectionOptions for _, opt := range opts { opt(&o) } locker := redislock.New(client) // Election loop for { lock, err := locker.Obtain(ctx, o.lockKey, o.lockTTL, nil) if errors.Is(err, redislock.ErrNotObtained) { // Another instance is the leader } else if err != nil { slog.ErrorContext(ctx, "failed to obtain lock", "error", err) } else { // We are the leader slog.DebugContext(ctx, "elected leader") runLeader(ctx, lock, onLeader, o) } // Sleep for a bit before trying again timer := time.NewTimer(o.lockTTL / 5) select { case <-ctx.Done(): if !timer.Stop() { <-timer.C } return case <-timer.C: } } } func runLeader( ctx context.Context, lock *redislock.Lock, onLeader func(context.Context), o leaderElectionOptions, ) { // A context that is canceled when the leader loses the lock ctx, cancel := context.WithCancel(ctx) defer cancel() // Release the lock when done defer func() { // Create new context without cancel if the original context is already canceled relCtx := ctx if ctx.Err() != nil { relCtx = context.WithoutCancel(ctx) } // Add a timeout to the release context relCtx, cancel := context.WithTimeout(relCtx, o.lockTTL) defer cancel() if err := lock.Release(relCtx); err != nil { slog.Error("failed to release lock", "error", err) } }() // Run the leader code go func(ctx context.Context) { onLeader(ctx) // If the leader code returns, cancel the context to release the lock cancel() }(ctx) // Refresh the lock periodically ticker := time.NewTicker(o.lockTTL / 10) defer ticker.Stop() for { select { case <-ticker.C: err := lock.Refresh(ctx, o.lockTTL, nil) if errors.Is(err, redislock.ErrNotObtained) || errors.Is(err, redislock.ErrLockNotHeld) { slog.ErrorContext(ctx, "leadership lost", "error", err) return } else if err != nil { slog.ErrorContext(ctx, "failed to refresh lock", "error", err) } case <-ctx.Done(): return } } } type leaderElectionOptions struct { lockKey string lockTTL time.Duration } type LeaderElectionOption func(*leaderElectionOptions) func WithLockKey(key string) LeaderElectionOption { return func(o *leaderElectionOptions) { o.lockKey = key } } func WithLockTTL(ttl time.Duration) LeaderElectionOption { return func(o *leaderElectionOptions) { o.lockTTL = ttl } } n value='db22'>db22 Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/packages/integrations/tailwind (unfollow)
AgeCommit message (Expand)AuthorFilesLines
2022-05-12Serialize route generation (#3354)Gravatar Juan Martín Seery 5-59/+61
2022-05-12Corrected the default value of trailingSlash (#3353)Gravatar Rafid Muhymin Wafi 1-1/+1
2022-05-12[ci] formatGravatar matthewp 1-85/+78
2022-05-12Fixed search bar of the docs example not working (#3247)Gravatar Rafid Muhymin Wafi 1-76/+94
2022-05-12Add config option customPages (#3315)Gravatar Eloi-Perez 1-0/+14
2022-05-12fix: vite types (#3352)Gravatar Juan Martín Seery 4-5/+16
2022-05-12[ci] update lockfile (#3287)Gravatar Fred K. Schott 33-1038/+1096
2022-05-12[ci] formatGravatar matthewp 2-2/+2
2022-05-12add error hints (#3350)Gravatar Fred K. Schott 3-0/+19
2022-05-12[ci] formatGravatar matthewp 2-10/+6
2022-05-12Fix: React - Use "createRoot" instead of "hydrateRoot" for `client:only` (#3337)Gravatar Ben Holmes 4-22/+34
2022-05-12[ci] formatGravatar matthewp 1-2/+8
2022-05-12Resolve components by module ID during compilation (#3300)Gravatar Tony Sullivan 22-41/+407
2022-05-12[ci] collect statsGravatar FredKSchott 1-0/+1
2022-05-11Exclude `node-fetch` from vite.optimizeDeps (#3348)Gravatar Nate Moore 2-0/+6
2022-05-11fix: updated blog template with existing address (#3312)Gravatar Gautier Ben Aïm 1-2/+2
2022-05-11refactor(vercel): Build Output API v3 (#3216)Gravatar Juan Martín Seery 42-231/+659
2022-05-11Fix APIRoute type (#3344)Gravatar Matthew Phillips 3-11/+8
2022-05-11[create-astro] Finalize developer experience... with gradients 🚀 (#3313)Gravatar Ben Holmes 5-23/+123