grind/job
Builds the jobs grind.submit admits, and names the states a stored job
moves through.
import gleam/time/duration
import grind
import grind/job
let request =
job.new(receipt_worker(), order.id)
|> job.with_id("receipt:" <> order.id)
|> job.after(duration.minutes(5))
grind.submit(jobs, request)
A job built with new runs now, in its worker’s queue, with its
worker’s attempt limit and a correlation Grind generates. Every submit
records a receipt under the job’s id (with_id) or under an id Grind
generates, so a submit whose reply was lost is reconcilable. Give a job
your own id when the submit may be retried: resubmitting the same job
under the same id returns the original admission instead of a second
job.
State may gain variants; branch on is_finished or state_name
where a new state should not break your code.
Types
Which of a worker’s codecs a contract check concerns.
pub type CodecKind {
InputCodec
OutputCodec
ErrorCodec
}
Constructors
-
InputCodec -
OutputCodec -
ErrorCodec
A job to submit. Build it with new and the with_*, at, after and
unique setters.
pub type Job(input, output, error) =
@internal Job(input, output, error)
A typed reference to a stored job. It keeps the worker’s codecs, so
grind.state, grind.outcome and grind.await return typed values.
Store id(handle) to find the job again with grind.bind.
pub type JobHandle(input, output, error) =
@internal JobHandle(input, output, error)
The stored lifecycle states.
pub type State {
Queued
Scheduled
Retryable
Executing
Succeeded
BusinessFailed
RuntimeFailed
ContractMismatch
Uncertain
Discarded
Cancelled
}
Constructors
-
QueuedWaiting to run.
-
ScheduledWaiting for its scheduled time, or snoozed.
-
RetryableFailed and waiting to retry.
-
ExecutingClaimed by a consumer and running.
-
Succeeded -
BusinessFailedFailed terminally: attempts ran out, the retry policy declined, or the snooze limit was reached.
-
RuntimeFailedThe input could not be decoded, or the handler’s output or error was rejected by its codec or exceeded the payload limit.
-
ContractMismatchThe stored codec versions no longer match the registered worker.
-
UncertainThe attempt’s effect is unknown; waits for an audited resolution.
-
Discarded -
Cancelled
Why a failure is terminal.
pub type TerminalCause {
BudgetExhausted
RetryDeclined
SnoozeLimitReached
}
Constructors
-
BudgetExhaustedThe last attempt failed.
-
RetryDeclinedThe worker’s retry policy declined to retry.
-
SnoozeLimitReachedThe job snoozed more often than its worker allows.
Values
pub fn after(
job: Job(input, output, error),
delay: duration.Duration,
) -> Job(input, output, error)
Runs the job delay after it is admitted, measured on the database’s
clock. A resubmit under the same id converges on the first admission.
pub fn at(
job: Job(input, output, error),
at: timestamp.Timestamp,
) -> Job(input, output, error)
Runs the job no earlier than at. A time in the past runs it now.
pub fn is_finished(state: State) -> Bool
Whether the state is terminal. Uncertain is not: it waits for an
audited resolution, which may replay the job.
pub fn new(
worker: worker.Worker(input, output, error),
input: input,
) -> Job(input, output, error)
A job for worker with input, to run now in the worker’s queue.
pub fn queue(handle: JobHandle(input, output, error)) -> String
The queue the stored job runs in.
pub fn state_from_name(name: String) -> Result(State, Nil)
The state with this stored name.
pub fn state_name(state: State) -> String
The state’s stored name, such as "business_failed", for logs, metrics
and records.
pub fn terminal_cause_name(cause: TerminalCause) -> String
The cause’s stored name, such as "snooze_limit_reached".
pub fn unique(
job: Job(input, output, error),
policy: unique.Policy(input),
) -> Job(input, output, error)
Admits the job only if no job occupies its uniqueness key.
pub fn with_correlation(
job: Job(input, output, error),
correlation: correlation.Correlation,
) -> Job(input, output, error)
The correlation the job carries into its worker’s context and every event Grind emits about it. Without one, Grind generates one at submit.
pub fn with_id(
job: Job(input, output, error),
id: String,
) -> Job(input, output, error)
The job’s idempotency key. A second submit with the same id and the same
job returns the first admission; with a different job it fails with
grind.IdConflict. An empty id fails at submit with grind.EmptyJobId.
The key lasts as long as the job is stored.
pub fn with_max_attempts(
job: Job(input, output, error),
max_attempts: Int,
) -> Job(input, output, error)
This one job’s attempt limit instead of its worker’s. Panics below 1.