refactor: rename payload to input, add startedAt/completedAt, unify Run types#42
Conversation
…un types
- Rename `payload` → `input` across all packages to align with
`defineJob({ input })` and `trigger(input)` API naming
- Add `startedAt`/`completedAt` columns to durably_runs table (migration v3)
and set them on worker status transitions
- Derive `ClientRun` from core `Run` via `Pick<>` instead of maintaining
a separate interface; remove `RunRecord` type entirely
- Update all tests, examples, and documentation
Closes #32
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
📝 WalkthroughWalkthroughSystematic refactor renaming the job run handler parameter and stored payload field from Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Rename payload→input in all website guide code examples - Add Run Type section to create-durably.md with full field table - Add Run Type summary to index.md cheat sheet - Both include new startedAt/completedAt fields Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/durably/src/migrations.ts`:
- Around line 125-145: The v3 migration (version: 3, up: async (db)) performs
multiple DDL steps on table 'durably_runs' (renameColumn 'payload'->'input' and
addColumn 'started_at'/'completed_at') but doesn't record the schema version
atomically; wrap the DDL and the schema-version write in a single transaction so
either all changes and the migration-record insert/update succeed or none do.
Modify the up function to begin a transaction via the DB transaction API (e.g.,
db.transaction(...) or a BEGIN/COMMIT block provided by your DB client), execute
the renameColumn and addColumn calls inside that transaction, then write the
migration version (insert or update your migrations table / schema version
record) inside the same transaction before committing; ensure any error rolls
back so re-running migrations won't see a half-applied state.
In `@packages/durably/src/worker.ts`:
- Around line 251-256: The current two-step claim (getNextPendingRun ->
storage.updateRun) is non-atomic and allows duplicate execution; replace it by
adding a new storage method claimPendingRun that performs an atomic guarded
update (e.g. UPDATE ... SET status='running', heartbeatAt=?, startedAt=? WHERE
id=? AND status='pending') and returns whether a row was affected, then change
the worker to call storage.claimPendingRun(run.id, {status:'running',
heartbeatAt: now, startedAt: now}) instead of storage.updateRun and only proceed
with execution when claimPendingRun reports success (otherwise skip/continue);
reference functions: getNextPendingRun, storage.updateRun, claimPendingRun, and
the worker run claim block in worker.ts.
In `@website/api/durably-react/client.md`:
- Line 401: Update the docs table entry for getRun to indicate it returns a
nullable result: change the return type from Promise<ClientRun> to
Promise<ClientRun | null> so it matches the actual client implementation (see
getRun usage in use-run-actions where it returns ClientRun | null); ensure the
table cell text is updated exactly to "Promise<ClientRun | null>" to avoid
misleading consumers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 64524b5c-77da-4f7f-81e0-225aca40dcce
📒 Files selected for processing (46)
examples/browser-react-router-spa/app/jobs/data-sync.tsexamples/browser-react-router-spa/app/jobs/import-csv.tsexamples/browser-react-router-spa/app/jobs/process-image.tsexamples/browser-vite-react/src/jobs/data-sync.tsexamples/browser-vite-react/src/jobs/process-image.tsexamples/fullstack-react-router/app/jobs/data-sync.tsexamples/fullstack-react-router/app/jobs/import-csv.tsexamples/fullstack-react-router/app/jobs/process-image.tsexamples/server-node/jobs/process-image.tspackages/durably-react/docs/llms.mdpackages/durably-react/src/client.tspackages/durably-react/src/client/index.tspackages/durably-react/src/client/use-run-actions.tspackages/durably-react/src/types.tspackages/durably-react/tests/types.test.tspackages/durably/docs/llms.mdpackages/durably/src/define-job.tspackages/durably/src/durably.tspackages/durably/src/events.tspackages/durably/src/job.tspackages/durably/src/migrations.tspackages/durably/src/schema.tspackages/durably/src/storage.tspackages/durably/src/worker.tspackages/durably/tests/node/core-extensions.test.tspackages/durably/tests/react/strict-mode.test.tsxpackages/durably/tests/shared/concurrency.shared.tspackages/durably/tests/shared/durably.shared.tspackages/durably/tests/shared/events.shared.tspackages/durably/tests/shared/job.shared.tspackages/durably/tests/shared/migrate.shared.tspackages/durably/tests/shared/recovery.shared.tspackages/durably/tests/shared/run-api.shared.tspackages/durably/tests/shared/server.shared.tspackages/durably/tests/shared/step.shared.tspackages/durably/tests/shared/storage.shared.tspackages/durably/tests/shared/worker.shared.tswebsite/api/create-durably.mdwebsite/api/define-job.mdwebsite/api/durably-react/browser.mdwebsite/api/durably-react/client.mdwebsite/api/durably-react/types.mdwebsite/api/events.mdwebsite/api/index.mdwebsite/api/step.mdwebsite/public/llms.txt
💤 Files with no reviewable changes (2)
- packages/durably-react/src/client.ts
- packages/durably-react/src/client/index.ts
| { | ||
| version: 3, | ||
| up: async (db) => { | ||
| // Rename payload column to input | ||
| await db.schema | ||
| .alterTable('durably_runs') | ||
| .renameColumn('payload', 'input') | ||
| .execute() | ||
|
|
||
| // Add started_at and completed_at columns | ||
| await db.schema | ||
| .alterTable('durably_runs') | ||
| .addColumn('started_at', 'text') | ||
| .execute() | ||
|
|
||
| await db.schema | ||
| .alterTable('durably_runs') | ||
| .addColumn('completed_at', 'text') | ||
| .execute() | ||
| }, | ||
| }, |
There was a problem hiding this comment.
Make migration v3 application atomic with version recording.
This migration performs multiple DDL steps. If execution stops after renaming payload but before schema version is recorded, re-running migrations can fail because payload no longer exists. Please ensure the migration step and its schema-version write are committed as one atomic unit.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/durably/src/migrations.ts` around lines 125 - 145, The v3 migration
(version: 3, up: async (db)) performs multiple DDL steps on table 'durably_runs'
(renameColumn 'payload'->'input' and addColumn 'started_at'/'completed_at') but
doesn't record the schema version atomically; wrap the DDL and the
schema-version write in a single transaction so either all changes and the
migration-record insert/update succeed or none do. Modify the up function to
begin a transaction via the DB transaction API (e.g., db.transaction(...) or a
BEGIN/COMMIT block provided by your DB client), execute the renameColumn and
addColumn calls inside that transaction, then write the migration version
(insert or update your migrations table / schema version record) inside the same
transaction before committing; ensure any error rolls back so re-running
migrations won't see a half-applied state.
There was a problem hiding this comment.
Thanks for catching this. This is a pre-existing issue not introduced by this PR, so I've created a separate issue to track it: #43
There was a problem hiding this comment.
@coji, thanks for the context! Good call on tracking it separately in #43 since it's a pre-existing pattern across all migrations. I'll keep an eye out for it in future reviews.
🧠 Learnings used
Learnt from: CR
Repo: coji/durably PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-04T13:25:17.638Z
Learning: Database schema consists of four tables: `durably_runs`, `durably_steps`, `durably_logs`, `durably_schema_versions` with specified key fields
Learnt from: CR
Repo: coji/durably PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-04T13:25:17.638Z
Learning: Applies to **/*.{ts,tsx} : Use top-level `await` for async initialization (e.g., `await durably.migrate()`). Do not wrap in async IIFE or Promise chains
… type Server /runs and /run endpoints now return ClientRun (excluding heartbeatAt, idempotencyKey, concurrencyKey, updatedAt). Added toClientRun() projection helper exported from core. durably-react ClientRun now re-exports from core. Also fixed confusing input.input naming in subscribe tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update types.md to reflect ClientRun excluding internal fields, add currentStepIndex/stepCount fields. Add ClientRun and toClientRun to quick reference. Note core re-export in react llms.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace .payload with .input and RunRecord with ClientRun in all example dashboard components. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
payload→inputacross all packages to align withdefineJob({ input })andtrigger(input)API namingstartedAt/completedAtcolumns todurably_runstable (migration v3) and set them on worker status transitionsClientRunfrom coreRunviaPick<>instead of maintaining a separate interface; removeRunRecordtype entirelyBreaking Changes
Run.payload→Run.inputRunTriggerEvent.payload/RunStartEvent.payload→.inputJobRunFunctionsecond parameter renamed frompayloadtoinputRunRecordtype removed (useClientRuninstead)Test plan
pnpm --filter durably typecheckpassespnpm --filter durably test:node -- --run— 186 tests passpnpm --filter durably-react typecheckpassespnpm --filter durably-react test -- --run— 140 tests passpnpm --filter durably-website generate:llmsregeneratedCloses #32
🤖 Generated with Claude Code
Summary by CodeRabbit
Breaking Changes
inputinstead ofpayloadRunobjects and emitted run events exposeinputinstead ofpayloadRunRecordrenamed toClientRunin the client APINew Features
startedAtandcompletedAttimestampsDocumentation
inputnaming and new timing fields