Heim > Web-Frontend > js-Tutorial > Hintergrundjobs in SvelteKit mit BullMQ

Hintergrundjobs in SvelteKit mit BullMQ

Linda Hamilton
Freigeben: 2025-01-26 08:32:11
Original
263 Leute haben es durchsucht

Hat Ihre SvelteKit-App Probleme mit Aufgaben wie dem Versenden von E-Mails, der Größenänderung von Bildern oder der Verarbeitung von Daten? Mit BullMQ können Sie diese schweren Aufgaben in den Hintergrund verlagern und Ihre App blitzschnell halten. In diesem Beitrag zeigen wir Ihnen, wie Sie es einrichten und reale Aufgaben wie ein Profi bewältigen. Lasst uns eintauchen!

tl;dr Richten Sie BullMQ-Worker in Hooks.server.js ein. Schauen Sie sich das Beispiel an

Was ist BullMQ?

BullMQ ist eine Node.js-Bibliothek zum Erstellen und Verwalten von Jobwarteschlangen mit Redis. Es hilft Ihnen, zeitaufwändige Aufgaben effizient im Hintergrund auszuführen. Mit integrierten Funktionen wie Wiederholungsversuchen, Auftragsplanung und Parallelitätskontrolle macht BullMQ die Handhabung komplexer Arbeitsabläufe in Ihrer App einfach und zuverlässig.

Schritt 1: Abhängigkeiten installieren

Installieren Sie zunächst ioredis (Redis-Client für node.js) und bullmq:

pnpm i -D ioredis bullmq
Nach dem Login kopieren

Auch wenn Sie aus einer serverlosen Umgebung wie Vercel Jobs zu einer Bullmq-Warteschlange hinzufügen können, müssen die Worker auf einem herkömmlichen, langlebigen node.js-Server ausgeführt werden. Ersetzen Sie daher „adapter-auto“ durch „adapter-node:
“.

pnpm rm @sveltejs/adapter-auto && pnpm i -D @sveltejs/adapter-node
Nach dem Login kopieren

Vergessen Sie nicht, Ihre Svelte-Konfiguration (svelte.config.js) mit dem neu installierten Knotenadapter zu aktualisieren.

Schritt 2: Jobwarteschlange und Prozessor einrichten

Als nächstes richten wir eine BullMQ-Jobwarteschlange und ihren Prozessor ein. Erstellen Sie eine .js-Datei im Verzeichnis src/lib/server/:

// 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 }) }
  );
};

Nach dem Login kopieren

Hier haben wir auch eine Hilfsfunktion erstellt, die einen BullMQ-Worker instanziiert, der auf Jobs in der Warteschlange Q_NAME wartet und diese verarbeitet.

Wir müssen diese Funktion in unserer Datei „hooks.server.js“ aufrufen – entweder auf der obersten Ebene oder innerhalb des Init-Hooks.

// src/hooks.server.js

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

Die !building-Prüfung überspringt das Einrichten des Workers (und damit einer Redis-Verbindung) während des Builds und beschleunigt so den Prozess.

? BullMQ kann jetzt in unserer SvelteKit-App verwendet werden ?

Demozeit

Um das Setup zu testen, erstellen wir einen POST-Endpunkt, um einen Job in die Warteschlange zu stellen.

// 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" },
  });
};
Nach dem Login kopieren

Und im Frontend fügen wir eine Schaltfläche hinzu, um den oben genannten Endpunkt auszulösen und anschließend den Status des Jobs anzuzeigen:

<!-- 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="/static/imghw/default1.png"  data-src="https://img.php.cn/upload/article/000/000/000/173785153552047.jpg"  class="lazy" 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
Nach dem Login kopieren

und ändern Sie Ihre 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);
};

Nach dem Login kopieren

Dann besuchen Sie /jobs, um das Bull-Board-Dashboard anzuzeigen

bull-board dashboard

Das obige ist der detaillierte Inhalt vonHintergrundjobs in SvelteKit mit BullMQ. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage