Skip to content

Commit 3d4a54b

Browse files
authored
do: docs feedback on alarms + waituntil (#27145)
1 parent 6b4df76 commit 3d4a54b

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

src/content/docs/durable-objects/api/alarms.mdx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,53 @@ Alarms are directly scheduled from within your Durable Object. Cron Triggers, on
2727

2828
Alarms can be used to build distributed primitives, like queues or batching of work atop Durable Objects. Alarms also provide a mechanism to guarantee that operations within a Durable Object will complete without relying on incoming requests to keep the Durable Object alive. For a complete example, refer to [Use the Alarms API](/durable-objects/examples/alarms-api/).
2929

30+
## Scheduling multiple events with a single alarm
31+
32+
Although each Durable Object can only have one alarm set at a time, you can manage many scheduled and recurring events by storing your event schedule in storage and having the `alarm()` handler process due events, then reschedule itself for the next one.
33+
34+
```js
35+
import { DurableObject } from "cloudflare:workers";
36+
37+
export class AgentServer extends DurableObject {
38+
// Schedule a one-time or recurring event
39+
async scheduleEvent(id, runAt, repeatMs = null) {
40+
await this.ctx.storage.put(`event:${id}`, { id, runAt, repeatMs });
41+
const currentAlarm = await this.ctx.storage.getAlarm();
42+
if (!currentAlarm || runAt < currentAlarm) {
43+
await this.ctx.storage.setAlarm(runAt);
44+
}
45+
}
46+
47+
async alarm() {
48+
const now = Date.now();
49+
const events = await this.ctx.storage.list({ prefix: "event:" });
50+
let nextAlarm = null;
51+
52+
for (const [key, event] of events) {
53+
if (event.runAt <= now) {
54+
await this.processEvent(event);
55+
if (event.repeatMs) {
56+
event.runAt = now + event.repeatMs;
57+
await this.ctx.storage.put(key, event);
58+
} else {
59+
await this.ctx.storage.delete(key);
60+
}
61+
}
62+
// Track the next event time
63+
if (event.runAt > now && (!nextAlarm || event.runAt < nextAlarm)) {
64+
nextAlarm = event.runAt;
65+
}
66+
}
67+
68+
if (nextAlarm) await this.ctx.storage.setAlarm(nextAlarm);
69+
}
70+
71+
async processEvent(event) {
72+
// Your event handling logic here
73+
}
74+
}
75+
```
76+
3077
## Storage methods
3178

3279
### `getAlarm`

src/content/docs/durable-objects/api/state.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ Contains loopback bindings to the Worker's own top-level exports. This has exact
7676

7777
`waitUntil` waits until the promise which is passed as a parameter resolves, and can extend a request context even after the last client disconnects. Refer to [Lifecycle of a Durable Object](/durable-objects/concepts/durable-object-lifecycle/) for more information.
7878

79-
:::note[`waitUntil` is not necessary]
79+
:::note[`waitUntil` has no effect in Durable Objects]
8080

81-
If a Durable Object is still waiting on any ongoing work or outbound I/O, it will remain active for a period of time. Therefore, `waitUntil` is not necessary. It remains part of the `DurableObjectState` interface to remain compatible with [Workers Runtime APIs](/workers/runtime-apis/context/#waituntil).
81+
Unlike in Workers, `waitUntil` has no effect in Durable Objects. It exists only for API compatibility with the [Workers Runtime APIs](/workers/runtime-apis/context/#waituntil).
8282

83-
Refer to [Lifecycle of a Durable Object](/durable-objects/concepts/durable-object-lifecycle/) for more information.
83+
Durable Objects automatically remain active as long as there is ongoing work or pending I/O, so `waitUntil` is not needed. Refer to [Lifecycle of a Durable Object](/durable-objects/concepts/durable-object-lifecycle/) for more information.
8484
:::
8585

8686
#### Parameters

0 commit comments

Comments
 (0)