grind/telemetry

The Sinal events Grind emits. Attach your handlers to these descriptors with sinal.observe or sinal.attach, as to any Sinal event.

sinal.observe(telemetry.acknowledged(), fn(measurements, metadata) {
  log(metadata.ref.correlation, job.state_name(metadata.committed_state))
})

Lifecycle events, named [grind, job, <event>], are emitted once a commit is proven: admitted, claimed, acknowledged, quarantined, resolved, cancellation_decided, released and contract_mismatch_recorded. Each carries a JobRef with the job’s correlation (the one given with job.with_correlation, or one Grind generated), and JobMeasurements with the node’s monotonic time. [grind, prune, completed] and [grind, prune, failed] report one pruner batch. Diagnostic events, named [grind, diagnostic, <event>], report renewal, acknowledgement, retry, checkout, claim-failure and capacity details; they do not imply a committed state.

Events go through the runtime’s bounded forwarder (1,024 in flight by default), so a slow handler never stalls a consumer. Delivery is best-effort: an event can arrive twice (a Reconciled after a Replied for the same command) or be dropped when the forwarder is full. Grind’s tables and receipts are the record; an event is a signal. The unions here may gain variants and the records may gain fields; read records by label.

Types

Native strings: replied, reconciled, rolled_back, unknown, fence_rejected, command_conflict, failed.

pub type AckOutcome {
  AckReplied
  AckReconciled
  AckRolledBack
  AckUnknown
  AckFenceRejected
  AckCommandConflict
  AckFailed
}

Constructors

  • AckReplied
  • AckReconciled
  • AckRolledBack
  • AckUnknown
  • AckFenceRejected
  • AckCommandConflict
  • AckFailed

[grind, job, acknowledged] metadata.

proposed is what the worker’s execution proposed; committed_state is what was actually durably committed, read from the acknowledgement’s own RETURNING/receipt — never from the proposal. They can differ: a concurrent cancellation overrides a proposed success or another non-uncertain proposal with a committed Cancelled. An explicit Uncertain proposal preserves its evidence and cancellation intent. Retry-budget exhaustion is decided by the worker’s own business retry policy before the acknowledgement ever runs — an exhausted retry is proposed as a business failure (worker.ExecutedBusinessFailure(.., BudgetExhausted), so proposed is already ProposedBusinessFailure), not as a Retryable proposal the acknowledgement later reinterprets. The acknowledgement’s own retryable commit path re-checks attempt_count < max_attempts as a defensive consistency guard, not a policy decision: if that guard fails for a genuinely proposed retry, the whole acknowledgement is rejected as stale (no commit, no observation) rather than silently committing some other outcome. available_at_unix_ms is only meaningful for a committed Retryable/Scheduled outcome (the job’s next eligibility time) and is None otherwise, including whenever the commit was proven by Reconciled receipt-read rather than by a fresh write — the acknowledgement receipt itself does not retain a re-derivable available_at. command_id is the stable acknowledgement fence for this attempt (grind/internal/attempt.acknowledgement_command_id), making it this event’s dedupe key across a Replied/Reconciled pair.

pub type AcknowledgedMetadata {
  AcknowledgedMetadata(
    ref: JobRef,
    attempt: AttemptRef,
    proposed: Proposed,
    committed_state: job.State,
    failure_cause: option.Option(job.TerminalCause),
    available_at_unix_ms: option.Option(Int),
    confirmation: Confirmation,
    command_id: String,
  )
}

Constructors

One returned ACK transaction/reconciliation path; duration includes reconciliation. Proposal validation before storage and contract-mismatch parking are excluded.

pub type AcknowledgementMeasurements {
  AcknowledgementMeasurements(count: Int, duration_us: Int)
}

Constructors

  • AcknowledgementMeasurements(count: Int, duration_us: Int)

Rolled back means a transaction result proved rollback. Unknown is not proof of either commit or rollback. Reconciled means a durable matching receipt.

pub type AcknowledgementMetadata {
  AcknowledgementMetadata(
    context: AttemptContext,
    command_id: String,
    outcome: AckOutcome,
  )
}

Constructors

[grind, job, admitted] metadata, shared by a plain submit/submit_at admission and a submit_unique admission decision (Inserted, Existing, or Rescheduled).

committed_state always comes from this call’s own committed transaction, never the request — the same discipline acknowledged’s metadata documents — but the exact source differs by admission shape: a plain submit reads it back from the insert’s own RETURNING; a unique Inserted decision is the computed initial state (queued/scheduled) bound as that same insert’s own parameter; a Rescheduled decision is the value that decision’s own UPDATE just wrote (always scheduled); an Existing decision is read from the locked candidate row inside the same admission transaction. available_at_unix_ms is Some only when committed_state is one where “next eligibility time” is a meaningful idea — Queued, Scheduled, or Retryable — and None otherwise, including for an Existing conflict whose candidate row is in some other eligible-for-the-policy state (Executing, Succeeded, and beyond, depending on the policy’s States group) where the column’s raw value is not a real next-run time. It is also None for a Reconciled decision (proven by a receipt read rather than a fresh write): the receipt does not retain a re-derivable available_at, the same limitation acknowledged documents for its own receipt-proven commits. submission_id is None for a plain submission and Some for a unique one — Grind’s own uniqueness identity, not a caller-assigned job id.

pub type AdmittedMetadata {
  AdmittedMetadata(
    ref: JobRef,
    committed_state: job.State,
    available_at_unix_ms: option.Option(Int),
    submission_id: option.Option(String),
    confirmation: Confirmation,
  )
}

Constructors

The job and attempt fence observed by one consumer incarnation.

pub type AttemptContext {
  AttemptContext(
    ref: JobRef,
    attempt: AttemptRef,
    consumer: ConsumerRef,
  )
}

Constructors

Native strings: handler_running, acknowledgement_pending.

pub type AttemptPhase {
  HandlerRunning
  AcknowledgementPending
}

Constructors

  • HandlerRunning
  • AcknowledgementPending

Shared attempt fencing fields carried by every event that is about one claimed attempt rather than the job as a whole (acknowledged, claimed, quarantined, released, contract_mismatch_recorded). attempt is the attempt number (grind_jobs.attempt_count at the time of the event), distinct from attempt_id (the durable per-attempt identity) and epoch (this job’s own attempt-fencing counter).

pub type AttemptRef {
  AttemptRef(attempt_id: Int, epoch: Int, attempt: Int)
}

Constructors

  • AttemptRef(attempt_id: Int, epoch: Int, attempt: Int)

Native strings: succeeded, failed.

pub type CallOutcome {
  CallSucceeded
  CallFailed
}

Constructors

  • CallSucceeded
  • CallFailed

[grind, job, cancellation_decided] metadata. outcome: CancellationDecidedWhileRunning can be delivered more than once for the same job: cancelling an already executing job whose cancellation is already requested is idempotent at the storage layer (postgres’s cancel_executing re-affirms the existing request rather than rejecting the call), so a caller that retries a cancellation request observes this event again rather than a distinct no-op outcome.

pub type CancellationMetadata {
  CancellationMetadata(
    ref: JobRef,
    previous_state: job.State,
    outcome: CancellationOutcome,
  )
}

Constructors

Cancellation of queued or executing work. AlreadyUncertain records intent without changing the disposition and emits no event. AlreadyCancelled and AlreadyFinished are read-only and also emit no event.

pub type CancellationOutcome {
  CancellationDecidedBeforeRun
  CancellationDecidedWhileRunning
}

Constructors

  • CancellationDecidedBeforeRun
  • CancellationDecidedWhileRunning

One local ledger snapshot. Active = running + ack_pending; available = maximum - active. Pending acknowledgements continue to occupy capacity.

pub type CapacityMeasurements {
  CapacityMeasurements(
    maximum: Int,
    active: Int,
    running: Int,
    ack_pending: Int,
    available: Int,
  )
}

Constructors

  • CapacityMeasurements(
      maximum: Int,
      active: Int,
      running: Int,
      ack_pending: Int,
      available: Int,
    )

Observed consumer draining state; this is not a global queue-depth sample.

pub type CapacityMetadata {
  CapacityMetadata(queue: QueueRef, draining: Bool)
}

Constructors

  • CapacityMetadata(queue: QueueRef, draining: Bool)

Actual checkout wait and full wrapper duration in microseconds. Native wait key is checkout_wait_us. Candidate count includes stale checkout candidates; probes, SQL and cleanup are outside wait but inside total duration.

pub type CheckoutMeasurements {
  CheckoutMeasurements(
    count: Int,
    wait_us: Int,
    call_duration_us: Int,
    candidates: Int,
  )
}

Constructors

  • CheckoutMeasurements(
      count: Int,
      wait_us: Int,
      call_duration_us: Int,
      candidates: Int,
    )

A completed selected queue-storage call, after cleanup. Nested calls on an already checked-out connection do not emit another checkout sample.

pub type CheckoutMetadata {
  CheckoutMetadata(
    queue: QueueRef,
    operation: Operation,
    pool: PoolRole,
    checkout: CheckoutOutcome,
    returned: CallOutcome,
  )
}

Constructors

Native strings: acquired, unavailable.

pub type CheckoutOutcome {
  CheckoutAcquired
  CheckoutUnavailable
}

Constructors

  • CheckoutAcquired
  • CheckoutUnavailable

One failed quarantine scan or candidate claim, timed in local microseconds.

pub type ClaimFailedMeasurements {
  ClaimFailedMeasurements(count: Int, duration_us: Int)
}

Constructors

  • ClaimFailedMeasurements(count: Int, duration_us: Int)

Sanitized failure classification before a job was obtained; no job identity or underlying exception message is invented.

pub type ClaimFailedMetadata {
  ClaimFailedMetadata(
    queue: QueueRef,
    stage: Operation,
    failure: FailureKind,
  )
}

Constructors

[grind, job, claimed] metadata. The claim itself autocommits as a single fenced UPDATE ... RETURNING, so a returned row is already the proof of commit — there is no separate transaction reply to distinguish a Replied/Reconciled pair for this event. previous_state is the state the row held immediately before this claim (queued, scheduled, or retryable), read from the same RETURNING.

pub type ClaimedMetadata {
  ClaimedMetadata(
    ref: JobRef,
    attempt: AttemptRef,
    previous_state: job.State,
  )
}

Constructors

How a Replied/Reconciled observation is emitted here: Replied is this call’s own commit reply, received directly, causing a fresh durable write. Reconciled is a commit proven by reading back an existing durable receipt instead — the exact same command was already durably applied, either by an earlier attempt of this same caller whose reply was lost, or by a concurrent retry that raced it. Both are genuine proof of a commit; Reconciled never means “assumed” or “probably”.

pub type Confirmation {
  Replied
  Reconciled
}

Constructors

  • Replied
  • Reconciled

Node and consumer-incarnation identity; both are native strings, never dynamic atoms.

pub type ConsumerRef {
  ConsumerRef(node: String, consumer: String)
}

Constructors

  • ConsumerRef(node: String, consumer: String)

[grind, job, contract_mismatch_recorded] metadata: a claimed attempt parked in the terminal, nonclaimable contract_mismatch state (not returned to queued — contrast released above) because the registered worker’s codec contract no longer matches what was persisted when the job was admitted (a deploy changed a codec version without a matching worker/version bump). expected_version is what was stored; actual_version is what the currently registered worker declares.

pub type ContractMismatchMetadata {
  ContractMismatchMetadata(
    ref: JobRef,
    attempt: AttemptRef,
    kind: job.CodecKind,
    expected_version: String,
    actual_version: String,
  )
}

Constructors

Native strings: timed_out, connection_unavailable, rejected, unexpected_result.

pub type FailureKind {
  TimedOut
  ConnectionUnavailable
  Rejected
  UnexpectedResult
}

Constructors

  • TimedOut
  • ConnectionUnavailable
  • Rejected
  • UnexpectedResult

Shared identity carried by every [grind, job, *] event: which job, queue, and worker contract the event is about. Reused as an embedded field rather than re-declared per event, so the underlying sinal/fields codec for it (job_ref_fields, defined once further down, above every metadata field builder that embeds it) is also built exactly once. The measurements of every [grind, job, *] event: count is always 1, and monotonic_ms is the emitting node’s monotonic clock when the event was emitted, so events from one node order causally even when they are delivered through different forwarders.

pub type JobMeasurements {
  JobMeasurements(count: Int, monotonic_ms: Int)
}

Constructors

  • JobMeasurements(count: Int, monotonic_ms: Int)
pub type JobRef {
  JobRef(
    job_id: Int,
    queue: String,
    worker_id: String,
    worker_version: String,
    correlation: correlation.Correlation,
  )
}

Constructors

  • JobRef(
      job_id: Int,
      queue: String,
      worker_id: String,
      worker_version: String,
      correlation: correlation.Correlation,
    )

Native strings: quarantine_scan, claim_candidate, lease_renewal, acknowledge, reconcile_acknowledgement.

pub type Operation {
  QuarantineScan
  ClaimCandidate
  LeaseRenewal
  Acknowledge
  ReconcileAcknowledgement
}

Constructors

  • QuarantineScan
  • ClaimCandidate
  • LeaseRenewal
  • Acknowledge
  • ReconcileAcknowledgement

Native strings: main, reserved.

pub type PoolRole {
  MainPool
  ReservedPool
}

Constructors

  • MainPool
  • ReservedPool

The closed set of dispositions a worker can propose for one attempt, mirroring grind/worker.Execution’s shape without depending on it — this module only needs the disposition kind, not the worker’s typed payload.

pub type Proposed {
  ProposedSuccess
  ProposedBusinessFailure
  ProposedRetryable
  ProposedRuntimeFailed
  ProposedSnoozed
  ProposedDiscarded
  ProposedCancelled
  ProposedUncertain
}

Constructors

  • ProposedSuccess
  • ProposedBusinessFailure
  • ProposedRetryable
  • ProposedRuntimeFailed
  • ProposedSnoozed
  • ProposedDiscarded
  • ProposedCancelled
  • ProposedUncertain

[grind, prune, completed] measurements: how many rows one postgres.prune_finished call actually deleted from grind_jobs — mirroring postgres.PruneReport’s own shape (each deleted job’s own acknowledgement/uniqueness-submission/resolution receipts cascade with it, via grind_v12’s own ON DELETE CASCADE foreign keys, and are not separately counted). Unlike every other event in this module, this one is not about a single job: it is one aggregate per call, the same shape Oban’s own [:oban, :plugin] pruner span reports a single pruned_count for.

pub type PruneCompletedMeasurements {
  PruneCompletedMeasurements(jobs: Int)
}

Constructors

  • PruneCompletedMeasurements(jobs: Int)

[grind, prune, completed] metadata: the retention window and batch size this exact call was given, so a handler can tell a small exhausted-limit batch (measurements.jobs == limit, worth looping again immediately) from a genuinely empty one apart from the count alone.

pub type PruneCompletedMetadata {
  PruneCompletedMetadata(older_than_ms: Int, limit: Int)
}

Constructors

  • PruneCompletedMetadata(older_than_ms: Int, limit: Int)

[grind, prune, failed] measurements: always count: 1, the same “this happened once” convention every [grind, job, *] event’s own count field already uses — there is no meaningful row count for a call that never committed cleanly.

pub type PruneFailedMeasurements {
  PruneFailedMeasurements(count: Int)
}

Constructors

  • PruneFailedMeasurements(count: Int)

[grind, prune, failed] metadata: the retention window and batch size the failed call was given, plus its own coarse failure kind.

pub type PruneFailedMetadata {
  PruneFailedMetadata(
    older_than_ms: Int,
    limit: Int,
    kind: PruneFailureKind,
  )
}

Constructors

  • PruneFailedMetadata(
      older_than_ms: Int,
      limit: Int,
      kind: PruneFailureKind,
    )

Coarsely classifies why a grind/pruner tick’s own prune_finished call failed, from the pog.QueryError it returned — narrow enough to be useful in a handler without exposing pog’s own type as part of Grind’s observation surface.

pub type PruneFailureKind {
  PruneReplyLost
  PruneResultUndecodable
  PruneRejected
  PruneNotAttempted
}

Constructors

  • PruneReplyLost

    The reply was lost after the statement may have already reached PostgreSQL and committed (pog.QueryTimeout) — rows may have been deleted despite this being reported as a failure.

  • PruneResultUndecodable

    The statement ran, returned rows, and committed, but they could not be decoded (pog.UnexpectedResultType) — the delete itself already happened; only reading its own RETURNING back failed.

  • PruneRejected

    A real PostgreSQL-side rejection before anything could commit (pog.ConstraintViolated/pog.PostgresqlError) — nothing was deleted.

  • PruneNotAttempted

    The call never reached PostgreSQL at all (pog.ConnectionUnavailable/ pog.UnexpectedArgumentCount/pog.UnexpectedArgumentType) — nothing was attempted.

[grind, job, quarantined] metadata: one abandoned attempt (an expired lease found by the claim-time quarantine scan) moved to uncertain. cancellation_was_requested distinguishes an abandoned attempt that also had a pending cancellation request from an ordinary one — both still require audited reconciliation, but the failure description differs (see postgres’s quarantine scan). attempt names the attempt that expired, as the row held it before the scan. A replay (replayed: True) refunds that attempt’s number, like a snooze, so the redelivery’s claimed event reports the same attempt under a new attempt_id and epoch.

pub type QuarantinedMetadata {
  QuarantinedMetadata(
    ref: JobRef,
    attempt: AttemptRef,
    cancellation_was_requested: Bool,
    replayed: Bool,
  )
}

Constructors

  • QuarantinedMetadata(
      ref: JobRef,
      attempt: AttemptRef,
      cancellation_was_requested: Bool,
      replayed: Bool,
    )

    Arguments

    replayed

    The worker’s ReplayAfterLeaseExpiry policy queued the job again instead of holding it uncertain.

One local consumer of a queue, not a global queue-depth identity.

pub type QueueRef {
  QueueRef(queue: String, consumer: ConsumerRef)
}

Constructors

[grind, job, released] metadata: a claimed attempt refunded before its worker ever ran (the temporary worker child failed to start). restored_state is the state the row is returned to — the same state it held before this claim.

pub type ReleasedMetadata {
  ReleasedMetadata(
    ref: JobRef,
    attempt: AttemptRef,
    restored_state: job.State,
  )
}

Constructors

One renewal outcome. Duration is the shared batch storage-call duration in local microseconds, repeated per attempt; summing it overcounts database time. Optional signed lease headroom is measured during database evaluation, not delivery.

pub type RenewalMeasurements {
  RenewalMeasurements(
    count: Int,
    duration_us: Int,
    remaining_lease_ms: option.Option(Int),
  )
}

Constructors

  • RenewalMeasurements(
      count: Int,
      duration_us: Int,
      remaining_lease_ms: option.Option(Int),
    )

A skipped lock does not identify its owner. A missing live fence may mean completion, cancellation, expiry or changed ownership. Budget exhaustion is local and proves neither expiry nor quarantine.

pub type RenewalMetadata {
  RenewalMetadata(
    context: AttemptContext,
    phase: AttemptPhase,
    outcome: RenewalOutcome,
  )
}

Constructors

Native strings: renewed, skipped_locked, live_fence_unavailable, storage_failed, completion_budget_exhausted.

pub type RenewalOutcome {
  Renewed
  SkippedLocked
  LiveFenceUnavailable
  StorageFailed
  CompletionBudgetExhausted
}

Constructors

  • Renewed
  • SkippedLocked
  • LiveFenceUnavailable
  • StorageFailed
  • CompletionBudgetExhausted

The closed set of decisions an operator can apply to an uncertain job, mirroring grind/postgres.Resolution’s shape without depending on it.

pub type ResolutionDecision {
  DecisionConfirmSuccess
  DecisionConfirmBusinessFailure
  DecisionAuthorizeReplay
}

Constructors

  • DecisionConfirmSuccess
  • DecisionConfirmBusinessFailure
  • DecisionAuthorizeReplay

[grind, job, resolved] metadata: an audited operator decision applied to an uncertain job. confirmation is Replied when this call’s own transaction committed the decision, Reconciled when an identical decision was already durably applied by an earlier attempt of this same resolution_id (postgres.ResolutionAlreadyApplied) — the resolution analogue of acknowledged’s duplicate-command reconciliation. committed_state comes from that same proven outcome, never the request.

pub type ResolvedMetadata {
  ResolvedMetadata(
    ref: JobRef,
    decision: ResolutionDecision,
    committed_state: job.State,
    resolution_id: String,
    resolved_by: String,
    confirmation: Confirmation,
  )
}

Constructors

One scheduled ACK retry. The retry number is local to acknowledgement, not the job attempt number. Pending duration is local monotonic microseconds.

pub type RetryMeasurements {
  RetryMeasurements(
    count: Int,
    retry_number: Int,
    delay_ms: Int,
    pending_duration_us: Int,
  )
}

Constructors

  • RetryMeasurements(
      count: Int,
      retry_number: Int,
      delay_ms: Int,
      pending_duration_us: Int,
    )

Scheduling repeats acknowledgement/reconciliation, never the handler.

pub type RetryMetadata {
  RetryMetadata(
    context: AttemptContext,
    command_id: String,
    reason: RetryReason,
  )
}

Constructors

Native strings: after_failure, after_unknown.

pub type RetryReason {
  RetryAfterFailure
  RetryAfterUnknown
}

Constructors

  • RetryAfterFailure
  • RetryAfterUnknown

Values

pub fn acknowledged() -> sinal.Event(
  JobMeasurements,
  AcknowledgedMetadata,
)

The [grind, job, acknowledged] event descriptor: one committed disposition for one claimed attempt. Emitted by grind/postgres from its own sinal/forwarder.Forwarder, strictly after that disposition is proven committed (see the module documentation above).

pub fn acknowledgement() -> sinal.Event(
  AcknowledgementMeasurements,
  AcknowledgementMetadata,
)

[grind, diagnostic, acknowledgement].

pub fn acknowledgement_retry() -> sinal.Event(
  RetryMeasurements,
  RetryMetadata,
)

[grind, diagnostic, acknowledgement_retry].

pub fn admitted() -> sinal.Event(
  JobMeasurements,
  AdmittedMetadata,
)

The [grind, job, admitted] event descriptor: one committed admission decision, either a plain submit/submit_at or a submit_unique outcome (Inserted, Existing, or Rescheduled). Emitted by grind/postgres strictly after that decision is proven committed — see AdmittedMetadata.

pub fn cancellation_decided() -> sinal.Event(
  JobMeasurements,
  CancellationMetadata,
)

The [grind, job, cancellation_decided] event descriptor: a cancellation request that changed something durable (CancellationDecidedBeforeRun or CancellationDecidedWhileRunning). AlreadyUncertain records intent without a disposition change and emits no event. AlreadyCancelled and AlreadyFinished are read-only and also emit no event — see CancellationMetadata.

pub fn capacity() -> sinal.Event(
  CapacityMeasurements,
  CapacityMetadata,
)

[grind, diagnostic, capacity].

pub fn checkout() -> sinal.Event(
  CheckoutMeasurements,
  CheckoutMetadata,
)

[grind, diagnostic, checkout].

pub fn claim_failed() -> sinal.Event(
  ClaimFailedMeasurements,
  ClaimFailedMetadata,
)

[grind, diagnostic, claim_failed].

pub fn claimed() -> sinal.Event(JobMeasurements, ClaimedMetadata)

The [grind, job, claimed] event descriptor: one job atomically claimed for execution. Emitted strictly after the claim’s own fenced UPDATE ... RETURNING returns a row — see ClaimedMetadata.

pub fn contract_mismatch_recorded() -> sinal.Event(
  JobMeasurements,
  ContractMismatchMetadata,
)

The [grind, job, contract_mismatch_recorded] event descriptor: a claimed attempt parked in the terminal, nonclaimable contract_mismatch state because a registered worker’s codec contract no longer matches what was persisted at admission. Emitted strictly after the mismatch’s own fenced UPDATE ... RETURNING returns a row.

pub fn prune_completed() -> sinal.Event(
  PruneCompletedMeasurements,
  PruneCompletedMetadata,
)

The [grind, prune, completed] event descriptor: one aggregate per postgres.prune_finished call, emitted strictly after that call’s own autocommitted delete has already returned its counts — never one event per deleted job. Unlike every [grind, job, *] event above, this is not scoped to a single job at all, so it lives under its own [grind, prune, ...] prefix rather than reusing job_event_name.

pub fn prune_failed() -> sinal.Event(
  PruneFailedMeasurements,
  PruneFailedMetadata,
)

The [grind, prune, failed] event descriptor: grind/pruner’s own tick emits this when the prune_finished call it drives returns an Error, since a supervised background pruner has no caller to return the PruneError to directly. postgres.prune_finished itself never emits this — see its own doc comment.

pub fn quarantined() -> sinal.Event(
  JobMeasurements,
  QuarantinedMetadata,
)

The [grind, job, quarantined] event descriptor: one abandoned attempt (an expired lease) moved to uncertain by the claim-time quarantine scan. Emitted once per row the scan’s RETURNING reports as quarantined.

pub fn released() -> sinal.Event(
  JobMeasurements,
  ReleasedMetadata,
)

The [grind, job, released] event descriptor: a claimed attempt refunded before its worker ever ran. Emitted strictly after the release’s own fenced UPDATE ... RETURNING returns a row.

pub fn renewal() -> sinal.Event(
  RenewalMeasurements,
  RenewalMetadata,
)

[grind, diagnostic, renewal].

pub fn resolved() -> sinal.Event(
  JobMeasurements,
  ResolvedMetadata,
)

The [grind, job, resolved] event descriptor: one audited operator decision committed against an uncertain job. Emitted strictly after that decision is proven committed — see ResolvedMetadata.

✨ Search Document