Background Jobs
The jobs library provides background job processing with priority queues,
scheduled execution, automatic retries with exponential backoff, and multi-tenant support.
Uses an in-memory backend for development/tests and Redis for production.
Defining a job handler
;; Handlers receive an args map, return a result map
(defn send-welcome-email [args]
(let [{:keys [user-id email]} args]
(email/send! {:to email :subject "Welcome!"})
{:success? true :result {:sent-to email}}))
;; A failing handler
(defn process-payment [args]
{:success? false
:error {:message "Payment gateway unavailable" :type "GatewayError"}})
Registering handlers
(require '[boundary.jobs.shell.worker :as worker]
'[boundary.jobs.ports :as ports])
(def registry (worker/create-job-registry))
(ports/register-handler! registry :send-welcome-email send-welcome-email)
(ports/register-handler! registry :process-payment process-payment)
Enqueueing jobs
(require '[boundary.jobs.core.job :as job])
(let [new-job (job/create-job {:job-type :send-welcome-email
:args {:user-id (random-uuid)
:email "alice@example.com"}
:priority :high
:max-retries 3}
(random-uuid))]
(ports/enqueue-job! job-queue :default new-job))
Priority levels: :critical, :high, :default, :low, :bulk.
Starting workers
;; Single worker
(def worker (worker/create-worker
{:queue-name :default :poll-interval-ms 1000}
queue store registry))
;; Worker pool (recommended for production)
(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)
Integrant configuration
;; config.edn
:boundary/job-queue {:backend :redis :redis-url #env REDIS_URL}
:boundary/job-store {:backend :redis :redis-url #env REDIS_URL}
:boundary/job-worker {:queue-name :default
:worker-count 5
:queue #ig/ref :boundary/job-queue
:store #ig/ref :boundary/job-store
:registry #ig/ref :boundary/job-registry}
Retry logic
Failed jobs are automatically retried 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
Multi-tenant jobs
;; Jobs run in tenant schema context automatically
(job/create-job {:job-type :sync-inventory
:args {:product-id sku}
:tenant-id "acme-corp"}
(random-uuid))
See jobs library for the full reference.