deno.com
本页内容

安排未来日期的通知

队列的一个常见用例是安排在未来某个时间完成的工作。为了演示其工作原理,我们提供了一个示例应用程序(如下所述),该应用程序通过 Courier API 安排通知消息。该应用程序在 Deno Deploy 上运行,使用内置的 KV 和队列 API 实现,无需任何配置即可使用。

下载并配置示例 跳转到标题

⬇️ 在此处下载或克隆完整的示例应用程序

您可以按照 GitHub 仓库的 README 文件中的说明自行运行和部署此示例应用程序。

要运行上述示例应用程序,您还需要注册 Courier。当然,您将在应用程序中看到的技术同样适用于任何通知服务,从 Amazon SNSTwilio,但 Courier 提供了一个易于使用的通知 API,您可以使用个人 GMail 帐户进行测试(除了它能做的所有其他酷炫功能)。

核心功能 跳转到标题

在设置和运行项目后,我们希望您关注代码中实现调度机制的几个关键部分。

在应用启动时连接到 KV 并添加监听器 跳转到标题

示例应用程序的大部分功能位于顶层目录的 server.tsx 中。当 Deno 应用程序进程启动时,它会创建与 Deno KV 实例的连接,并附加一个事件处理程序,该处理程序将处理从队列接收到的消息。

server.tsx
// 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 函数,延迟五秒钟后发送通知电子邮件。

server.tsx
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 的源代码,我们用它来描述系统中通知的属性。

notification.ts
// 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 中,我们使用导出的类型守卫来确保我们响应的是正确的消息类型。

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 的更多信息可以在他们的参考文档中找到。

server.tsx
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",
      },
    },
  }),
});

您找到所需内容了吗?

隐私政策