SQLStreams

the messaging platform that is just Postgres

You last visited on 9999-99-99 Show what's new since then

Scheduler

Edit this page
Posted: 2026-09-12 · Report this thread
brandon Site Admin brandon profile Posts: 677

client.Scheduler(name) names a schedule on the client: no I/O, no failure. Register declares it against a target stream, a cron expression, and the payload it produces, and returns a SchedulerInstance[T]. The schedule is the one handle outside the typed tree: only Register knows a payload type, and Go infers it from the payload argument.

nightly, err := client.Scheduler("nightly-report").Register(ctx,
	"reports.requested", "0 3 * * *",
	&ReportRequestedV1{Kind: "nightly"}, &sqlstreams.SchedulerConfig{
		Timeout:     time.Minute,
		Concurrency: sqlstreams.ConcurrencyExclusive,
	})
if err != nil {
	return err
}

return nightly.Schedule(ctx)

Verbs

On the handle:

verbreturnsnotes
Register(ctx, streamName, cron, payload, cfg)*SchedulerInstance[T]newest declaration wins, and a differing one logs SQL0062; nil cfg is the defaults; ErrStreamNotFound
Get(ctx)*Schedulethe comma-ok read: (nil, nil) when not registered
Suspend(ctx)errorstops producing until unsuspended; ErrScheduleNotFound
Unsuspend(ctx)errorresumes at the next scheduled time; a run that came due while suspended is dropped, not produced late
Run(ctx, options)*ProduceResult[ScheduleStoredMessage]produces the stored message now, outside the expression; nil options is the defaults
Status(ctx)[]*ScheduleConsumerGroupSummarythe schedule’s messages rolled up per consumer group
Messages(ctx, limit)[]*ScheduleMessageStatusproduced messages newest first, each with its outcome: pending, deferred, succeeded, failed, superseded
Destroy(ctx)errordeletes the schedule; ErrDestroyDisabled unless ClientConfig.AllowDestroy

On the instance:

verbreturnsnotes
Schedule(ctx)errorblocks running the system manager, whose schedule producer produces every registered schedule; cancel ctx to stop and get nil back

CLI

sqlstreams scheduler get nightly-report --output json returns the schedule object directly, with timeout as a duration string, or null with exit 1 when absent. scheduler status and scheduler messages return arrays.

sqlstreams scheduler run nightly-report --concurrency exclusive runs early without overlapping a request already running. The flag defaults to parallel. Schedules compact their messages, so ordered concurrency is rejected.

Config

SchedulerConfig

fielddefaultwhat it decides
Timeout30show long one produced message’s delivery may run
ConcurrencyConcurrencyParallelwhether a run may overlap a previous one still running; ConcurrencyExclusive waits
Metadatanil (stored as {})opaque JSON on the row, shown by sqlstreams scheduler get; not part of the produced message

ScheduleRunOptions

fielddefaultwhat it decides
ConcurrencyConcurrencyParallelthe early run’s own policy; ConcurrencyExclusive runs early without overlapping a request already running

Gotchas

  • Schedule runs every worker in the fleet, not just this schedule, the way Consume does. A program that registers a schedule and exits has registered one that never fires until something in the deployment runs a manager, and any consumer does (schedules).
  • The schedule name lives on the handle, so it cannot trade places with the target stream in Register. Every verb but Register is keyed by the name alone.
  • schedule_config keeps no _config_log trail: a redeclared expression leaves no history.