ホームページ >ウェブフロントエンド >jsチュートリアル >BullMQ を使用した SvelteKit のバックグラウンド ジョブ

BullMQ を使用した SvelteKit のバックグラウンド ジョブ

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-26 08:32:11201ブラウズ

SvelteKit アプリは、電子メールの送信、画像のサイズ変更、データの処理などのタスクに苦労していませんか? BullMQ を使用すると、これらの重いジョブをバックグラウンドにオフロードし、アプリを超高速に保つことができます。この投稿では、それを設定し、プロのように実際のタスクに取り組む方法を説明します。飛び込んでみましょう!

tl;drhooks.server.js で BullMQ ワーカーをセットアップします。例を確認してください

BullMQとは何ですか?

BullMQ は、Redis でジョブ キューを作成および管理するための Node.js ライブラリです。時間のかかるタスクをバックグラウンドで効率的に実行するのに役立ちます。 BullMQ は、再試行、ジョブ スケジュール、同時実行制御などの組み込み機能を使用して、アプリ内での複雑なワークフローの処理をシンプルかつ信頼性の高いものにします。

ステップ 1: 依存関係をインストールする

まず、ioredis (node.js の Redis クライアント) と bullmq をインストールします。

pnpm i -D ioredis bullmq

Vercel のようなサーバーレス環境から bullmq キューにジョブを追加することはできますが、ワーカーは従来の長期間存続する Node.js サーバー上で実行する必要があります。したがって、adapter-auto をadapter-node:
に置き換えます。

pnpm rm @sveltejs/adapter-auto && pnpm i -D @sveltejs/adapter-node

新しくインストールしたノード アダプターで Svelte 構成 (svelte.config.js) を更新することを忘れないでください。

ステップ 2: ジョブ キューとプロセッサをセットアップする

次に、BullMQ ジョブ キューとそのプロセッサを設定しましょう。 src/lib/server/ ディレクトリに .js ファイルを作成します:

// src/lib/server/background-jobs.js

import { REDIS_URL } from "$env/static/private";
import { Queue, Worker } from "bullmq";
import IORedis from "ioredis";

const Q_NAME = "q";

export const jobsQueue = new Queue(Q_NAME, {
  connection: new IORedis(REDIS_URL),
});

const sleep = (t) => new Promise((resolve) => setTimeout(resolve, t * 100));

export const setupBullMQProcessor = () => {
  new Worker(
    Q_NAME,
    async (job) => {
      for (let i = 0; i <= 100; i++) {
        await sleep(Math.random());
        await job.updateProgress(i);
        await job.log(`Processing job at interval ${i}`);

        if (Math.random() * 200 < 1) throw new Error(`Random error at ${i}`);
      }

      return `This is the return value of job (${job.id})`;
    },
    // https://docs.bullmq.io/bull/patterns/persistent-connections#maxretriesperrequest
    { connection: new IORedis(REDIS_URL, { maxRetriesPerRequest: null }) }
  );
};

ここでは、キュー Q_NAME 内のジョブをリッスンして処理する BullMQ ワーカーをインスタンス化するユーティリティ関数も作成しました。

この関数は、hooks.server.js ファイル内で、トップレベルまたは init フック内で呼び出す必要があります。

// src/hooks.server.js

// ...
import { building } from "$app/environment";
import { setupBullMQProcessor } from "$lib/server/background-jobs";
// ...
if (!building) {
  setupBullMQProcessor();
}
// ...

!building チェックでは、ビルド中のワーカー (および Redis 接続) のセットアップがスキップされ、プロセスが高速化されます。

? BullMQ を SvelteKit アプリで使用できるようになりました ?

デモタイム

セットアップをテストするために、ジョブをキューに入れるための POST エンドポイントを作成しましょう。

// src/routes/+server.ts

import { jobsQueue } from "$lib/server/background-jobs";

export const POST = async () => {
  const { id: jobId } = await jobsQueue.add("job", {});

  /*
  The following code passes the job's progress to the client as a stream.
  If you don't need to update the client with the progress, you can skip
  the following. You can also use web-sockets or polling for that.
  */
  const stream = new ReadableStream({
    async pull(controller) {
      const job = await jobsQueue.getJob(jobId);
      controller.enqueue(
        JSON.stringify(
          job.failedReason
            ? { error: job.failedReason }
            : job.returnvalue
            ? { data: job.returnvalue }
            : { progress: job.progress }
        )
      );
      controller.enqueue("\n");

      if (job.finishedOn) {
        controller.close();
      }

      // wait for 1-second before sending the next status update
      await new Promise((r) => setTimeout(r, 1e3));
    },
  });

  return new Response(stream, {
    headers: { "content-type": "text/plain" },
  });
};

フロントエンドで、上記のエンドポイントをトリガーし、その後ジョブのステータスを表示するボタンを追加しましょう:

<!-- src/routes/+page.svelte -->

<script>
  let result = $state();

  $inspect(result);

  const handleClick = async () => {
    const response = await fetch("/", { method: "post" });
    const reader = await response.body.getReader();
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      result = JSON.parse(new TextDecoder().decode(value));
    }

    setTimeout(() => (result = undefined), 3e3);
  };
</script>

{#if result?.error}
  <div>



<p>Here is the output:</p>

<p><img src="https://img.php.cn/upload/article/000/000/000/173785153552047.jpg" alt="background jobs demo using sveltekit and bullmq" loading="lazy"    style="max-width:90%"  style="max-width:90%" data-animated="true"></p>


<hr>

<h3>
  
  
  Bonus ?
</h3>

<p>You can also mount a bull-board dashboard in your SvelteKit app for easy monitoring of background jobs.</p>

<p>Install bull-board dependencies<br>
</p>

<pre class="brush:php;toolbar:false">pnpm i -D @bull-board/api @bull-board/hono @hono/node-server hono

そして、hooks.server.js を変更します:

// src/hooks.server.js

import { building } from "$app/environment";
import { jobsQueue, setupBullMQProcessor } from "$lib/server/background-jobs";
import { createBullBoard } from "@bull-board/api";
import { BullMQAdapter } from "@bull-board/api/bullMQAdapter";
import { HonoAdapter } from "@bull-board/hono";
import { serveStatic } from "@hono/node-server/serve-static";
import { Hono } from "hono";

if (!building) {
  setupBullMQProcessor();
}

const bullboard = (() => {
  const serverAdapter = new HonoAdapter(serveStatic);

  createBullBoard({
    queues: [new BullMQAdapter(jobsQueue)],
    serverAdapter,
  });
  const app = new Hono({ strict: false });
  const basePath = "/jobs";
  serverAdapter.setBasePath(basePath);
  app.route(basePath, serverAdapter.registerPlugin());

  return app;
})();

export const handle = async ({ event, resolve }) => {
  if (event.url.pathname.match(/^\/jobs($|\/)/)) {
    return bullboard.fetch(event.request);
  }

  return resolve(event);
};

次に、/jobs にアクセスして、ブルボード ダッシュボードを表示します

bull-board dashboard

以上がBullMQ を使用した SvelteKit のバックグラウンド ジョブの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。