CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/golang-github-com-go-co-op-gocron-v2

A Golang job scheduling library that lets you run Go functions at pre-determined intervals using cron expressions, fixed durations, daily, weekly, monthly, or one-time schedules with support for distributed deployments.

Overview
Eval results
Files

distributed.mddocs/guides/

Distributed Deployment

Guide to running gocron across multiple instances.

Overview

Gocron supports two distributed patterns:

  1. Leader Election: All-or-nothing scheduling (one instance schedules all jobs)
  2. Distributed Locking: Per-job locking (all instances schedule, one executes per job)

Leader Election

Simple pattern where one instance becomes leader and schedules all jobs.

s, _ := gocron.NewScheduler(
    gocron.WithDistributedElector(myElector),
)

// Only leader schedules jobs
j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(doWork),
)

s.Start()

Characteristics:

  • Simple to implement
  • All jobs on one instance
  • Fast leader failover
  • No per-job coordination

Detailed guide: Leader Election

Distributed Locking

Per-job locking pattern where all instances schedule but only one executes each job.

s, _ := gocron.NewScheduler(
    gocron.WithDistributedLocker(myLocker),
)

// All instances schedule, one executes
j, _ := s.NewJob(
    gocron.DurationJob(time.Minute),
    gocron.NewTask(doWork),
)

s.Start()

Characteristics:

  • Load distribution
  • Per-job coordination
  • Requires lock implementation
  • Higher overhead

Detailed guide: Distributed Locking

Choosing a Pattern

FactorLeader ElectionDistributed Locking
ComplexityLowMedium
Load distributionSingle instanceAll instances
FailoverInstance-levelJob-level
CoordinationOnce (leader)Per job execution
Use whenSimple deploymentsLoad distribution needed

Implementation Interfaces

Elector Interface

type Elector interface {
    IsLeader(context.Context) error
}

Return nil if instance is leader, error otherwise.

Locker Interface

type Locker interface {
    Lock(context.Context, string) (Lock, error)
}

type Lock interface {
    Unlock(context.Context) error
}

Acquire/release locks per job.

Clock Synchronization

Distributed instances should have synchronized clocks for consistent scheduling.

Detailed guide: Clock Synchronization

Testing

Test distributed behavior in development environments.

Detailed guide: Testing Distributed

Example Implementations

Redis Leader Election

type redisElector struct {
    client *redis.Client
    key    string
    id     string
}

func (e *redisElector) IsLeader(ctx context.Context) error {
    ok, err := e.client.SetNX(ctx, e.key, e.id, 10*time.Second).Result()
    if err != nil {
        return err
    }
    if !ok {
        return errors.New("not leader")
    }
    return nil
}

Redis Distributed Locking

type redisLocker struct {
    client *redis.Client
}

func (l *redisLocker) Lock(ctx context.Context, key string) (gocron.Lock, error) {
    ok, err := l.client.SetNX(ctx, key, "1", time.Minute).Result()
    if err != nil {
        return nil, err
    }
    if !ok {
        return nil, errors.New("lock held")
    }
    return &redisLock{client: l.client, key: key}, nil
}

See Also

Install with Tessl CLI

npx tessl i tessl/golang-github-com-go-co-op-gocron-v2

docs

index.md

tile.json