安排未来日期的通知
一个常见的用例是 队列 是安排在将来的某个时间完成的工作。为了帮助演示它是如何工作的,我们提供了一个示例应用程序(如下所述),该应用程序安排通过 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 类型,但我们可以使用 类型守卫 来告诉编译器我们期望的数据形状。
以下是 通知模块 的源代码,我们使用它来描述系统中通知的属性。
// 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",
},
},
}),
});