Documentation
¶
Overview ¶
Package workers provides background job management with periodic execution, scheduling, retry logic, and graceful shutdown.
Workers is designed for running background tasks like data processing, cleanup jobs, API synchronization, and scheduled reports.
Basic Usage ¶
Create a WorkerManager, register workers with their jobs, and start:
wm := workers.NewWorkerManager()
wm.RegisterWorker(workers.NewWorker("cleanup", cleanupJob))
wm.Start()
Jobs are functions that receive a context:
func cleanupJob(ctx context.Context) error {
return nil
}
Configuration ¶
Configure workers using functional options:
workers.NewWorker("sync", syncJob,
workers.WithTick(5*time.Minute),
workers.WithTimeout(30*time.Second),
workers.WithNRetries(3),
)
Scheduling ¶
Run jobs at specific times instead of intervals:
workers.WithSchedules(
workers.DailyAt(9, 0),
workers.WeeklyAt(time.Monday, 14, 30),
)
Retry and Backoff ¶
Automatic retries with configurable backoff strategies:
workers.WithNRetries(5), workers.WithRetryDelay(10*time.Second), workers.WithBackoffStrategy(workers.ExponentialBackoff)
Available strategies: ConstantBackoff, LinearBackoff, ExponentialBackoff. Custom strategies can be defined as: func(time.Duration, int) time.Duration
Graceful Shutdown ¶
The library handles SIGINT and SIGTERM signals, allowing running jobs to complete before shutdown.
Index ¶
- type BackoffStrategy
- func ConstantBackoff() BackoffStrategy
- func DecorrelatedJitterBackoff(capDelay time.Duration) BackoffStrategy
- func EqualJitterBackoff(capDelay time.Duration) BackoffStrategy
- func ExponentialBackoff() BackoffStrategy
- func FullJitterBackoff(capDelay time.Duration) BackoffStrategy
- func LinearBackoff() BackoffStrategy
- type BaseBackoff
- type Schedule
- type Worker
- type WorkerJob
- type WorkerManager
- type WorkerManagerOption
- type WorkerOption
- func WithBackoffStrategy(strategy BackoffStrategy) WorkerOption
- func WithItsOwnLogger(logger *slog.Logger) WorkerOption
- func WithNRetries(n int) WorkerOption
- func WithNRuns(n int) WorkerOption
- func WithRetryDelay(delay time.Duration) WorkerOption
- func WithSchedules(schedules ...Schedule) WorkerOption
- func WithTick(tick time.Duration) WorkerOption
- func WithTimeout(timeout time.Duration) WorkerOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BackoffStrategy ¶
type BackoffStrategy interface {
SetBaseDelay(baseDelay time.Duration)
GetNextDelay() time.Duration
Reset()
}
BackoffStrategy defines how long to wait between retry attempts. Implement this interface to create custom backoff strategies.
The worker calls GetNextDelay() to get the next retry delay. SetBaseDelay(baseDelay) is called when the worker is created to set the initial delay. Reset() is called after a successful retry to reset the backoff state for the next failure cycle.
Example:
type myBackoff struct {
workers.BaseBackoff
}
func (m *myBackoff) SetBaseDelay(baseDelay time.Duration) {
m.BaseDelay = baseDelay
}
func (m *myBackoff) GetNextDelay() time.Duration {
m.Attempt += 1
return m.BaseDelay * time.Duration(m.Attempt)
}
func (m *myBackoff) Reset() {
m.Attempt = 0
}
func ConstantBackoff ¶
func ConstantBackoff() BackoffStrategy
ConstantBackoff returns a fixed delay regardless of attempt number.
Formula:
delay = baseDelay
Example (base=5s):
5s, 5s, 5s, 5s...
func DecorrelatedJitterBackoff ¶ added in v1.2.0
func DecorrelatedJitterBackoff(capDelay time.Duration) BackoffStrategy
DecorrelatedJitterBackoff returns an exponential backoff strategy where the next delay depends on the previous delay, with added randomness.
Instead of strictly doubling the delay, this method randomly selects a value between baseDelay and three times the previous delay, then clamps it to capDelay.
Formula:
delay = min(capDelay, random(baseDelay, previousDelay * 3))
This produces a wider distribution of retry delays and helps prevent retry synchronization while still allowing delays to grow over time.
Example (base=5s, cap=40s):
random(5–15s) random(5–45s) random(5–120s) → capped at 40s random(5–120s) → capped at 40s...
func EqualJitterBackoff ¶ added in v1.2.0
func EqualJitterBackoff(capDelay time.Duration) BackoffStrategy
EqualJitterBackoff returns an exponential backoff strategy with equal jitter. Half of the delay is deterministic and the other half is randomized.
Formula:
cap = min(capDelay, baseDelay * 2^attempt) delay = cap/2 + random(0, cap/2)
Compared to Full Jitter, this guarantees a minimum delay while still spreading retries to reduce contention.
Example (base=5s, cap=40s):
5s + random(0–5s) 10s + random(0–10s) 20s + random(0–20s) 20s + random(0–20s)...
func ExponentialBackoff ¶
func ExponentialBackoff() BackoffStrategy
ExponentialBackoff doubles the delay with each attempt.
Formula:
delay = baseDelay * 2^attempt
Example (base=5s):
5s, 10s, 20s, 40s...
func FullJitterBackoff ¶ added in v1.2.0
func FullJitterBackoff(capDelay time.Duration) BackoffStrategy
FullJitterBackoff returns an exponential backoff strategy with full jitter. The exponential delay is used as a cap, and the actual delay is randomly chosen between 0 and that cap.
Formula:
cap = min(capDelay, baseDelay * 2^attempt) delay = random(0, cap)
This strategy spreads retries uniformly to reduce synchronized retry spikes.
Example (base=5s, cap=40s):
random(0–10s), random(0–20s), random(0–40s), random(0–40s)...
func LinearBackoff ¶
func LinearBackoff() BackoffStrategy
LinearBackoff increases delay linearly with each attempt.
Formula:
delay = baseDelay * attempt
Example (base=5s):
5s, 10s, 15s, 20s...
type BaseBackoff ¶ added in v1.2.0
type BaseBackoff struct {
// Attempt is the current retry attempt number.
// It is incremented each time GetNextDelay() is called.
Attempt int
// BaseDelay is the initial delay set by SetBaseDelay().
// This is typically the retryDelay configured on the worker.
BaseDelay time.Duration
// CapDelay is the maximum delay cap.
// Used by jitter strategies to limit maximum backoff time.
CapDelay time.Duration
// PreviousDelay is the delay returned by the last GetNextDelay() call.
// Used by decorrelated jitter to calculate the next delay.
PreviousDelay time.Duration
}
BaseBackoff provides common state for backoff strategies. Embed this struct in your custom backoff implementation.
func (*BaseBackoff) Reset ¶ added in v1.2.0
func (me *BaseBackoff) Reset()
func (*BaseBackoff) SetBaseDelay ¶ added in v1.2.0
func (me *BaseBackoff) SetBaseDelay(baseDelay time.Duration)
type Schedule ¶
type Schedule struct {
// contains filtered or unexported fields
}
Schedule defines when a worker should execute. Use DailyAt, WeeklyAt, or EveryNDays to create schedules. Modify with the In method to set timezones.
func DailyAt ¶
DailyAt creates a schedule that runs daily at the specified hour and minute. Hour must be between 0-23 and minute must be between 0-59.
Example:
workers.DailyAt(9, 0) // Daily at 9:00 AM workers.DailyAt(14, 30) // Daily at 2:30 PM
func EveryNDays ¶
EveryNDays creates a schedule that runs every N days at the specified time. The anchor date is set to today at midnight, so the pattern starts from today. For example, if created on Monday with n=2, it will run on Mon, Wed, Fri, Sun, etc. Hour must be between 0-23 and minute must be between 0-59.
Example:
workers.EveryNDays(2, 9, 0) // Every 2 days at 9:00 AM workers.EveryNDays(7, 14, 0) // Weekly at 2:00 PM - same as WeeklyAt(time.Now().Weekday(), hour, minute)
func WeeklyAt ¶
WeeklyAt creates a schedule that runs weekly on a specific day at the specified time. Weekday specifies which day of the week (time.Monday through time.Sunday). Hour must be between 0-23 and minute must be between 0-59.
Example:
workers.WeeklyAt(time.Monday, 9, 0) // Every Monday at 9:00 AM workers.WeeklyAt(time.Friday, 17, 30) // Every Friday at 5:30 PM
func (Schedule) In ¶
In sets the timezone for the schedule and returns the modified schedule. By default, schedules use the local timezone. Use this to specify a different timezone.
Example:
workers.DailyAt(9, 0).In(time.UTC) // Daily at 9:00 AM UTC
workers.WeeklyAt(time.Monday, 9, 0).In(time.FixedZone("EST", -5*60*60)) // Monday at 9:00 AM EST
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
Worker manages a background job with configurable execution intervals, retry logic, timeouts, and scheduling. Workers can run periodically or at specific times defined by schedules.
type WorkerJob ¶
WorkerJob defines the function signature for job implementations. The function receives a context for cancellation and timeout handling.
type WorkerManager ¶
type WorkerManager struct {
// contains filtered or unexported fields
}
WorkerManager coordinates multiple workers, managing their lifecycle from startup to graceful shutdown. It handles OS signals (SIGINT, SIGTERM) and recovers from worker panics to ensure system stability.
func NewWorkerManager ¶
func NewWorkerManager(options ...WorkerManagerOption) WorkerManager
NewWorkerManager creates a manager for coordinating workers. Configure with options before registering workers and calling Start.
func (*WorkerManager) RegisterWorker ¶
func (me *WorkerManager) RegisterWorker(worker Worker)
RegisterWorker adds a worker to the manager. The worker inherits the manager's logger if it doesn't have its own. Workers must be registered before Start is called.
func (WorkerManager) Start ¶
func (me WorkerManager) Start()
Start runs all registered workers and blocks until shutdown. Workers execute concurrently. The method blocks until SIGINT or SIGTERM is received, then waits for running jobs to complete before returning.
type WorkerManagerOption ¶
type WorkerManagerOption func(*WorkerManager)
WorkerManagerOption configures a WorkerManager. Use WithLogger to create options.
func WithLogger ¶
func WithLogger(logger *slog.Logger) WorkerManagerOption
WithLogger sets the default logger for the manager and all workers without their own logger.
Default: slog.Default()
type WorkerOption ¶
type WorkerOption func(*Worker)
WorkerOption configures a Worker. Use the With* functions to create options.
func WithBackoffStrategy ¶
func WithBackoffStrategy(strategy BackoffStrategy) WorkerOption
WithBackoffStrategy sets how the retry delay increases with each attempt. Use ConstantBackoff, LinearBackoff, ExponentialBackoff, or a custom function.
Default: ConstantBackoff
func WithItsOwnLogger ¶
func WithItsOwnLogger(logger *slog.Logger) WorkerOption
WithItsOwnLogger sets a worker-specific logger, overriding the WorkerManager's logger. The logger must not be nil.
Default: inherits from WorkerManager
func WithNRetries ¶
func WithNRetries(n int) WorkerOption
WithNRetries sets how many times to retry a failed job. Set to 0 to disable retries.
Default: 3 retries
func WithNRuns ¶
func WithNRuns(n int) WorkerOption
WithNRuns limits the total number of times a worker executes. After reaching the limit, the worker stops automatically. Must be greater than 0.
Default: unlimited runs
func WithRetryDelay ¶
func WithRetryDelay(delay time.Duration) WorkerOption
WithRetryDelay sets the initial delay between retry attempts. The actual delay may increase based on the backoff strategy. Must be greater than 0.
Default: 5 seconds
func WithSchedules ¶
func WithSchedules(schedules ...Schedule) WorkerOption
WithSchedules sets specific times for the worker to run, replacing tick-based execution. When schedules are configured, the worker runs only at the specified times. Multiple schedules can be combined to run at different times.
Example:
workers.WithSchedules(
workers.DailyAt(9, 0),
workers.WeeklyAt(time.Friday, 14, 30),
workers.EveryNDays(2, 2, 0),
)
func WithTick ¶
func WithTick(tick time.Duration) WorkerOption
WithTick sets the interval between job executions. Ignored when schedules are set. The tick must be greater than 0.
Default: 1 hour
func WithTimeout ¶
func WithTimeout(timeout time.Duration) WorkerOption
WithTimeout sets a maximum execution time for each job run. Jobs exceeding this duration are cancelled via context. Must be greater than 0.
Default: no timeout (jobs run indefinitely)