排程未來日期的通知
佇列的一個常見使用案例是將工作排程在將來的某個時間點完成。
為了說明這是如何運作的,我們提供了一個範例應用程式 (如下所述),它排程透過 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 模組 的原始程式碼,我們使用它來描述系統中通知的屬性。
// 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",
},
},
}),
});