Loading docs/manual/mq.md +79 −0 Original line number Diff line number Diff line Loading @@ -222,3 +222,82 @@ const federation = createFederation<void>({ > If your [inbox listeners](./inbox.md) are CPU-bound, you should consider > running multiple nodes of your application so that each node can process > messages in parallel with the shared message queue. Separating message processing from the main process --------------------------------------------------- *This API is available since Fedify 0.12.0.* On high-traffic servers, it's common to separate message processing from the main server process to avoid blocking the main event loop. To achieve this, you can use the `~CreateFederationOptions.manuallyStartQueue` option and `Federation.startQueue()` method: ::: code-group ~~~~ typescript{11-15} twoslash [Deno] import type { KvStore } from "@fedify/fedify"; // ---cut-before--- import { createFederation } from "@fedify/fedify"; import { RedisMessageQueue } from "@fedify/redis"; import Redis from "ioredis"; const federation = createFederation<void>({ queue: new RedisMessageQueue(() => new Redis()), manuallyStartQueue: true, // [!code highlight] // ... other options // ---cut-start--- kv: null as unknown as KvStore, // ---cut-end--- }); // Start the message queue manually only in worker nodes. // On non-worker nodes, the queue won't be started. if (Deno.env.get("NODE_TYPE") === "worker") { await federation.startQueue(); } ~~~~ ~~~~ typescript{12-16} twoslash [Node.js/Bun] import type { KvStore } from "@fedify/fedify"; // ---cut-before--- import { createFederation } from "@fedify/fedify"; import { RedisMessageQueue } from "@fedify/redis"; import Redis from "ioredis"; import { env } from "node:process"; const federation = createFederation<void>({ queue: new RedisMessageQueue(() => new Redis()), manuallyStartQueue: true, // [!code highlight] // ... other options // ---cut-start--- kv: null as unknown as KvStore, // ---cut-end--- }); // Start the message queue manually only in worker nodes. // On non-worker nodes, the queue won't be started. if (env.NODE_TYPE === "worker") { await federation.startQueue(); } ~~~~ ::: The key point is to ensure that messages are enqueued only from the `NODE_TYPE=web` nodes, and messages are processed only from the `NODE_TYPE=worker` nodes: | `NODE_TYPE` | Process messages? | Enqueue messages? | |-------------|-------------------|-------------------| | `web` | Do not process | Enqueue | | `worker` | Process | Do not enqueue | This separation allows you to scale your application by running multiple worker nodes that process messages concurrently. It also helps to keep the main server process responsive by offloading message processing to worker nodes. > [!NOTE] > To ensure that messages are enqueued only from the `NODE_TYPE=web` nodes, > you should not place the `NODE_TYPE=worker` nodes behind a load balancer. docs/package.json +1 −1 Original line number Diff line number Diff line { "devDependencies": { "@deno/kv": "^0.8.2", "@fedify/fedify": "1.0.0-dev.407", "@fedify/fedify": "1.0.0-dev.408", "@fedify/redis": "^0.1.1", "@hono/node-server": "^1.12.2", "@js-temporal/polyfill": "^0.4.4", Loading docs/pnpm-lock.yaml +5 −5 Original line number Diff line number Diff line Loading @@ -12,8 +12,8 @@ importers: specifier: ^0.8.2 version: 0.8.2 '@fedify/fedify': specifier: 1.0.0-dev.407 version: 1.0.0-dev.407(web-streams-polyfill@3.3.3) specifier: 1.0.0-dev.408 version: 1.0.0-dev.408(web-streams-polyfill@3.3.3) '@fedify/redis': specifier: ^0.1.1 version: 0.1.1(web-streams-polyfill@3.3.3) Loading Loading @@ -370,8 +370,8 @@ packages: '@fedify/fedify@0.10.2': resolution: {integrity: sha512-GKxm+NZ1zNPJ9HTbTW+Y2o/HT3Rk6ly+j/GJfjXBFiwm391Ni56VYC8ON/KQsFdFYIp+eNMn1hWr0RbFtMwoOg==} '@fedify/fedify@1.0.0-dev.407': resolution: {integrity: sha512-VYbsOkaS+lsBg3JgOTXcG4GDyCD7GcOBvjn1f/K37EDqPUjmuqPJuhBquiTz+EffFpHKqJ10A0i78rHufa8U7g==} '@fedify/fedify@1.0.0-dev.408': resolution: {integrity: sha512-Lln5Ln0lCCgrskhVN4YibDBgTeuHA2nyT2r3szeXi81j6vNGxpRzdHQ+0wBSglrR17X+EtHlMltsrCCmXbDFsQ==} '@fedify/redis@0.1.1': resolution: {integrity: sha512-oKhOVYLRwkRf/tuePoT3CnwXUKm5rTE7hDg8/qfVo/txmydPPptXzPG10kL24zCv8t18FwmyaE0LlcrUrxd6FQ==} Loading Loading @@ -1974,7 +1974,7 @@ snapshots: transitivePeerDependencies: - web-streams-polyfill '@fedify/fedify@1.0.0-dev.407(web-streams-polyfill@3.3.3)': '@fedify/fedify@1.0.0-dev.408(web-streams-polyfill@3.3.3)': dependencies: '@deno/shim-crypto': 0.3.1 '@deno/shim-deno': 0.18.2 Loading Loading
docs/manual/mq.md +79 −0 Original line number Diff line number Diff line Loading @@ -222,3 +222,82 @@ const federation = createFederation<void>({ > If your [inbox listeners](./inbox.md) are CPU-bound, you should consider > running multiple nodes of your application so that each node can process > messages in parallel with the shared message queue. Separating message processing from the main process --------------------------------------------------- *This API is available since Fedify 0.12.0.* On high-traffic servers, it's common to separate message processing from the main server process to avoid blocking the main event loop. To achieve this, you can use the `~CreateFederationOptions.manuallyStartQueue` option and `Federation.startQueue()` method: ::: code-group ~~~~ typescript{11-15} twoslash [Deno] import type { KvStore } from "@fedify/fedify"; // ---cut-before--- import { createFederation } from "@fedify/fedify"; import { RedisMessageQueue } from "@fedify/redis"; import Redis from "ioredis"; const federation = createFederation<void>({ queue: new RedisMessageQueue(() => new Redis()), manuallyStartQueue: true, // [!code highlight] // ... other options // ---cut-start--- kv: null as unknown as KvStore, // ---cut-end--- }); // Start the message queue manually only in worker nodes. // On non-worker nodes, the queue won't be started. if (Deno.env.get("NODE_TYPE") === "worker") { await federation.startQueue(); } ~~~~ ~~~~ typescript{12-16} twoslash [Node.js/Bun] import type { KvStore } from "@fedify/fedify"; // ---cut-before--- import { createFederation } from "@fedify/fedify"; import { RedisMessageQueue } from "@fedify/redis"; import Redis from "ioredis"; import { env } from "node:process"; const federation = createFederation<void>({ queue: new RedisMessageQueue(() => new Redis()), manuallyStartQueue: true, // [!code highlight] // ... other options // ---cut-start--- kv: null as unknown as KvStore, // ---cut-end--- }); // Start the message queue manually only in worker nodes. // On non-worker nodes, the queue won't be started. if (env.NODE_TYPE === "worker") { await federation.startQueue(); } ~~~~ ::: The key point is to ensure that messages are enqueued only from the `NODE_TYPE=web` nodes, and messages are processed only from the `NODE_TYPE=worker` nodes: | `NODE_TYPE` | Process messages? | Enqueue messages? | |-------------|-------------------|-------------------| | `web` | Do not process | Enqueue | | `worker` | Process | Do not enqueue | This separation allows you to scale your application by running multiple worker nodes that process messages concurrently. It also helps to keep the main server process responsive by offloading message processing to worker nodes. > [!NOTE] > To ensure that messages are enqueued only from the `NODE_TYPE=web` nodes, > you should not place the `NODE_TYPE=worker` nodes behind a load balancer.
docs/package.json +1 −1 Original line number Diff line number Diff line { "devDependencies": { "@deno/kv": "^0.8.2", "@fedify/fedify": "1.0.0-dev.407", "@fedify/fedify": "1.0.0-dev.408", "@fedify/redis": "^0.1.1", "@hono/node-server": "^1.12.2", "@js-temporal/polyfill": "^0.4.4", Loading
docs/pnpm-lock.yaml +5 −5 Original line number Diff line number Diff line Loading @@ -12,8 +12,8 @@ importers: specifier: ^0.8.2 version: 0.8.2 '@fedify/fedify': specifier: 1.0.0-dev.407 version: 1.0.0-dev.407(web-streams-polyfill@3.3.3) specifier: 1.0.0-dev.408 version: 1.0.0-dev.408(web-streams-polyfill@3.3.3) '@fedify/redis': specifier: ^0.1.1 version: 0.1.1(web-streams-polyfill@3.3.3) Loading Loading @@ -370,8 +370,8 @@ packages: '@fedify/fedify@0.10.2': resolution: {integrity: sha512-GKxm+NZ1zNPJ9HTbTW+Y2o/HT3Rk6ly+j/GJfjXBFiwm391Ni56VYC8ON/KQsFdFYIp+eNMn1hWr0RbFtMwoOg==} '@fedify/fedify@1.0.0-dev.407': resolution: {integrity: sha512-VYbsOkaS+lsBg3JgOTXcG4GDyCD7GcOBvjn1f/K37EDqPUjmuqPJuhBquiTz+EffFpHKqJ10A0i78rHufa8U7g==} '@fedify/fedify@1.0.0-dev.408': resolution: {integrity: sha512-Lln5Ln0lCCgrskhVN4YibDBgTeuHA2nyT2r3szeXi81j6vNGxpRzdHQ+0wBSglrR17X+EtHlMltsrCCmXbDFsQ==} '@fedify/redis@0.1.1': resolution: {integrity: sha512-oKhOVYLRwkRf/tuePoT3CnwXUKm5rTE7hDg8/qfVo/txmydPPptXzPG10kL24zCv8t18FwmyaE0LlcrUrxd6FQ==} Loading Loading @@ -1974,7 +1974,7 @@ snapshots: transitivePeerDependencies: - web-streams-polyfill '@fedify/fedify@1.0.0-dev.407(web-streams-polyfill@3.3.3)': '@fedify/fedify@1.0.0-dev.408(web-streams-polyfill@3.3.3)': dependencies: '@deno/shim-crypto': 0.3.1 '@deno/shim-deno': 0.18.2 Loading