Skip to content

feat: run observability with listRuns and resume#49

Open
danfry1 wants to merge 2 commits into
fix/sqlite-bun-changesfrom
feat/run-observability
Open

feat: run observability with listRuns and resume#49
danfry1 wants to merge 2 commits into
fix/sqlite-bun-changesfrom
feat/run-observability

Conversation

@danfry1

@danfry1 danfry1 commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Adds two operational primitives for inspecting and recovering workflow runs — the foundation for run observability in Reflow.

  • engine.listRuns(filter?) — lists runs in reverse-chronological order for inspection and dead-letter visibility. Filter by status and/or workflow; paginate with limit and a before (createdAt) cursor. A non-positive limit is rejected with a ConfigError.
  • engine.resume(runId) — re-queues a failed or cancelled run. Completed steps are preserved and skipped on replay, so execution resumes at the step that failed; the failed step's result is discarded and re-run. Returns false when the run is not in a resumable state (pending / running / completed / missing).

Storage interface

StorageAdapter gains two methods, implemented across every built-in adapter (memory, sqlite-node, sqlite-bun, sqlite-node-builtin):

  • listRuns(filter?) — backs engine.listRuns().
  • requeueRun(runId) — resets a failed/cancelled run to pending and deletes its failed step results in a transaction; backs engine.resume().

Custom adapters must implement these two methods.

Tests

+27 tests (387 total, all passing). Coverage added for both methods across the memory, better-sqlite3, and node:sqlite adapters, plus end-to-end engine tests: resume-from-failure without re-running completed steps, resume rejection on non-resumable runs, dead-letter listing, and limit validation.

Typecheck, build, and lint:deps all pass.

Public API

New exported type: ListRunsFilter. No breaking changes to existing surface.

@danfry1 danfry1 force-pushed the feat/run-observability branch from e704d43 to 1afdb7b Compare June 21, 2026 20:49
@danfry1 danfry1 changed the base branch from main to fix/sqlite-bun-changes June 21, 2026 20:49
@danfry1 danfry1 force-pushed the feat/run-observability branch from 1afdb7b to a994a19 Compare June 21, 2026 20:56
danfry1 added 2 commits June 22, 2026 20:25
Add two operational primitives for inspecting and recovering runs:

- engine.listRuns(filter?) lists runs most-recent-first for inspection
  and dead-letter visibility, filtered by status/workflow and paged with
  limit + a before (createdAt) cursor.
- engine.resume(runId) re-queues a failed or cancelled run. Completed
  steps are preserved and skipped on replay, so execution resumes at the
  step that failed; the failed step's result is discarded and re-run.

StorageAdapter gains listRuns() and requeueRun(), implemented across all
built-in adapters (memory, sqlite-node, sqlite-bun, sqlite-node-builtin)
with matching tests. New exported ListRunsFilter type.
- listRuns: deterministic order (createdAt DESC, id DESC) across all
  adapters, and a keyset cursor (before + beforeId) so pagination is
  exact even when runs share a createdAt. The SQLite adapters order by
  id rather than rowid so the cursor and order agree.
- resume(): return false for a missing run, and throw
  WorkflowNotFoundError when the run's workflow is not registered, rather
  than re-queuing it into an unclaimable pending state.
- sqlite-bun requeueRun: read the affected-row count from the run()
  result (inherits the change-detection fix this branch is rebased on).
- Tests: tied-createdAt keyset pagination (memory + sqlite), resume on
  missing/unregistered-workflow runs, requeue of a running run.
@danfry1 danfry1 force-pushed the feat/run-observability branch from a994a19 to f907606 Compare June 22, 2026 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant