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
lockedfield 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 |