← Cloudflare Durable Objects / durable-objects / api
Alarmy
Kontext
Alarmy Durable Objects umožňují naplánovat probuzení Durable Object v budoucím čase. Jakmile nastane naplánovaný čas alarmu, alarm() se zavolá metoda handleru. Alarmy se upravují pomocí Storage API, a operace s alarmy se řídí stejnými pravidly jako ostatní operace s úložištěm.
Stojí za zmínku:
- Každý Durable Object může najednou naplánovat jeden alarm zavoláním
setAlarm(). - Alarms mají zaručené provedení alespoň jednou a automaticky se opakují, když
alarm()handler vyvolá výjimku. - Opakované pokusy probíhají pomocí exponenciálního prodlužování intervalů, které začíná prodlevou 2 sekundy od prvního selhání, přičemž je povoleno až 6 opakování.
Alarms lze použít k vytváření distribuovaných primitiv, jako jsou fronty nebo dávkové zpracování práce nad Durable Objects. Alarms zároveň poskytují mechanismus, který zaručuje dokončení operací uvnitř Durable Object, aniž by bylo nutné spoléhat na příchozí požadavky udržující Durable Object naživu. Kompletní příklad najdete v Použití Alarms API.
Plánování více událostí pomocí jediného alarmu
Ačkoli může mít každý Durable Object nastavený vždy jen jeden alarm, můžete spravovat mnoho naplánovaných a opakujících se událostí tak, že si harmonogram událostí uložíte do úložiště a necháte alarm() handler zpracuje splatné události a poté se naplánuje na další.
import { DurableObject } from "cloudflare:workers";
export class AgentServer extends DurableObject {
// Schedule a one-time or recurring event
async scheduleEvent(id, runAt, repeatMs = null) {
await this.ctx.storage.put(`event:${id}`, { id, runAt, repeatMs });
const currentAlarm = await this.ctx.storage.getAlarm();
if (!currentAlarm || runAt < currentAlarm) {
await this.ctx.storage.setAlarm(runAt);
}
}
async alarm() {
const now = Date.now();
const events = await this.ctx.storage.list({ prefix: "event:" });
let nextAlarm = null;
for (const [key, event] of events) {
if (event.runAt <= now) {
await this.processEvent(event);
if (event.repeatMs) {
event.runAt = now + event.repeatMs;
await this.ctx.storage.put(key, event);
} else {
await this.ctx.storage.delete(key);
}
}
// Track the next event time
if (event.runAt > now && (!nextAlarm || event.runAt < nextAlarm)) {
nextAlarm = event.runAt;
}
}
if (nextAlarm) await this.ctx.storage.setAlarm(nextAlarm);
}
async processEvent(event) {
// Your event handling logic here
}
}Metody úložiště
getAlarm
-
getAlarm():number | null-
Pokud je nastaven alarm, vrátí se aktuálně nastavený čas alarmu jako počet milisekund od začátku UNIX epochy. V opačném případě se vrátí
null. -
Pokud
getAlarmje volán, zatímcoalarmuž běží, vrátínullledažesetAlarmbyla také zavolána od chvíle, kdy se spustil handler alarmu.
-
setAlarm
-
setAlarm(scheduledTimeMs:number)void- Nastavte čas spuštění alarmu. Čas zadejte jako počet milisekund od začátku UNIX epochy.
- Pokud zavoláte
setAlarmpokud je již jeden naplánován, přepíše se tím stávající alarm.
deleteAlarm
-
deleteAlarm():void-
Pokud je aktuálně nastavený nějaký alarm, zrušte ho.
-
Volání
deleteAlarm()uvnitřalarm()handler se může s nejlepším úsilím pokusit zabránit opakováním, není to však zaručeno.
-
Metody handleru
alarm
-
alarm(alarmInfo:Object)void-
Systém tuto metodu volá, jakmile nastane naplánovaný čas alarmu.
-
Volitelný parametr
alarmInfoobjekt má dvě vlastnosti:retryCountnumber: Počet opakování této alarmové události.isRetryboolean: Booleovská hodnota udávající, zda byl alarm zopakován. Tato hodnota jetruepokud je tato událost alarmu opakováním.
-
Pouze jedna instance
alarm()kdy poběží v daném okamžiku na jednu instanci Durable Object. -
alarm()má zaručeno spuštění alespoň jednou a v případě selhání se opakuje s exponenciálním prodlením, počínaje prodlevou 2 sekundy až po 6 opakování. Toto platí pouze pro nejnovějšísetAlarm()volání. Pokud metoda selže s nezachycenou výjimkou, budou provedeny opakované pokusy. -
Tuto metodu lze
async.
-
Příklad
Tento příklad ukazuje, jak nastavit alarmy pomocí setAlarm(timestamp) metodu a zpracujte alarmy pomocí alarm() handler ve vašem Durable Object.
-
alarm()handler se zavolá jednou pokaždé, když se spustí alarm. - Pokud neočekávaná chyba ukončí Durable Object,
alarm()handler může být znovu vytvořen na jiném stroji. - Po krátké prodlevě
alarm()handler spustí od začátku na jiném stroji.
import { DurableObject } from "cloudflare:workers";
export default {
async fetch(request, env) {
return await env.ALARM_EXAMPLE.getByName("foo").fetch(request);
},
};
const SECONDS = 1000;
export class AlarmExample extends DurableObject {
constructor(ctx, env) {
super(ctx, env);
this.storage = ctx.storage;
}
async fetch(request) {
// If there is no alarm currently set, set one for 10 seconds from now
let currentAlarm = await this.storage.getAlarm();
if (currentAlarm == null) {
this.storage.setAlarm(Date.now() + 10 * SECONDS);
}
}
async alarm() {
// The alarm handler will be invoked whenever an alarm fires.
// You can use this to do work, read from the Storage API, make HTTP calls
// and set future alarms to run using this.storage.setAlarm() from within this handler.
}
}import time
from workers import DurableObject, WorkerEntrypoint
class Default(WorkerEntrypoint):
async def fetch(self, request):
return await self.env.ALARM_EXAMPLE.getByName("foo").fetch(request)
SECONDS = 1000
class AlarmExample(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)
self.storage = ctx.storage
async def fetch(self, request):
# If there is no alarm currently set, set one for 10 seconds from now
current_alarm = await self.storage.getAlarm()
if current_alarm is None:
self.storage.setAlarm(int(time.time() * 1000) + 10 * SECONDS)
async def alarm(self):
# The alarm handler will be invoked whenever an alarm fires.
# You can use this to do work, read from the Storage API, make HTTP calls
# and set future alarms to run using self.storage.setAlarm() from within this handler.
passNásledující příklad ukazuje, jak použít alarmInfo vlastnost, podle které zjistíte, zda o zpracování dané alarmové události již byl proveden pokus.
class MyDurableObject extends DurableObject {
async alarm(alarmInfo) {
if (alarmInfo?.retryCount != 0) {
console.log(
"This alarm event has been attempted ${alarmInfo?.retryCount} times before.",
);
}
}
}class MyDurableObject(DurableObject):
async def alarm(self, alarm_info):
if alarm_info and alarm_info.get('retryCount', 0) != 0:
print(f"This alarm event has been attempted {alarm_info.get('retryCount')} times before.")Související zdroje
- Seznamte se s tím, jak použijte Alarms API v ukázkovém příkladu od začátku do konce.
- Přečtěte si Blogový příspěvek oznamující alarmy Durable Objects ↗.
- Zkontrolujte Storage API dokumentaci k Durable Objects.