安排未来日期的通知
队列的一个常见用例是安排在未来某个时间完成的工作。为了演示其工作原理,我们提供了一个示例应用程序(如下所述),该应用程序通过 Courier API 安排通知消息。该应用程序在 Deno Deploy 上运行,使用内置的 KV 和队列 API 实现,无需任何配置即可使用。
下载并配置示例 跳转到标题
您可以按照 GitHub 仓库的 README
文件中的说明自行运行和部署此示例应用程序。
要运行上述示例应用程序,您还需要注册 Courier。当然,您将在应用程序中看到的技术同样适用于任何通知服务,从 Amazon SNS 到 Twilio,但 Courier 提供了一个易于使用的通知 API,您可以使用个人 GMail 帐户进行测试(除了它能做的所有其他酷炫功能)。
核心功能 跳转到标题
在设置和运行项目后,我们希望您关注代码中实现调度机制的几个关键部分。
在应用启动时连接到 KV 并添加监听器 跳转到标题
示例应用程序的大部分功能位于顶层目录的 server.tsx 中。当 Deno 应用程序进程启动时,它会创建与 Deno KV 实例的连接,并附加一个事件处理程序,该处理程序将处理从队列接收到的消息。
// Create a Deno KV database reference
const kv = await Deno.openKv();
// Create a queue listener that will process enqueued messages
kv.listenQueue(async (message) => {
/* ... implementation of listener here ... */
});
创建和安排通知 跳转到标题
在此演示应用程序中通过表单提交新订单后,将调用 enqueue
函数,延迟五秒钟后发送通知电子邮件。
app.post("/order", async (c) => {
const { email, order } = await c.req.parseBody();
const n: Notification = {
email: email as string,
body: `Order received for: "${order as string}"`,
};
// Select a time in the future - for now, just wait 5 seconds
const delay = 1000 * 5;
// Enqueue the message for processing!
kv.enqueue(n, { delay });
// Redirect back home with a success message!
setCookie(c, "flash_message", "Order created!");
return c.redirect("/");
});
在 TypeScript 中定义通知数据类型 跳转到标题
通常,在将数据推入或推出队列时,最好使用强类型对象。虽然队列消息最初是 unknown
TypeScript 类型,但我们可以使用类型守卫来告诉编译器我们期望的数据形状。
这是 notification module 的源代码,我们用它来描述系统中通知的属性。
// Shape of a notification object
export default interface Notification {
email: string;
body: string;
}
// Type guard for a notification object
export function isNotification(o: unknown): o is Notification {
return (
((o as Notification)?.email !== undefined &&
typeof (o as Notification).email === "string") &&
((o as Notification)?.body !== undefined &&
typeof (o as Notification).body === "string")
);
}
在 server.tsx
中,我们使用导出的类型守卫来确保我们响应的是正确的消息类型。
kv.listenQueue(async (message) => {
// Use type guard to short circuit early if the message is of the wrong type
if (!isNotification(message)) return;
// Grab the relevant data from the message, which TypeScript now knows
// is a Notification interface
const { email, body } = message;
// Create an email notification with Courier
// ...
});
发送 Courier API 请求 跳转到标题
为了按计划发送电子邮件,我们使用 Courier REST API。有关 Courier REST API 的更多信息可以在他们的参考文档中找到。
const response = await fetch("https://api.courier.com/send", {
method: "POST",
headers: {
Authorization: `Bearer ${COURIER_API_TOKEN}`,
},
body: JSON.stringify({
message: {
to: { email },
content: {
title: "New order placed by Deno!",
body: "notification body goes here",
},
},
}),
});