跳转到内容
搜索文档

使用 Alarms API

使用 Durable Objects Alarms API 批处理对 Durable Object 的请求。

最后更新 查看 MarkdownAgent 设置

此示例实现 alarm() 处理器,允许批处理对单个 Durable Object 的请求。

当收到请求且未设置 alarm 时,它将 alarm 设置为 10 秒后。alarm() 处理器处理在该 10 秒窗口内收到的所有请求。

如果未收到新请求,在下一个请求到达之前不会设置进一步的 alarm。

import { DurableObject } from "cloudflare:workers";

// Worker
export default {
	async fetch(request, env) {
		return await env.BATCHER.getByName("foo").fetch(request);
	},
};

// Durable Object
export class Batcher extends DurableObject {
	constructor(ctx, env) {
		super(ctx, env);
		this.storage = ctx.storage;
		this.ctx.blockConcurrencyWhile(async () => {
			let vals = await this.storage.list({ reverse: true, limit: 1 });
			this.count = vals.size == 0 ? 0 : parseInt(vals.keys().next().value);
		});
	}

	async fetch(request) {
		this.count++;

		// If there is no alarm currently set, set one for 10 seconds from now
		// Any further POSTs in the next 10 seconds will be part of this batch.
		let currentAlarm = await this.storage.getAlarm();
		if (currentAlarm == null) {
			this.storage.setAlarm(Date.now() + 1000 * 10);
		}

		// Add the request to the batch.
		await this.storage.put(this.count, await request.text());
		return new Response(JSON.stringify({ queued: this.count }), {
			headers: {
				"content-type": "application/json;charset=UTF-8",
			},
		});
	}

	async alarm() {
		let vals = await this.storage.list();
		await fetch("http://example.com/some-upstream-service", {
			method: "POST",
			body: Array.from(vals.values()),
		});
		await this.storage.deleteAll();
		this.count = 0;
	}
}
from workers import DurableObject, Response, WorkerEntrypoint, fetch
import time

# Worker
class Default(WorkerEntrypoint):
	async def fetch(self, request):
		stub = self.env.BATCHER.getByName("foo")
		return await stub.fetch(request)

# Durable Object
class Batcher(DurableObject):
	def __init__(self, ctx, env):
		super().__init__(ctx, env)
		self.storage = ctx.storage

		@self.ctx.blockConcurrencyWhile
		async def initialize():
			vals = await self.storage.list(reverse=True, limit=1)
			self.count = 0
			if len(vals) > 0:
			    self.count = int(vals.keys().next().value)

	async def fetch(self, request):
		self.count += 1

		# If there is no alarm currently set, set one for 10 seconds from now
		# Any further POSTs in the next 10 seconds will be part of this batch.
		current_alarm = await self.storage.getAlarm()
		if current_alarm is None:
			self.storage.setAlarm(int(time.time() * 1000) + 1000 * 10)

		# Add the request to the batch.
		await self.storage.put(self.count, await request.text())
		return Response.json(
			{"queued": self.count}
		)

	async def alarm(self):
		vals = await self.storage.list()
		await fetch(
			"http://example.com/some-upstream-service",
			method="POST",
			body=list(vals.values())
		)
		await self.storage.deleteAll()
		self.count = 0

alarm() 处理器将每 10 秒调用一次。如果意外错误终止 Durable Object,alarm() 处理器将在另一台机器上重新实例化。短暂延迟后,alarm() 处理器将在另一台机器上从头运行。

最后,配置 Wrangler 文件以包含基于先前选择的 namespace 和类名称的 Durable Object 绑定迁移

{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "durable-object-alarm",
	"main": "src/index.ts",
	"durable_objects": {
		"bindings": [
			{
				"name": "BATCHER",
				"class_name": "Batcher"
			}
		]
	},
	"migrations": [
		{
			"tag": "v1",
			"new_sqlite_classes": [
				"Batcher"
			]
		}
	]
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "durable-object-alarm"
main = "src/index.ts"

[[durable_objects.bindings]]
name = "BATCHER"
class_name = "Batcher"

[[migrations]]
tag = "v1"
new_sqlite_classes = [ "Batcher" ]

这篇文档对您有帮助吗?