Conversation
scheduleEvery() now deduplicates by callback name: calling it multiple times with the same callback returns the existing schedule instead of creating a duplicate. If the interval or payload changed, the existing schedule is updated in place. This fixes the common pattern of calling scheduleEvery() inside onStart(), which runs on every Durable Object wake. Previously each wake created a new interval schedule, leading to duplicate executions. keepAlive() opts out of idempotency via an internal _idempotent: false flag so multiple concurrent keepAlive calls still get independent schedules with independent disposers. Closes #1049
🦋 Changeset detectedLatest commit: 7b1b0c8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
|
/bonk a different interval and/or payload should probably create a new row |
Instead of updating the existing row when interval/payload differs, treat a different interval or payload as a distinct schedule that gets its own row. The idempotency key is now the full tuple of (callback, intervalSeconds, payload) rather than just callback. Uses SQL IS instead of = for payload comparison to correctly handle NULL payload values (NULL IS NULL is true in SQLite).
|
Here's a summary of the changes made: ChangesThe idempotency key for
Files changed
All 675 tests pass. |
All done. Here's a summary of the changes:
Summary
Problem
scheduleEvery()generated a newnanoid(9)on every call, soINSERT OR REPLACEnever actually replaced — it always inserted a new row. CallingscheduleEvery(30, "tick")inonStart()(which runs on every DO wake) created N duplicate interval schedules after N wakes.Solution
packages/agents/src/index.ts— ModifiedscheduleEvery()to be idempotent by callback name:callbackintervalSecondsandpayload: returns the existing schedule (no-op)_idempotent: falseoption sokeepAlive()can opt out (it needs independent schedules for each concurrent caller)packages/agents/src/tests/agents/schedule.ts— Added test agent methods:createIntervalScheduleWithPayload(),createSecondIntervalSchedule(),countIntervalSchedules(),countIntervalSchedulesForCallback()packages/agents/src/tests/schedule.test.ts— Added 6 idempotency tests:onStart) produce exactly 1 scheduledocs/scheduling.md— Documented idempotency behavior in both the Interval section and API reference..changeset/idempotent-schedule-every.md— Patch changeset for theagentspackage.Closes #1049
github run