Dispatch

Jobs

Typed job definitions, the registry, state machine, retries, and backoff.

Jobs are the fundamental unit of work in Dispatch. A job definition is a typed Go function that processes a JSON payload.

Defining a job

import "github.com/xraph/dispatch/job"

type EmailInput struct {
    To      string `json:"to"`
    Subject string `json:"subject"`
    Body    string `json:"body"`
}

var SendEmail = job.NewDefinition("send_email",
    func(ctx context.Context, input EmailInput) error {
        return mailer.Send(input.To, input.Subject, input.Body)
    },
)

The generic type parameter T must be JSON-serializable. NewDefinition returns a *Definition[T] that carries both the name and the handler.

Registering a job

Use engine.Register at startup:

engine.Register(eng, SendEmail)
engine.Register(eng, GenerateReport)
engine.Register(eng, ProcessPayment)

Internally, Register calls job.RegisterDefinition on the engine's *job.Registry, converting the typed handler to a type-erased HandlerFunc.

Enqueueing a job

engine.Enqueue(ctx, eng, SendEmail, EmailInput{
    To:      "user@example.com",
    Subject: "Welcome!",
})

Additional enqueue options:

// Schedule for the future
engine.EnqueueAt(ctx, eng, SendEmail, input, time.Now().Add(10*time.Minute))

// Set priority (higher = dequeued first)
engine.EnqueueWithPriority(ctx, eng, SendEmail, input, 10)

// Target a specific queue
engine.EnqueueOnQueue(ctx, eng, SendEmail, input, "critical")

State machine

A job progresses through these states:

pending → running → completed
pending → running → retrying → pending → running → ...
pending → running → failed
pending → running → failed → dlq
pending → cancelled
StateMeaning
pendingWaiting to be picked up
runningCurrently executing
completedFinished successfully
retryingFailed but scheduled for retry
failedFailed terminally (no retries remain)
cancelledExplicitly cancelled

Retries and backoff

Configure retries on the job definition:

var SendEmail = job.NewDefinition("send_email",
    handler,
    job.WithMaxRetries(5),
)

Configure the backoff strategy on the engine:

eng := engine.Build(d,
    engine.WithBackoff(backoff.Exponential(
        backoff.WithBase(5*time.Second),
        backoff.WithMax(2*time.Hour),
    )),
)

After MaxRetries is exhausted, the job is moved to the DLQ.

Job timeout

Set a per-job execution deadline:

var SendEmail = job.NewDefinition("send_email",
    handler,
    job.WithTimeout(30*time.Second),
)

The middleware.Timeout() middleware enforces this via context cancellation.

On this page