ReLab

Break it. Watch it recover.

← all runs

Run

Status
SUCCEEDED
Workflow
effectful v1
Run id
c68a432f-a112-40a3-b1af-2433dad7c7f9
Seed
31337
Scenario
duplicate-delivery-on-charge
Duration
39ms

This run was disrupted and finished anyway

1 side effect already performed was suppressed by the idempotency ledger, so the retry did not repeat work that had already happened. All of it is in the 18 events below.

What happened

The milestones of this run, in the order they were recorded. Each one is a real event; the full sequence is in the timeline below.

  1. Run started#6 23:31:07.030
    RUN_STARTED

    A worker picked up the first task in the run.

  2. Failure injected on purpose charge#13 23:31:07.047
    FAULT_INJECTED

    ReLab degraded the real system here. This is the break, and everything after it is the recovery.

  3. Duplicate effect prevented charge#14 23:31:07.048
    SIDE_EFFECT_SKIPPED

    The retry asked to perform an effect already recorded under the same key, so it was not performed a second time.

  4. Task running report#16 23:31:07.052
    TASK_STARTED

    The handler began executing. Each attempt writes one of these.

  5. Task finished report#17 23:31:07.054
    TASK_SUCCEEDED

    The handler returned without an error and the result was recorded.

  6. Workflow completed#18 23:31:07.054
    RUN_SUCCEEDED

    Every task finished. This event is the run's last: a finished run's story cannot change.

What the journal proves

3
Attempts
1
Workers involved
1
Faults injected
0
Leases expired
0
Tasks requeued
0
Retries scheduled
0
Workers lost
1
Effects suppressed
0
Dead-lettered
0.01s
Recovery

Every number above is a count of events in this run’s journal. Recovery is measured from the first fault, lease expiry, task failure or lost worker to the run completing, the same interval relab test asserts on.

Tasks

Each task in the run, with the attempt it reached and the worker that last held it.
StatusTaskAttemptWorkerError
SUCCEEDEDcharge1/360026864·
SUCCEEDEDimport1/360026864·
SUCCEEDEDreport1/360026864·

Timeline

The run’s complete recorded history, in sequence order. This is the same journal relab replay reduces. Filtering hides rows from this view; it never changes the sequence numbers, so a gap in them is still a gap.

12 of 18 recorded events, oldest first.
SeqTimeWhat happenedTaskWorkerTechnical detail
223:31:07.015Task ready to runTASK_SCHEDULEDimport·
attempt=0

The task's dependencies are satisfied, so it entered the queue.

Event
TASK_SCHEDULED
Sequence
2
Task
import
Worker
·
Occurred at
2026-09-02T23:31:07.015775Z
{
  "v": 1,
  "attempt": 0,
  "scheduled_at": "2026-09-02T23:31:07.015775166Z"
}
423:31:07.024Task claimed by a workerTASK_LEASEDimport60026864
attempt=1

One worker holds the task for a bounded time and renews that hold while it works. The hold is on this attempt: if it expires while that worker is still running, a second worker may take the task under a new attempt number.

Event
TASK_LEASED
Sequence
4
Task
import
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.024229Z
{
  "v": 1,
  "attempt": 1,
  "lease_expires_at": "2026-09-02T23:31:09.02422958Z"
}
523:31:07.030Task runningTASK_STARTEDimport60026864
attempt=1

The handler began executing. Each attempt writes one of these.

Event
TASK_STARTED
Sequence
5
Task
import
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.030696Z
{
  "v": 1,
  "attempt": 1,
  "handler": "import_csv"
}
723:31:07.033Task finishedTASK_SUCCEEDEDimport60026864
attempt=1 duration_ms=0

The handler returned without an error and the result was recorded.

Event
TASK_SUCCEEDED
Sequence
7
Task
import
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.033676Z
{
  "v": 1,
  "output": {
    "rows": 1000
  },
  "attempt": 1,
  "artifacts": [
    {
      "name": "imported.csv",
      "size": 9,
      "sha256": "6eb31300aed462386f9f52f25d0155b3ca1a9ebce4c811950777282d69a81c64",
      "content_type": "text/csv"
    }
  ],
  "duration_ms": 0
}
823:31:07.033Task ready to runTASK_SCHEDULEDcharge·
attempt=0

The task's dependencies are satisfied, so it entered the queue.

Event
TASK_SCHEDULED
Sequence
8
Task
charge
Worker
·
Occurred at
2026-09-02T23:31:07.033676Z
{
  "v": 1,
  "attempt": 0,
  "depends_on": [
    "import"
  ],
  "scheduled_at": "2026-09-02T23:31:07.033676176Z"
}
923:31:07.038Task claimed by a workerTASK_LEASEDcharge60026864
attempt=1

One worker holds the task for a bounded time and renews that hold while it works. The hold is on this attempt: if it expires while that worker is still running, a second worker may take the task under a new attempt number.

Event
TASK_LEASED
Sequence
9
Task
charge
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.038887Z
{
  "v": 1,
  "attempt": 1,
  "lease_expires_at": "2026-09-02T23:31:09.038887823Z"
}
1023:31:07.041Task runningTASK_STARTEDcharge60026864
attempt=1

The handler began executing. Each attempt writes one of these.

Event
TASK_STARTED
Sequence
10
Task
charge
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.041142Z
{
  "v": 1,
  "attempt": 1,
  "handler": "charge_once"
}
1123:31:07.044Task finishedTASK_SUCCEEDEDcharge60026864
attempt=1 duration_ms=1

The handler returned without an error and the result was recorded.

Event
TASK_SUCCEEDED
Sequence
11
Task
charge
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.044385Z
{
  "v": 1,
  "output": {
    "effect": {
      "charged": true,
      "by_attempt": 1
    },
    "attempt": 1
  },
  "attempt": 1,
  "duration_ms": 1
}
1223:31:07.044Task ready to runTASK_SCHEDULEDreport·
attempt=0

The task's dependencies are satisfied, so it entered the queue.

Event
TASK_SCHEDULED
Sequence
12
Task
report
Worker
·
Occurred at
2026-09-02T23:31:07.044385Z
{
  "v": 1,
  "attempt": 0,
  "depends_on": [
    "charge"
  ],
  "scheduled_at": "2026-09-02T23:31:07.044385533Z"
}
1523:31:07.050Task claimed by a workerTASK_LEASEDreport60026864
attempt=1

One worker holds the task for a bounded time and renews that hold while it works. The hold is on this attempt: if it expires while that worker is still running, a second worker may take the task under a new attempt number.

Event
TASK_LEASED
Sequence
15
Task
report
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.050833Z
{
  "v": 1,
  "attempt": 1,
  "lease_expires_at": "2026-09-02T23:31:09.050833659Z"
}
1623:31:07.052Task runningTASK_STARTEDreport60026864
attempt=1

The handler began executing. Each attempt writes one of these.

Event
TASK_STARTED
Sequence
16
Task
report
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.052974Z
{
  "v": 1,
  "attempt": 1,
  "handler": "summarize"
}
1723:31:07.054Task finishedTASK_SUCCEEDEDreport60026864
attempt=1 duration_ms=0

The handler returned without an error and the result was recorded.

Event
TASK_SUCCEEDED
Sequence
17
Task
report
Worker
60026864-76be-404a-9c4b-45f17465da3d
Occurred at
2026-09-02T23:31:07.054474Z
{
  "v": 1,
  "output": {
    "inputs": 1
  },
  "attempt": 1,
  "artifacts": [
    {
      "name": "summary.json",
      "size": 65,
      "sha256": "54cb487a3dd596a1d7337436435d9ff485ee285dc6e727a8eda83ff26eb2bc2b",
      "content_type": "application/json"
    }
  ],
  "duration_ms": 0
}
RECORDINGfive real runs exported from real PostgreSQL by scripts/record-demo.sh, crashes delivered by SIGKILLrelab 241c136-dirty, recorded