Skip to content

Jobs

Jobs provide background processing for events in Snaapi. Define jobs that match event patterns and execute registered processor functions, with automatic retry, concurrency locking, and full execution tracking.

Job Definitions

A job connects an event pattern to a processor function:

Field Type Description
id string UUID identifier
name string Display name
description string Human-readable description
eventPattern string Pattern to match events (e.g., posts.*, *)
processorName string Name of the registered processor
enabled boolean Whether the job is active
retryConfig RetryConfig | null Custom retry configuration
createdAt string ISO 8601 creation timestamp
updatedAt string ISO 8601 last-updated timestamp

Processors

A job processor is a function that handles matched events. Processors are registered by name and invoked when a matching event occurs.

Processor Signature

type JobProcessor = (
  event: Event,
  execution: JobExecution,
) => Promise<Record<string, unknown> | void>;

Processor Definition

interface JobProcessorDefinition {
  name: string;
  description: string;
  processor: JobProcessor;
}

Built-in Processors

Processor Name Description
webhook-delivery Delivers events to registered webhook endpoints

Execution Tracking

When an event matches a job's event pattern, a JobExecution record is created to track processing:

Field Type Description
id string Execution UUID
jobId string Parent job ID
eventId string Associated event ID
status string pending, running, completed, or failed
attemptNumber number Current attempt number
startedAt string | null Timestamp when execution started
completedAt string | null Timestamp when execution completed
error string | null Error message (if failed)
result Record<string, unknown> | null Processor return value
nextRetryAt string | null Scheduled time for next retry
locked string | null Timestamp-based concurrency lock
createdAt string ISO 8601 creation timestamp

Execution Status Transitions

pending → running → completed
                  → failed → pending (retry)

Retry Configuration

Jobs use exponential backoff for failed executions. Defaults are used when no custom retryConfig is provided:

Property Default
maxAttempts 3
initialDelayMs 1,000 ms
backoffMultiplier 2
maxDelayMs 60,000 ms

The delay between retries is calculated as:

delay = min(initialDelayMs * backoffMultiplier ^ (attempt - 1), maxDelayMs)

On failure, the execution remains in pending status with a calculated nextRetryAt timestamp until all retry attempts are exhausted, at which point it transitions to failed.

Concurrency Locking

Job executions use timestamp-based locking to prevent concurrent processing of the same execution:

  • The locked field stores a timestamp when an execution is being processed
  • Only one worker can acquire the lock at a time
  • KV store uses atomic versionstamp checks for lock acquisition
  • Locks prevent duplicate processing in distributed environments

Invocation Records

Each individual attempt of a job execution is tracked as an ExecutionInvocation:

Field Type Description
id string Invocation UUID
executionId string Parent execution ID
attemptNumber number Attempt number for this invocation
startedAt string Timestamp when attempt started
completedAt string | null Timestamp when attempt completed
status string running, success, or failed
error string | null Error message (if failed)
result Record<string, unknown> | null Processor return value
createdAt string ISO 8601 creation timestamp

Database Tables

Table Description
_jobs Job definitions
_job_executions Job execution records
_execution_invocations Individual retry attempt tracking