Initial Commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# `LocalWorker`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`LocalWorker<Ctx>` is an in-process executor — it runs `DistributedTask.execute` directly in the calling JavaScript event loop, with no IO indirection. Use it when the work can run on the same node as the dispatcher: tiny CPU jobs, fan-out across a thread, or local-only test setups. The constructor is parameterised by an `ExecutionContext` of type `Ctx`, which the worker passes verbatim into every `task.execute(input, ctx)` call.
|
||||
|
||||
## Features
|
||||
|
||||
- Inherits lifecycle, metrics, OTel emission, and FSM from `AbstractWorker`.
|
||||
- Generic over caller-defined `ExecutionContext`.
|
||||
- `getCapabilities()` advertises `{ hasFileSystemAccess: true, isRemote: false, contextType }` so strategies can route work accordingly.
|
||||
- `getType()` returns `"local"`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { LocalWorker } from "@suaveplan/queue-distribution/worker/local/local";
|
||||
import type { DistributedTask, ExecutionContext } from "@suaveplan/queue-distribution/task/task";
|
||||
|
||||
class EmptyContext implements ExecutionContext {}
|
||||
|
||||
const worker = new LocalWorker(new EmptyContext(), { capacity: 4 });
|
||||
await worker.start();
|
||||
|
||||
const task: DistributedTask<number, string> = {
|
||||
id: "format-number",
|
||||
execute: async (n) => `n=${n}`,
|
||||
getStatus: () => "PENDING",
|
||||
setStatus: () => {},
|
||||
getMetadata: () => ({ createdAt: new Date(), attempts: 0 }),
|
||||
};
|
||||
|
||||
const result = await worker.executeTask(task, 7); // "n=7"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Thread your dependency container through the `ExecutionContext` so every task gets access to the same logger, tracer, and DB client.
|
||||
|
||||
```ts
|
||||
import { LocalWorker } from "@suaveplan/queue-distribution/worker/local/local";
|
||||
import type { DistributedTask, ExecutionContext } from "@suaveplan/queue-distribution/task/task";
|
||||
|
||||
interface AppContext extends ExecutionContext {
|
||||
logger: { info: (m: string) => void };
|
||||
db: { query: (sql: string) => Promise<unknown> };
|
||||
}
|
||||
|
||||
const ctx: AppContext = {
|
||||
logger: { info: console.log },
|
||||
db: { query: async () => undefined },
|
||||
};
|
||||
|
||||
const worker = new LocalWorker<AppContext>(ctx, { capacity: 8 });
|
||||
await worker.start();
|
||||
|
||||
const task: DistributedTask<string, unknown> = {
|
||||
id: "lookup",
|
||||
execute: async (sql, c) => (c as AppContext).db.query(sql),
|
||||
getStatus: () => "PENDING",
|
||||
setStatus: () => {},
|
||||
getMetadata: () => ({ createdAt: new Date(), attempts: 0 }),
|
||||
};
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `class LocalWorker<Ctx extends ExecutionContext = ExecutionContext> extends AbstractWorker`.
|
||||
- `constructor(context: Ctx, options?: AbstractWorkerOptions, deps?: AbstractWorkerDeps)`.
|
||||
- `protected doExecuteTask<I, O>(task, input): Promise<O>` — invokes `task.execute(input, this.context)`.
|
||||
- `protected getType(): string` — returns `"local"`.
|
||||
- `protected getCapabilities(): Readonly<Record<string, unknown>>` — `{ hasFileSystemAccess: true, isRemote: false, contextType: <ctor name> }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`getCapabilities` reflects the context constructor name (`Object` when the context is `Object.create(null)`) so logs and dashboards can distinguish similarly-typed workers running with different contexts (e.g. tenant-specific). The `hasFileSystemAccess: true` flag is a best-effort signal — strategies that route IO-heavy work to file-system-aware workers can filter on it. Remote / worker-thread plugins explicitly set `isRemote: true` or `isThreaded: true` so the negation is meaningful in dashboards.
|
||||
Reference in New Issue
Block a user