Liking cljdoc? Tell your friends :D

boundary.jobs.shell.tenant-context

Tenant context support for background job processing.

This namespace provides utilities for executing background jobs within tenant-specific database schema contexts. It integrates with the multi-tenant architecture by extracting tenant-id from job metadata and setting the appropriate PostgreSQL search_path before job execution.

Key Features:

  • Extract tenant-id from job metadata
  • Set database search_path to tenant schema
  • Execute job handlers in tenant context
  • Automatic fallback to public schema if no tenant

Usage: (require '[boundary.jobs.shell.tenant-context :as tenant-jobs])

;; Enqueue job with tenant context (tenant-jobs/enqueue-tenant-job! job-queue tenant-id :send-email {:to "user@example.com"})

;; Process job with tenant context (tenant-jobs/process-tenant-job! job handler-fn db-ctx tenant-service)

See ADR-004 for architecture details (lines 525-554).

Tenant context support for background job processing.

This namespace provides utilities for executing background jobs within
tenant-specific database schema contexts. It integrates with the multi-tenant
architecture by extracting tenant-id from job metadata and setting the
appropriate PostgreSQL search_path before job execution.

Key Features:
- Extract tenant-id from job metadata
- Set database search_path to tenant schema
- Execute job handlers in tenant context
- Automatic fallback to public schema if no tenant

Usage:
  (require '[boundary.jobs.shell.tenant-context :as tenant-jobs])
  
  ;; Enqueue job with tenant context
  (tenant-jobs/enqueue-tenant-job! job-queue tenant-id :send-email
                                   {:to "user@example.com"})
  
  ;; Process job with tenant context
  (tenant-jobs/process-tenant-job! job handler-fn db-ctx tenant-service)

See ADR-004 for architecture details (lines 525-554).
raw docstring

enqueue-tenant-job!clj

(enqueue-tenant-job! job-queue tenant-id job-type args)
(enqueue-tenant-job! job-queue
                     tenant-id
                     job-type
                     args
                     {:keys [priority max-retries queue-name]
                      :or {priority :normal max-retries 3 queue-name :default}})

Enqueue a background job with tenant context.

This stores the tenant-id in job metadata so the worker can execute the job in the correct tenant schema context.

Args: job-queue: IJobQueue implementation tenant-id: Tenant UUID job-type: Job type keyword (e.g., :send-email, :process-upload) args: Job arguments map options: Optional map with: :priority - :critical, :high, :normal (default), :low :max-retries - Retry count (default: 3) :queue-name - Queue name (default: :default)

Returns: Job UUID

Example: (enqueue-tenant-job! job-queue tenant-uuid :send-email {:to "user@example.com" :subject "Welcome!" :body "Thanks for signing up."} {:priority :high})

Notes:

  • Tenant-id is stored in job :metadata
  • Jobs without tenant-id run in public schema
  • Worker must have access to db-context and tenant-service
Enqueue a background job with tenant context.

This stores the tenant-id in job metadata so the worker can execute
the job in the correct tenant schema context.

Args:
  job-queue: IJobQueue implementation
  tenant-id: Tenant UUID
  job-type: Job type keyword (e.g., :send-email, :process-upload)
  args: Job arguments map
  options: Optional map with:
           :priority - :critical, :high, :normal (default), :low
           :max-retries - Retry count (default: 3)
           :queue-name - Queue name (default: :default)

Returns:
  Job UUID

Example:
  (enqueue-tenant-job! job-queue
                       tenant-uuid
                       :send-email
                       {:to "user@example.com"
                        :subject "Welcome!"
                        :body "Thanks for signing up."}
                       {:priority :high})

Notes:
  - Tenant-id is stored in job :metadata
  - Jobs without tenant-id run in public schema
  - Worker must have access to db-context and tenant-service
sourceraw docstring

extract-tenant-contextclj

(extract-tenant-context job tenant-service)

Extract tenant context from job metadata.

Args: job: Job map with :metadata tenant-service: ITenantService implementation

Returns: Map with: :tenant-id - Tenant UUID (or nil if not found) :tenant-schema - Tenant schema name (or nil) :tenant-entity - Full tenant entity (or nil)

Notes:

  • Returns nil values if job has no tenant-id
  • Logs warning if tenant-id present but tenant not found
  • Jobs without tenant run in public schema (multi-tenant optional)
Extract tenant context from job metadata.

Args:
  job: Job map with :metadata
  tenant-service: ITenantService implementation

Returns:
  Map with:
    :tenant-id - Tenant UUID (or nil if not found)
    :tenant-schema - Tenant schema name (or nil)
    :tenant-entity - Full tenant entity (or nil)

Notes:
  - Returns nil values if job has no tenant-id
  - Logs warning if tenant-id present but tenant not found
  - Jobs without tenant run in public schema (multi-tenant optional)
sourceraw docstring

process-tenant-job!clj

(process-tenant-job! job
                     handler-fn
                     db-ctx
                     tenant-service
                     tenant-schema-provider)

Process a job with tenant schema context.

This wraps job handler execution to:

  1. Extract tenant-id from job metadata
  2. Lookup tenant entity to get schema name
  3. Set PostgreSQL search_path to tenant schema
  4. Execute job handler with database connection
  5. Restore search_path after execution

Args: job: Job map with :id, :job-type, :args, :metadata handler-fn: Job handler function (fn [args db-ctx] -> result) db-ctx: Database context with :datasource, :database-type tenant-service: ITenantService implementation tenant-schema-provider: ITenantSchemaProvider implementation (optional, required for tenant jobs)

Returns: Result map with :success?, :result or :error

Example: (process-tenant-job! job (fn [args db-ctx] ;; Handler logic here {:success? true :result {:rows 5}}) db-ctx tenant-service tenant-schema-provider)

Notes:

  • Handler receives db-ctx as second argument
  • Handler should use db-ctx for database operations
  • search_path is automatically managed
  • Falls back to public schema if no tenant
  • Only works with PostgreSQL (other databases use public schema)

Security:

  • Tenant isolation enforced via search_path
  • Each job execution gets isolated transaction
  • Schema validation before execution
  • Automatic cleanup on error
Process a job with tenant schema context.

This wraps job handler execution to:
1. Extract tenant-id from job metadata
2. Lookup tenant entity to get schema name
3. Set PostgreSQL search_path to tenant schema
4. Execute job handler with database connection
5. Restore search_path after execution

Args:
  job: Job map with :id, :job-type, :args, :metadata
  handler-fn: Job handler function (fn [args db-ctx] -> result)
  db-ctx: Database context with :datasource, :database-type
  tenant-service: ITenantService implementation
  tenant-schema-provider: ITenantSchemaProvider implementation (optional, required for tenant jobs)

Returns:
  Result map with :success?, :result or :error

Example:
  (process-tenant-job! job
                       (fn [args db-ctx]
                         ;; Handler logic here
                         {:success? true :result {:rows 5}})
                       db-ctx
                       tenant-service
                       tenant-schema-provider)

Notes:
  - Handler receives db-ctx as second argument
  - Handler should use db-ctx for database operations
  - search_path is automatically managed
  - Falls back to public schema if no tenant
  - Only works with PostgreSQL (other databases use public schema)

Security:
  - Tenant isolation enforced via search_path
  - Each job execution gets isolated transaction
  - Schema validation before execution
  - Automatic cleanup on error
sourceraw docstring

wrap-handler-with-tenant-contextclj

(wrap-handler-with-tenant-context handler-fn
                                  db-ctx
                                  tenant-service
                                  tenant-schema-provider)

Wrap an existing job handler to add tenant context support.

This is a convenience function for integrating tenant context into existing job handlers without modifying them.

Args: handler-fn: Original handler (fn [args] -> result) db-ctx: Database context tenant-service: ITenantService implementation tenant-schema-provider: ITenantSchemaProvider implementation (optional, required for tenant jobs)

Returns: Wrapped handler (fn [job] -> result)

Example: (def my-handler (wrap-handler-with-tenant-context (fn [args db-ctx] ;; Original handler logic {:success? true :result {}}) db-ctx tenant-service tenant-schema-provider))

;; Register wrapped handler (ports/register-handler! registry :send-email my-handler)

Notes:

  • Wrapped handler expects job (not just args)
  • Tenant context extracted and applied automatically
  • Original handler must accept db-ctx as second arg
Wrap an existing job handler to add tenant context support.

This is a convenience function for integrating tenant context into
existing job handlers without modifying them.

Args:
  handler-fn: Original handler (fn [args] -> result)
  db-ctx: Database context
  tenant-service: ITenantService implementation
  tenant-schema-provider: ITenantSchemaProvider implementation (optional, required for tenant jobs)

Returns:
  Wrapped handler (fn [job] -> result)

Example:
  (def my-handler
    (wrap-handler-with-tenant-context
      (fn [args db-ctx]
        ;; Original handler logic
        {:success? true :result {}})
      db-ctx
      tenant-service
      tenant-schema-provider))
  
  ;; Register wrapped handler
  (ports/register-handler! registry :send-email my-handler)

Notes:
  - Wrapped handler expects job (not just args)
  - Tenant context extracted and applied automatically
  - Original handler must accept db-ctx as second arg
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close