---
id: STATE-PFM-QRY-008
title: Schedule run
object: DOM-PFM-QRY-004
product_area: platform
module: queries
revision: 1
status: draft
design_intent: confirmed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
states:
  - name: queued
    meaning: A due occurrence or manual run has been admitted to the delivery queue.
  - name: running
    meaning: The consumer is preparing the file and processing recipient delivery requests.
  - name: succeeded
    meaning: The file is complete and recipient outcomes have been recorded as submitted or skipped.
  - name: skipped
    meaning: The query returned no rows and its configured empty-result policy suppressed delivery.
  - name: failed
    meaning: >-
      The attempt settled with a failure code after a refusal or exhausted retries; some recipients
      may already have received a request.
transitions:
  - from: queued
    to: running
    trigger: The delivery consumer begins the occurrence.
    guard: The run has not settled.
    side_effects:
      - the attempt count advances
    who: system (schedule consumer)
    provenance: observed
    source: 'services-platform:modules/queries/aws/logic/query-schedules.lambda.ts'
  - from: running
    to: succeeded
    trigger: File production and recipient outcome recording finish.
    guard: The run can settle successfully.
    side_effects:
      - the failure streak resets and the last-run outcome is recorded
    who: system (schedule consumer)
    provenance: observed
    source: 'services-platform:modules/queries/services/schedules/scheduled-delivery.ts'
  - from: running
    to: skipped
    trigger: The file has no records and empty-result suppression is enabled.
    guard: The source is a query schedule.
    side_effects:
      - no communication is submitted; history records skipped_empty
    who: system (schedule consumer)
    provenance: observed
    source: 'services-platform:modules/queries/services/schedules/scheduled-delivery.ts'
  - from: running
    to: failed
    trigger: A request refusal or exhausted infrastructure attempt settles the run.
    guard: The run can settle as failed.
    side_effects:
      - the failure streak advances; applicable source-access or report-deletion pauses are recorded
    who: system (schedule consumer)
    provenance: observed
    source: 'services-platform:modules/queries/services/schedules/scheduled-report-delivery.ts'
  - from: running
    to: running
    trigger: An infrastructure failure returns unfinished work to the queue.
    guard: A configured receive attempt remains.
    side_effects:
      - the existing file and recipient submission records are reused
    who: system (SQS)
    provenance: documented
    source: 'services-platform:docs/migrations/query-scheduling-exports/README.md#D12'
invalid:
  - from: succeeded
    to: running
    why: A terminal run is not reopened; another manual request or due occurrence creates new work.
  - from: skipped
    to: succeeded
    why: An empty-result skip stays terminal rather than sending that run later.
concurrency: >-
  The occurrence key prevents duplicate admission. Redelivery reuses the file and recipient
  submission keys. Report runs wait in their consumer for renderer completion for up to twelve
  minutes before throwing an unsettled attempt back for retry.
invariants:
  - INV-DOM-PFM-QRY-004-05
  - INV-DOM-PFM-QRY-004-08
evidence:
  - >-
    services-platform at ad3f6a6: modules/queries/db/schedule-runs.table.ts,
    query-schedule-deliveries.table.ts; services/schedules/scheduled-delivery.ts,
    scheduled-report-delivery.ts; @rhythmsoftware/macroservice-schedules (SCHEDULE_RUN_STATUSES)
---

# Schedule run

## The Lifecycle

```mermaid
stateDiagram-v2
  state "queued" as s0
  state "running" as s1
  state "succeeded" as s2
  state "skipped" as s3
  state "failed" as s4
  s0 --> s1
  s1 --> s2
  s1 --> s3
  s1 --> s4
  s1 --> s1
```

Each occurrence tracks a file and recipient outcomes independently of the recurrence definition. A failure can follow partial delivery.

## Transitions Explained

The consumer records attempts, completes or skips the run, and updates recurrence outcome tracking. Transient failures reuse prior work on redelivery.

## What Cannot Happen

Settled runs do not restart, and an empty query skip cannot later become a delivery of the same occurrence.

## Concurrency and Timing

Waiting report consumers occupy the configured concurrency until rendering settles or their polling deadline is reached.
