---
id: WF-PFM-DJE-002
title: Run one batch of a data job
trigger: >-
  A CRM worker receives a batch message, or a Platform request invokes its local
  batch runner.
product_area: platform
module: data-job-engine
revision: 1
status: draft
design_intent: confirmed
origin: >-
  services-platform:docs/proposals/rhythm-data-job-engine-plan.md §8 failure
  classification, §9.3 the batch algorithm, §9.5 receipts, §16 security
  (approved 2026-10-12); PLAT-M19 D4 job attribution in history
implementation_evidence: observed
inference: []
source_sha:
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
implements:
  - CAP-PFM-DJE-003
  - CAP-PFM-DJE-005
  - CAP-PFM-DJE-006
  - CAP-PFM-DJE-012
moves:
  - STATE-PFM-DJE-001
  - STATE-PFM-DJE-002
crosses:
  - SVC-PFM-DJE-engine
  - SVC-PFM-DJE-crm-data-jobs
hops:
  - 'n': 1
    actor_or_service: Batch runner
    action: Read execution eligibility before taking up item work.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/run-data-job-batch.ts:runDataJobBatch
    seam: sync
    on_failure: A nonrunnable job produces a no-work response.
    left_inconsistent: Business records remain untouched by this delivery.
    observer: Worker logging records the delivery.
    provenance: documented
    source: >-
      macroservice-libraries:packages/data-jobs/src/run-data-job-batch.ts
      (module comment, step 1)
  - 'n': 2
    actor_or_service: Worker boundary and batch runner
    action: Record the attempt and evaluate current submitter authority.
    anchor: >-
      services-crm:modules/data-jobs/services/queue/data-job-worker.ts:runQueuedDataJobBatches
    seam: sync
    on_failure: Fail revoked authority and acknowledge the message.
    left_inconsistent: Earlier batches retain their committed changes.
    observer: Saved job failure identifies revoked execution access.
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#fails
      the whole job with the code, not just the batch
  - 'n': 3
    actor_or_service: Owning record's operation (prevalidate)
    action: >-
      Perform domain prevalidation, capture or compare versions and propagate
      refusals across commit-group members.
    anchor: 'macroservice-libraries:packages/data-jobs/src/version-capture.ts'
    seam: sync
    on_failure: Record individual or group refusals and continue with survivors.
    left_inconsistent: Prevalidation changes no business record.
    observer: Refusals page; conflicts name both versions.
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-versions.integration.spec.js#skips
      the contact that changed after the validation as a named conflict
  - 'n': 4
    actor_or_service: Owning record's operation (prepare)
    action: >-
      Prepare required record assets outside the write transaction, omitting
      already settled items.
    anchor: 'services-crm:modules/data-jobs/services/operations/record-files.ts'
    seam: sync
    on_failure: >-
      Refuse invalid assets per item; classify storage outages for transient
      retry.
    left_inconsistent: Unused prepared assets await their cleanup sweep.
    observer: Refusals; asset cleanup.
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/initial-import-guarantees.integration.spec.js#applies
      every organization whose logo could be saved, and rejects the two that
      could not be written
  - 'n': 5
    actor_or_service: Batch runner and the owning record's save
    action: >-
      Claim receipts, invoke domain persistence and complete receipts inside
      each commit unit.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/run-data-job-batch.ts:runDataJobBatch
    seam: sync
    on_failure: >-
      Use savepoints for small domain refusals and recursively split failed
      database units.
    left_inconsistent: Each failed unit rolls back; successful earlier units remain.
    observer: >-
      Outcome pages expose results and refusals; record history retains job
      attribution.
    provenance: test
    source: >-
      macroservice-libraries:packages/data-jobs/src/commit-split.spec.ts#halves
      the unit until the failing object stands alone, and isolates only it
  - 'n': 6
    actor_or_service: Batch runner
    action: >-
      Classify systemic problems and retry transient failures within the attempt
      limit.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/run-data-job-batch.ts:handleSystemicFailure
    seam: queue
    on_failure: Pause after transient exhaustion or fail permanent processing problems.
    left_inconsistent: Earlier changes persist; remaining work is held or abandoned.
    observer: The job's state and pause reason; worker metrics.
    provenance: documented
    source: 'services-crm:docs/data-jobs.md#What each contact''s outcome can be'
  - 'n': 7
    actor_or_service: Batch runner
    action: >-
      Complete batch progress, evaluate the refusal-rate guard and settle when
      no unfinished batch remains.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/run-data-job-batch.ts:settleJob
    seam: sync
    on_failure: >-
      The guard can hold work; automatic settlement can bypass the declared
      transition table.
    left_inconsistent: Held jobs preserve completed item evidence.
    observer: Job counters and final state.
    provenance: observed
    source: >-
      macroservice-libraries:packages/data-jobs/src/rejection-guard.ts:rejectionGuardVerdict
idempotency: >-
  Receipt insertion claims each workspace, job and item position in the write
  transaction. A pre-existing receipt skips that item. Conditional batch
  completion increments progress once even when deliveries overlap.
concurrency: >-
  Concurrent deliveries can process a batch, but unique receipts select its item
  writers. Job settlement uses the parent lock. Domain expected-version checks
  protect the gap between prevalidation and persistence.
branches:
  - Keyed items also consult their producer mappings.
  - >-
    Validation saves impact, versions and refusals while leaving target records
    unchanged.
  - An unchanged contact update creates no new record history or event.
waits:
  - CRM redelivery uses increasing delays bounded by its configured ceiling.
evidence:
  - >-
    macroservice-libraries at 54536a44: src/run-data-job-batch.ts,
    commit-split.ts, version-capture.ts, rejection-guard.ts, data-job-config.ts.
  - >-
    services-crm at a8d1364f: services/queue/data-job-worker.ts,
    sqs-redelivery.ts; services/operations/record-files.ts, contact-update.ts,
    error-classification.ts.
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, TC-CHG-007, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-DAT-005, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-PRV-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Run One Batch Of A Data Job

## What It Does

The batch runner checks execution eligibility, validates records, prepares external assets and commits domain writes with receipts. Refusals stay local to affected items or commit groups, while systemic problems stop further work.

## The Flow

```mermaid
flowchart TD
  H1["Batch runner"] --> H2
  H2["Worker boundary and batch runner"] --> H3
  H3["Owning record's operation (prevalidate)"] --> H4
  H4["Owning record's operation (prepare)"] --> H5
  H5["Batch runner and the owning record's save"] --> H6
  H6["Batch runner"] --> H7
  H7["Batch runner"]
```

## When Something Fails

Domain refusals are reported per item or group. Transient systemic failures receive attempts and can leave a paused job; permanent problems fail it. Prepared assets and earlier committed units follow separate cleanup and recovery boundaries.

## Open Design Questions

The recorded findings identify the remaining limits; this examination does not authorize stronger behavior or change the planning rules.
