Go Worker
The flare-go module ships a background-job worker runtime in the /worker
subpackage. It turns the thin REST client into a full worker host: it announces
itself to Zeridion Flare, long-polls for jobs, dispatches each to a typed Go
handler with bounded concurrency, sends liveness heartbeats with progress,
honours server-side cancellation, reports the outcome, and drains in-flight jobs
gracefully on shutdown.
import (
flare "github.com/zeridion/flare-go"
"github.com/zeridion/flare-go/worker"
)
The worker lives in the same module as the client (no second dependency) and reuses the client you already build as its transport. Importing the worker is opt-in, so thin-client programs stay lean.
Requires: Go 1.22+
A complete worker
package main
import (
"context"
"time"
flare "github.com/zeridion/flare-go"
"github.com/zeridion/flare-go/worker"
)
type WelcomeEmail struct {
UserID string `json:"user_id"`
Email string `json:"email"`
}
func main() {
// Build the client the worker reuses as transport. Timeout: 0 keeps the
// long-poll from being aborted by a total request deadline.
client, _ := flare.NewClient(flare.WithHTTPClient(worker.NewPollHTTPClient()))
w := worker.NewWorker(client, worker.Options{
Queues: []string{"default", "maintenance"},
Concurrency: 5,
})
worker.Handle(w, "SendWelcomeEmail",
worker.JobConfig{Queue: "default", MaxAttempts: 5, Timeout: 60 * time.Second},
func(ctx context.Context, p WelcomeEmail, jc worker.JobContext) error {
jc.ReportProgress(0.5)
return sendEmail(ctx, p.Email)
})
worker.HandleRecurring(w, "NightlyCleanup",
worker.RecurringConfig{Cron: "0 3 * * *", Queue: "maintenance", Timezone: "UTC"},
func(ctx context.Context, jc worker.JobContext) error {
return cleanup(ctx)
})
// Blocks until SIGINT/SIGTERM, then drains and returns.
_ = w.Run(context.Background())
}
What the worker does for you
| Concern | Handled by the runtime |
|---|---|
| Identity | A unique worker id is generated per process and announced on startup. |
| Polling | Long-polls each configured queue and respects free-slot capacity. |
| Dispatch | Decodes the JSON payload into your handler's type and calls it. |
| Concurrency | Caps simultaneous jobs at Concurrency; reports remaining capacity so the server never overfills the worker. |
| Liveness | Sends a heartbeat on claim and on a steady cadence while a job runs. |
| Progress | Surfaces jc.ReportProgress(...) on the next heartbeat. |
| Cancellation | A server cancel directive cancels the job's context. |
| Timeouts | Each job runs under a per-job deadline. |
| Outcome | Reports success or a structured failure when the handler returns. |
| Shutdown | Stops polling on SIGINT/SIGTERM, waits for in-flight jobs, then returns. |
How handlers run
- A handler receives a
context.Contextthat is cancelled when the job times out, the host shuts down, or the server asks to cancel. Pass it to every blocking call you make. - Cancellation is cooperative: Go cannot safely stop a running goroutine, so a handler that never checks its context keeps running until the server reclaims the job. Always honour the context.
- Outcome reporting is best-effort, so a job can be delivered more than once
(for example, a crash after the work finished but before the outcome was
recorded). Handlers must be idempotent — guard side effects on
jc.JobID.
Pages
- Handlers — defining payload jobs with
Handle. - Recurring jobs — cron-scheduled jobs with
HandleRecurring. - Job context — metadata, cancellation, progress, logging.
- Configuration —
Optionsand per-handler config. - Heartbeats & progress — cadence, cancellation, progress reporting.
- Graceful shutdown — draining in-flight jobs.