momento を Deno で使えないかと、試みたが失敗したので他のものを探していたら、次の記事を見つけました。
無料で使えるデータベース Upstash をご存知、ないのですか!?
公式サイトを見ると、キャッシュ以外に qStash というスケジュール形式のメッセージングソリューションのサービスをしているという記載があります。
Deno Deploy を間接的にスケジュール実行できそうな気がするのは魅力的に感じます。
というところでこの2つを試します。
参考
upstash redis
upstash redis を作成するところは、冒頭紹介したブログに記載が有るので、そちらを参考にします。
データベース名は test-db としました。
実装は以下の通り。(公式が Deno 向けに SDK を提供してくれているところは非常に最高。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import "https://deno.land/std@0.150.0/dotenv/load.ts"; import { Application, Router, Context } from "https://deno.land/x/oak/mod.ts"; import { Redis } from "https://deno.land/x/upstash_redis/mod.ts";
const redis = new Redis({ url: Deno.env.get("UPSTASH_URL"), token: Deno.env.get("UPSTASH_TOKEN"), });
const router = new Router(); router.get("/", async (context: Context) => { const count = await redis.get("count"); context.response.body = count; });
router.get("/update", async (context: Context) => { await redis.incr("count"); context.response.body = "updated"; });
const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods());
await app.listen({ port: 8080 });
|
以上の用意をして、サーバーを起動し curl で動作確認していくと次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12
| $ curl http://localhost:8080/ 1 $ curl http://localhost:8080/update updated $ curl http://localhost:8080/ 2 $ curl http://localhost:8080/update updated $ curl http://localhost:8080/update updated $ curl http://localhost:8080/ 4
|
書き込みと更新ができました。
(ざっと試したかったので update を get メソッドで呼んでいます。)
upstash qstash
先に作ったアプリは、/update にアクセスすると、値が増えるものです。
これを定期的に、実行してくれれば/ にアクセスするだけで内容が更新されます。
Deno Deploy 向けの説明 があったので、これを踏襲します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import "https://deno.land/std@0.150.0/dotenv/load.ts"; import { Application, Router, Context } from "https://deno.land/x/oak/mod.ts"; import { Redis } from "https://deno.land/x/upstash_redis/mod.ts"; import { Receiver } from "https://deno.land/x/upstash_qstash/mod.ts";
const redis = new Redis({ url: Deno.env.get("UPSTASH_URL"), token: Deno.env.get("UPSTASH_TOKEN"), })
const receiver = new Receiver({ currentSigningKey: Deno.env.get("QSTASH_CURRENT_SIGNING_KEY")!, nextSigningKey: Deno.env.get("QSTASH_NEXT_SIGNING_KEY")!, });
const router = new Router(); router.get("/", async(context:Context) => { const count = await redis.get("count"); context.response.body = count; });
router.post("/update", async(context:Context) => { const isValid = await receiver.verify({ signature: context.request.headers.get("Upstash-Signature")!, body: await context.request.body({ type: "text" }).value, }).catch((err: Error) => { console.error(err); return false; }); if (!isValid) { return new Response("Invalid signature", { status: 401 }); }
await redis.incr("count");
console.log("updated");
return new Response("OK", { status: 200 }); });
const app = new Application(); app.use(router.routes()); app.use(router.allowedMethods());
await app.listen({ port: 8080 });
|
こちらを deno deploy で稼働させて、qStash の設定をします。
ドキュメントには、200 系のメッセージが、返されるまで繰り返す。
とあるのですが、200 を返していても、1 分に 3 回程度繰り返しメッセージが到達しているようで、ドキュメント通りなのかははっきりとしません。
本番運用するなら、排他制御するとかの方法もありそうですが、GUI にはないリトライ回数オプションが curl では制御できました。
次のように設定します。
1 2 3 4 5
| $ curl -XPOST \ "https://qstash.upstash.io/v1/publish/https://hoge.deno.dev/update" \ -H "Authorization: Bearer hogehogehogehoge" \ -H "Upstash-Retries: 0" \ -H "Upstash-Cron: * * * * *"
|
リトライ回数を 0 にすると、到達件数が 1 件だけになった(ように見えます)。
必ずメッセージを受け取りたいという要件が有った場合には、これはこれでまずい気がします。
ということで、upStash を触ってみました。
確認のため 1 分に 1 回 qStash を呼び出すと早々に、リクエスト回数上限に達してしまい、有償プランに切り替えてしまいました。
面白いので、次回何か作る際のインフラ候補としてぜひ採用するでしょう。
ではでは。