jobs
Background job processing with priority queues, scheduled execution, automatic retries with exponential backoff, and multi-tenant support.
Key namespaces
| Namespace | Purpose |
|---|---|
|
Pure functions: job creation, state transitions, retry logic |
|
Protocols: |
|
Malli schemas: job states, priorities, retry config |
|
In-memory adapter (atoms, for dev/test) |
|
Redis adapter (sorted sets, lists, hashes) |
|
Worker implementation: polling, processing, pool management |
|
Multi-tenant job execution with schema switching |
Handler signature
;; Handlers receive args map, return result map
(defn send-email-handler [args]
{:success? true
:result {:sent-to (:email args)}})
;; Failing handler
(defn failing-handler [args]
{:success? false
:error {:message "Processing failed" :type "ProcessingError"}})
Enqueueing jobs
(require '[boundary.jobs.core.job :as job]
'[boundary.jobs.ports :as ports])
(let [new-job (job/create-job {:job-type :send-email
:args {:to "user@example.com"}
:priority :high
:max-retries 3}
(random-uuid))]
(ports/enqueue-job! job-queue :default new-job))
Priority levels: :critical, :high, :default, :low, :bulk.
Worker pool
(require '[boundary.jobs.shell.worker :as worker])
(def pool (worker/create-worker-pool
{:queue-name :default :worker-count 5 :poll-interval-ms 500}
queue store registry))
(worker/start-pool! pool)
(worker/stop-pool! pool)
Retry behaviour
Failed jobs retry with exponential backoff:
-
Attempt 1: immediate
-
Attempt 2: 30 seconds
-
Attempt 3: 5 minutes
-
Attempt 4: 1 hour
-
After
max-retries: moved to dead letter queue
Redis counters
Stats are stored as Redis keys: stats:global:* and stats:queue:{name}:*.
Testing
clojure -M:test:db/h2 :jobs