From 4fb3b987637d059463250ed4de26342f6441fef3 Mon Sep 17 00:00:00 2001 From: John Roesler Date: Fri, 16 May 2025 14:15:33 -0500 Subject: [PATCH] chore: document the limitations with the locker design (#848) --- README.md | 2 ++ distributed.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/README.md b/README.md index d15e59f..43f46c5 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,8 @@ other instances checking to see if a new leader needs to be elected. - [**Locker**](https://pkg.go.dev/github.com/go-co-op/gocron/v2#WithDistributedLocker): A locker can be used to lock each run of a job to a single instance of gocron. Locker can be at job or scheduler, if it is defined both at job and scheduler then locker of job will take precedence. + - See Notes in the doc for [Locker](https://pkg.go.dev/github.com/go-co-op/gocron/v2#Locker) for + details and limitations of the locker design. - Implementations: [go-co-op lockers](https://github.com/go-co-op?q=-lock&type=all&language=&sort=) (don't see what you need? request on slack to get a repo created to contribute it!) diff --git a/distributed.go b/distributed.go index 1617c62..98e906e 100644 --- a/distributed.go +++ b/distributed.go @@ -18,6 +18,21 @@ type Elector interface { // locker implementation handles time splay between schedulers. // The lock key passed is the job's name - which, if not set, defaults to the // go function's name, e.g. "pkg.myJob" for func myJob() {} in pkg +// +// Notes: The locker and scheduler do not handle synchronization of run times across +// schedulers. +// +// 1. If you are using duration based jobs (DurationJob), you can utilize the JobOption +// WithStartAt to set a start time for the job to the nearest time rounded to your +// duration. For example, if you have a job that runs every 5 minutes, you can set +// the start time to the nearest 5 minute e.g. 12:05, 12:10. +// +// 2. For all jobs, the implementation is still vulnerable to clockskew between scheduler +// instances. This may result in a single scheduler instance running the majority of the +// jobs. +// +// For distributed jobs, consider utilizing the Elector option if these notes are not acceptable +// to your use case. type Locker interface { // Lock if an error is returned by lock, the job will not be scheduled. Lock(ctx context.Context, key string) (Lock, error)