Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deno Queue を使って OGP画像の遅延作成をやってみる

Deno Queue を使って OGP画像の遅延作成をやってみる

Deno Deploy でホストしたWebアプリケーションに、投稿に内容に伴ったOGP画像作成を Deno Queue を使って遅延実行する

- Deno でOGP画像を作るには
- Deno Deploy にOGP画像を保持するには
- Deno Queue でOGP画像作成を遅延実行

More Decks by 虎の穴ラボ株式会社

Other Decks in Technology

Transcript

  1. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. T

    O R A N O A N A L a b 2024 Deno Queue を使って OGP画像の遅延作成をやってみる 2024/5/15 toranoana.deno #16 虎の穴ラボ株式会社 奥谷 一陽
  2. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    自己紹介 奥谷 一陽 所属:虎の穴ラボ株式会社 興味:Deno、TypeScript 最近興味があるパッケージ:Effect X:@okutann88 github:Octo8080X
  3. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    アジェンダ - Deno でOGP画像を作るには - Deno Deploy にOGP画像を保持するには - Deno Queue でOGP画像作成を遅延実行
  4. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    こんなものを作っています

  5. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Echo-Echo - Fresh + hono - ストレージにDeno KV を採用 - Deno Deploy で稼働 - 20秒までの短い音を投稿できるサイト Echo-Echo について詳しくはこちら https://speakerdeck.com/toranoana/freshto honodedeno-kvwoshi-idao-su
  6. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    今回やりたいこと
 「Deno Deployにホストしたサイトで
 投稿に即したOGPを作りたい」

  7. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno で画像を扱えるモジュール - ImageScript:画像編集 - terminal_images:画像表示 - DenoChart:グラフ画像作成 - satori:JSX + CSS でSVGを作成できる - svg2png-wasm:SVGをpngに変換できる など 採用
  8. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno でOGP画像を作るには tsx + css - (satori) -> SVG - (svg2png-wasm) -> PNG で処理 import satori from "npm:satori"; import * as svg2png from "npm:svg2png-wasm"; await svg2png.initialize( await fetch("https://unpkg.com/svg2png-wasm/svg2png_wasm_bg.wasm"), ); export async function createOgp(id: string) { const svg = await satori( <div style={{ backgroundColor: info.colorCode, width: 600, height: 315, display: "flex", }} > *** </div>, { width: 600, height: 315, }, ); const convert_options: svg2png.ConverterOptions = { defaultFontFamily: { sansSerifFamily: "Noto Sans JP", }, }; const png = await svg2png.svg2png(svg, convert_options); }
  9. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno でOGP画像を作るには tsx + css - (satori) -> SVG - (svg2png-wasm) -> PNG で処理 import satori from "npm:satori"; import * as svg2png from "npm:svg2png-wasm"; await svg2png.initialize( await fetch("https://unpkg.com/svg2png-wasm/svg2png_wasm_bg.wasm"), ); export async function createOgp(id: string) { const svg = await satori( <div style={{ backgroundColor: info.colorCode, width: 600, height: 315, display: "flex", }} > *** </div>, { width: 600, height: 315, }, ); const convert_options: svg2png.ConverterOptions = { defaultFontFamily: { sansSerifFamily: "Noto Sans JP", }, }; const png = await svg2png.svg2png(svg, convert_options); }
  10. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Deploy にOGP画像を保持するには

  11. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Deploy にOGP画像を保持するには Deno Deployにホストしたアプリケーションで、 動的に作られた画像を保持する方法として、 - 外部のS3など - Deno KV などが選択肢になる 採用
  12. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Deploy にOGP画像を保持するには 今回は、Deno KVの1レコードで画像を保持したい。 最初に1200 x 630 の画像を作ったが容量不足だった => 600 x 315 にサイズ変更にして対応
  13. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Queue で
 OGP画像作成を遅延実行

  14. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Queue でOGP画像作成を遅延実行 - Deno Queue は enqueue した内容を listenQueue で受け付ける   例 // app.ts const kv = await Deno.openKv(); kv.listenQueue((msg: unknown) => { console.log("listen message"); console.log(">> " + msg); }); await kv.enqueue("message 1", { delay: 1000 * 3 }); console.log("enqueue message"); > deno run --unstable-kv app.ts enqueue message listen message # << 3秒経過したら表示 >> message 1
  15. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Queue でOGP画像作成を遅延実行 Deno Queue をFreshに導入した - listenQueue // utils/queues.ts import { createOgp } from "./create_ogp.tsx"; interface OgpMessage { type: "createOgp"; id: string; } function createOgpMessage(id: string) { return { type: "createOgp", id, }; } export async function callCreateOgp(id: string) { const kv = await Deno.openKv(); await kv.enqueue(createOgpMessage(id), { delay: 3000 }); } export async function listenQueue() { console.log("[START listenQueue]"); const kv = await Deno.openKv(); kv.listenQueue((msg: OgpMessage) => { if (msg.type === "createOgp") { createOgp(msg.id); } }); } // main.ts (抜粋) import "$std/dotenv/load.ts"; import { start } from "$fresh/server.ts"; import manifest from "./fresh.gen.ts"; import config from "./fresh.config.ts"; import { deleteData } from "./tasks/delete_task.ts"; import { listenQueue } from "./utils/queues.ts"; Deno.cron("Delete Task", "0 0 * * *", () => { deleteData(); }); listenQueue(); await start(manifest, config); main.ts でlistenQueueする処理の 呼び出しを行う
  16. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Queue でOGP画像作成を遅延実行 Deno Queue をFreshに導入した - enqueue // utils/queues.ts import { createOgp } from "./create_ogp.tsx"; interface OgpMessage { type: "createOgp"; id: string; } function createOgpMessage(id: string) { return { type: "createOgp", id, }; } export async function callCreateOgp(id: string) { const kv = await Deno.openKv(); await kv.enqueue(createOgpMessage(id), { delay: 3000 }); } export async function listenQueue() { console.log("[START listenQueue]"); const kv = await Deno.openKv(); kv.listenQueue((msg: OgpMessage) => { if (msg.type === "createOgp") { createOgp(msg.id); } }); } // routes/api/[...path].ts(抜粋) import { callCreateOgp } from "../../utils/queues.ts"; const app = new OpenAPIHono(); const appRoutes = app // POST /api/recording .openapi(postRecordsRoute, async (c) => { const formData = await c.req.formData(); const blob = formData.get("file") as Blob; const title = formData.get("title") as string; const file = new Uint8Array(await blob.arrayBuffer()); const result = await saveRecord(title, file); await callCreateOgp(result.id); return c.json({ message: "OK", url: `/play/${result.id}` }); }) リクエストで enqueue する処理を呼び出し 今回の実装では、3秒後にOGP画像を作成開始
  17. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    Deno Queue でOGP画像作成を遅延実行 Deno Queue をFreshに導入した // utils/queues.ts import { createOgp } from "./create_ogp.tsx"; interface OgpMessage { type: "createOgp"; id: string; } function createOgpMessage(id: string) { return { type: "createOgp", id, }; } export async function callCreateOgp(id: string) { const kv = await Deno.openKv(); await kv.enqueue(createOgpMessage(id), { delay: 3000 }); } export async function listenQueue() { console.log("[START listenQueue]"); const kv = await Deno.openKv(); kv.listenQueue((msg: OgpMessage) => { if (msg.type === "createOgp") { createOgp(msg.id); } }); } 今回遅延処理する内容は、OGP作成だけ。 しかし、他の処理もさせることを想定して、 処理内容を区別できるように実装。 キューイングできるのが、オブジェクトなのが 効いている!
  18. Copyright (C) 2023 Toranoana Lab Inc. All Rights Reserved. 2024

    まとめ - Deno Deploy で画像が作成できる - Deno KVにデータをホストする場合、画像サイズに注意 - もし大きなものをホストしたい場合、kvdex や、kv-toolboxを検討する - さらに大きいなら、外部ストレージを検討する - Deno Queue は、オブジェクトでキューイングできるのはメリット - 重めな処理をどんどん、キューに入れてみよう