@btravstack/amqp-worker 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/index.cjs +55 -0
- package/dist/index.d.cts +8 -8
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +55 -0
- package/package.json +15 -16
package/README.md
CHANGED
|
@@ -188,15 +188,15 @@ module lists (`imports`, `provides`, `exports`, `needs`). The `amqp()`
|
|
|
188
188
|
primitive does not take `handlers` as an option — it **needs** the handlers
|
|
189
189
|
provider on its own port, which is how the composition root supplies it:
|
|
190
190
|
|
|
191
|
-
| Option | What it is
|
|
192
|
-
| ------------------------ |
|
|
193
|
-
| `contract` | the `amqp-contract` contract; the queues consumed are read off it
|
|
194
|
-
| `handlers` | the handlers provider — what `AmqpHandlers(contract)(...)` returns for this contract
|
|
195
|
-
| `url` | pins `AMQP_URL` (default `amqp://127.0.0.1:5672`) — a test's container
|
|
196
|
-
| `connectionOptions` | `AmqpConnectionOptions`, the library's own connection tuning: heartbeat, reconnect interval, `findServers`, TLS
|
|
197
|
-
| `defaultConsumerOptions` | the library's `ConsumerOptions`, applied to every handler: `prefetch` (the throughput knob), `priority`, …
|
|
198
|
-
| `connectTimeoutMs` | pins `AMQP_CONNECT_TIMEOUT_MS` — how long startup waits before an unreachable broker is a `RuntimeStartFailed` (default `5000`)
|
|
199
|
-
| `unit` | `{ message }` — the module the worker forks per delivery, seeded with the message on `AmqpMessage(contract)`
|
|
191
|
+
| Option | What it is |
|
|
192
|
+
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
193
|
+
| `contract` | the `amqp-contract` contract; the queues consumed are read off it |
|
|
194
|
+
| `handlers` | the handlers provider — what `AmqpHandlers(contract)(...)` returns for this contract |
|
|
195
|
+
| `url` | pins `AMQP_URL` (default `amqp://127.0.0.1:5672`) — a test's container |
|
|
196
|
+
| `connectionOptions` | `AmqpConnectionOptions`, the library's own connection tuning: heartbeat, reconnect interval, `findServers`, TLS |
|
|
197
|
+
| `defaultConsumerOptions` | the library's `ConsumerOptions`, applied to every handler: `prefetch` (the throughput knob — unset is `10`, `"unbounded"` is no cap), `priority`, … |
|
|
198
|
+
| `connectTimeoutMs` | pins `AMQP_CONNECT_TIMEOUT_MS` — how long startup waits before an unreachable broker is a `RuntimeStartFailed` (default `5000`) |
|
|
199
|
+
| `unit` | `{ message }` — the module the worker forks per delivery, seeded with the message on `AmqpMessage(contract)` |
|
|
200
200
|
|
|
201
201
|
The full table — required/optional, defaults, and the reasoning — lives on
|
|
202
202
|
[the reference page](https://btravstack.github.io/btravstack/reference/amqp-worker),
|
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,60 @@ let _btravstack_config = require("@btravstack/config");
|
|
|
5
5
|
let _btravstack_core = require("@btravstack/core");
|
|
6
6
|
let unthrown = require("unthrown");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
|
+
//#region src/broker-log.ts
|
|
9
|
+
/**
|
|
10
|
+
* The library's own diagnostics, as operations on `Observers`.
|
|
11
|
+
*
|
|
12
|
+
* **`@amqp-contract/worker` takes a `logger` and was given none**, so every
|
|
13
|
+
* line it writes was discarded: "Consumer cancelled by server", "poison message
|
|
14
|
+
* will be lost on nack", "Max retries exceeded, sending to DLQ", "Publish for
|
|
15
|
+
* retry failed; leaving original un-ack'd", "Failed to parse/validate message;
|
|
16
|
+
* sending to DLQ", and the channel's own `error`. Each of those is a fact an
|
|
17
|
+
* operator has no other way to learn: the first three are permanent outages
|
|
18
|
+
* this package's own `Serving` cannot see, and the last is where a poison
|
|
19
|
+
* stream goes — nacked before the handler middleware runs, so the `outcome`
|
|
20
|
+
* dimension a healthy-looking rate is read off never sees it.
|
|
21
|
+
*
|
|
22
|
+
* **Observers rather than the kernel's `Logger` port.** Forwarding `Logger`
|
|
23
|
+
* would put it in `amqp()`'s `Needs`, which is exactly the compile error the
|
|
24
|
+
* `instrumented` flag was deleted for: a root that wants a worker and no
|
|
25
|
+
* OpenTelemetry SDK should not be handed a port list. This costs a root
|
|
26
|
+
* nothing — the starter already injects `Observers` and contributes the no-op
|
|
27
|
+
* member — and a root composing `observability()` gets the lines for free.
|
|
28
|
+
*
|
|
29
|
+
* **`debug` and `info` are dropped, and that is the shape of the seam rather
|
|
30
|
+
* than a judgement about them.** An observer writes no line for a successful
|
|
31
|
+
* operation — the repository's own rule, and what keeps a per-request metric
|
|
32
|
+
* from also being a per-request line — so an `info` mapped to `outcome: "ok"`
|
|
33
|
+
* would be silently discarded anyway. Every diagnostic the issue named is a
|
|
34
|
+
* `warn` or an `error`, which is the half that survives.
|
|
35
|
+
*
|
|
36
|
+
* `traced: false`: these have no duration, and a zero-length span per broker
|
|
37
|
+
* line is noise in a trace rather than information.
|
|
38
|
+
*/
|
|
39
|
+
const brokerLog = (observers) => {
|
|
40
|
+
const report = (level) => (message, context) => {
|
|
41
|
+
(0, _btravstack_core.observe)(observers, {
|
|
42
|
+
component: "amqp",
|
|
43
|
+
name: "broker",
|
|
44
|
+
attributes: { level },
|
|
45
|
+
details: { message },
|
|
46
|
+
traced: false
|
|
47
|
+
})({
|
|
48
|
+
outcome: "error",
|
|
49
|
+
attributes: {},
|
|
50
|
+
...context?.error === void 0 ? {} : { cause: context.error }
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const ignore = () => {};
|
|
54
|
+
return {
|
|
55
|
+
debug: ignore,
|
|
56
|
+
info: ignore,
|
|
57
|
+
warn: report("warn"),
|
|
58
|
+
error: report("error")
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
8
62
|
//#region src/unit.ts
|
|
9
63
|
/**
|
|
10
64
|
* Where `messageUnits` leaves the forked context for the piece wrappers to read.
|
|
@@ -268,6 +322,7 @@ const createWorker = (host, config, options, handlers, observers) => _amqp_contr
|
|
|
268
322
|
contract: options.contract,
|
|
269
323
|
handlers,
|
|
270
324
|
middleware: messageUnits(host, observers, options.unit?.message),
|
|
325
|
+
logger: brokerLog(observers),
|
|
271
326
|
urls: [config.url],
|
|
272
327
|
...options.connectionOptions === void 0 ? {} : { connectionOptions: options.connectionOptions },
|
|
273
328
|
...options.defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions: options.defaultConsumerOptions },
|
package/dist/index.d.cts
CHANGED
|
@@ -53,7 +53,7 @@ type AmqpMessageInstance = PortInstance<"AmqpMessage", unknown>;
|
|
|
53
53
|
* at the type level, the move `AmqpHandlersPort` makes, so a module built for
|
|
54
54
|
* one contract cannot read another's message.
|
|
55
55
|
*/
|
|
56
|
-
declare const AmqpMessage: <C extends AnyAmqpContract>(contract: C) => AmqpMessagePortOf<C>;
|
|
56
|
+
export declare const AmqpMessage: <C extends AnyAmqpContract>(contract: C) => AmqpMessagePortOf<C>;
|
|
57
57
|
/**
|
|
58
58
|
* The port one piece targets. Its id carries the contract key, which is what
|
|
59
59
|
* makes two slices claiming one consumer di's duplicate-provider defect rather
|
|
@@ -84,7 +84,7 @@ type MintedHandler<C extends AnyAmqpContract, K extends HandlerKeyOf<C>, N, U ex
|
|
|
84
84
|
* of the fork the delivery opened; the root's `unit.message` module must export
|
|
85
85
|
* every one of them.
|
|
86
86
|
*/
|
|
87
|
-
declare const AmqpHandler: <C extends AnyAmqpContract, const K extends HandlerKeyOf<C>>(contract: C, key: K) => <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
|
|
87
|
+
export declare const AmqpHandler: <C extends AnyAmqpContract, const K extends HandlerKeyOf<C>>(contract: C, key: K) => <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
|
|
88
88
|
readonly inject: D;
|
|
89
89
|
/** The unit-scoped ports this handler reads off `context.unit`. */
|
|
90
90
|
readonly unit?: U;
|
|
@@ -107,13 +107,13 @@ declare const AmqpConfig_base: import("@btravstack/di").PortClass<"AmqpConfig">;
|
|
|
107
107
|
* unless pinned, and anything else in the graph may read it — a publisher
|
|
108
108
|
* sharing the consumer's broker, say.
|
|
109
109
|
*/
|
|
110
|
-
declare class AmqpConfig extends AmqpConfig_base<{
|
|
110
|
+
export declare class AmqpConfig extends AmqpConfig_base<{
|
|
111
111
|
readonly url: string;
|
|
112
112
|
/** How long `create` waits for the connection before failing. */
|
|
113
113
|
readonly connectTimeoutMs: number;
|
|
114
114
|
}> {}
|
|
115
115
|
/** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
|
|
116
|
-
declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
|
|
116
|
+
export declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
|
|
117
117
|
/**
|
|
118
118
|
* A module `unit.message` may bind, as the upper bound `amqp()` constrains its
|
|
119
119
|
* own `Unit` type parameter to. `Module`'s `_exports` channel is contravariant,
|
|
@@ -192,7 +192,7 @@ type AmqpTuning<Unit extends AnyUnitModule | undefined = undefined> = {
|
|
|
192
192
|
*
|
|
193
193
|
* With `url` pinned the module reads nothing from the environment.
|
|
194
194
|
*/
|
|
195
|
-
declare const amqp: <TContract extends AnyAmqpContract, Unit extends AnyUnitModule | undefined = undefined>(options: AmqpOptions<TContract, Unit>) => Module<AmqpRuntime | AmqpConfig, ConfigInvalid, Env | HandlersInstanceOf<TContract> | UnitNeedsOf<Unit>>;
|
|
195
|
+
export declare const amqp: <TContract extends AnyAmqpContract, Unit extends AnyUnitModule | undefined = undefined>(options: AmqpOptions<TContract, Unit>) => Module<AmqpRuntime | AmqpConfig, ConfigInvalid, Env | HandlersInstanceOf<TContract> | UnitNeedsOf<Unit>>;
|
|
196
196
|
/** One piece of the handlers record — what `AmqpHandler(contract, key)(…)` returns, as the composing form consumes it. */
|
|
197
197
|
type PieceOf<C extends AnyAmqpContract> = { readonly [K in HandlerKeyOf<C>]: {
|
|
198
198
|
readonly port: HandlerPortOf<C, K>;
|
|
@@ -276,7 +276,7 @@ type Compose<C extends AnyAmqpContract> = <const T extends readonly PieceOf<C>[]
|
|
|
276
276
|
* record IS the handlers record. Every declared key must be covered, and two
|
|
277
277
|
* slices claiming one key are di's duplicate-provider defect at build.
|
|
278
278
|
*/
|
|
279
|
-
declare const AmqpHandlers: <C extends AnyAmqpContract>(contract: C) => Whole<C> & Compose<C>;
|
|
279
|
+
export declare const AmqpHandlers: <C extends AnyAmqpContract>(contract: C) => Whole<C> & Compose<C>;
|
|
280
280
|
//#endregion
|
|
281
281
|
//#region src/amqp-module.d.ts
|
|
282
282
|
/** The starter's own module, as the sugar adds it to the application's imports. */
|
|
@@ -322,6 +322,6 @@ type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, Handler
|
|
|
322
322
|
* await runMain(OrderAmqpWorker);
|
|
323
323
|
* ```
|
|
324
324
|
*/
|
|
325
|
-
declare const AmqpModule: <const Name extends string>(name: Name) => <TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, Declared = never, Unit extends AnyUnitModule | undefined = undefined, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, TContract, Unit>, Provides<P, TContract, HandlersError, HandlersNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: AmqpModuleOptions<TContract, HandlersError, HandlersNeeds, Declared, Unit, I, P, X, N>) => Module<(Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof AmqpRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
|
|
325
|
+
export declare const AmqpModule: <const Name extends string>(name: Name) => <TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, Declared = never, Unit extends AnyUnitModule | undefined = undefined, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, TContract, Unit>, Provides<P, TContract, HandlersError, HandlersNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: AmqpModuleOptions<TContract, HandlersError, HandlersNeeds, Declared, Unit, I, P, X, N>) => Module<(Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof AmqpRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
|
|
326
326
|
//#endregion
|
|
327
|
-
export {
|
|
327
|
+
export type { AmqpConnectionOptions, AmqpInfo, AmqpMessageOf, AmqpMessagePortOf, AmqpModuleOptions, AmqpOptions, HandlerPortOf, HandlersInstanceOf, HandlersPortOf };
|
package/dist/index.d.mts
CHANGED
|
@@ -53,7 +53,7 @@ type AmqpMessageInstance = PortInstance<"AmqpMessage", unknown>;
|
|
|
53
53
|
* at the type level, the move `AmqpHandlersPort` makes, so a module built for
|
|
54
54
|
* one contract cannot read another's message.
|
|
55
55
|
*/
|
|
56
|
-
declare const AmqpMessage: <C extends AnyAmqpContract>(contract: C) => AmqpMessagePortOf<C>;
|
|
56
|
+
export declare const AmqpMessage: <C extends AnyAmqpContract>(contract: C) => AmqpMessagePortOf<C>;
|
|
57
57
|
/**
|
|
58
58
|
* The port one piece targets. Its id carries the contract key, which is what
|
|
59
59
|
* makes two slices claiming one consumer di's duplicate-provider defect rather
|
|
@@ -84,7 +84,7 @@ type MintedHandler<C extends AnyAmqpContract, K extends HandlerKeyOf<C>, N, U ex
|
|
|
84
84
|
* of the fork the delivery opened; the root's `unit.message` module must export
|
|
85
85
|
* every one of them.
|
|
86
86
|
*/
|
|
87
|
-
declare const AmqpHandler: <C extends AnyAmqpContract, const K extends HandlerKeyOf<C>>(contract: C, key: K) => <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
|
|
87
|
+
export declare const AmqpHandler: <C extends AnyAmqpContract, const K extends HandlerKeyOf<C>>(contract: C, key: K) => <const D extends Readonly<Record<string, AnyPort>>, const U extends Readonly<Record<string, AnyPort>> = Record<never, never>>(options: {
|
|
88
88
|
readonly inject: D;
|
|
89
89
|
/** The unit-scoped ports this handler reads off `context.unit`. */
|
|
90
90
|
readonly unit?: U;
|
|
@@ -107,13 +107,13 @@ declare const AmqpConfig_base: import("@btravstack/di").PortClass<"AmqpConfig">;
|
|
|
107
107
|
* unless pinned, and anything else in the graph may read it — a publisher
|
|
108
108
|
* sharing the consumer's broker, say.
|
|
109
109
|
*/
|
|
110
|
-
declare class AmqpConfig extends AmqpConfig_base<{
|
|
110
|
+
export declare class AmqpConfig extends AmqpConfig_base<{
|
|
111
111
|
readonly url: string;
|
|
112
112
|
/** How long `create` waits for the connection before failing. */
|
|
113
113
|
readonly connectTimeoutMs: number;
|
|
114
114
|
}> {}
|
|
115
115
|
/** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
|
|
116
|
-
declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
|
|
116
|
+
export declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
|
|
117
117
|
/**
|
|
118
118
|
* A module `unit.message` may bind, as the upper bound `amqp()` constrains its
|
|
119
119
|
* own `Unit` type parameter to. `Module`'s `_exports` channel is contravariant,
|
|
@@ -192,7 +192,7 @@ type AmqpTuning<Unit extends AnyUnitModule | undefined = undefined> = {
|
|
|
192
192
|
*
|
|
193
193
|
* With `url` pinned the module reads nothing from the environment.
|
|
194
194
|
*/
|
|
195
|
-
declare const amqp: <TContract extends AnyAmqpContract, Unit extends AnyUnitModule | undefined = undefined>(options: AmqpOptions<TContract, Unit>) => Module<AmqpRuntime | AmqpConfig, ConfigInvalid, Env | HandlersInstanceOf<TContract> | UnitNeedsOf<Unit>>;
|
|
195
|
+
export declare const amqp: <TContract extends AnyAmqpContract, Unit extends AnyUnitModule | undefined = undefined>(options: AmqpOptions<TContract, Unit>) => Module<AmqpRuntime | AmqpConfig, ConfigInvalid, Env | HandlersInstanceOf<TContract> | UnitNeedsOf<Unit>>;
|
|
196
196
|
/** One piece of the handlers record — what `AmqpHandler(contract, key)(…)` returns, as the composing form consumes it. */
|
|
197
197
|
type PieceOf<C extends AnyAmqpContract> = { readonly [K in HandlerKeyOf<C>]: {
|
|
198
198
|
readonly port: HandlerPortOf<C, K>;
|
|
@@ -276,7 +276,7 @@ type Compose<C extends AnyAmqpContract> = <const T extends readonly PieceOf<C>[]
|
|
|
276
276
|
* record IS the handlers record. Every declared key must be covered, and two
|
|
277
277
|
* slices claiming one key are di's duplicate-provider defect at build.
|
|
278
278
|
*/
|
|
279
|
-
declare const AmqpHandlers: <C extends AnyAmqpContract>(contract: C) => Whole<C> & Compose<C>;
|
|
279
|
+
export declare const AmqpHandlers: <C extends AnyAmqpContract>(contract: C) => Whole<C> & Compose<C>;
|
|
280
280
|
//#endregion
|
|
281
281
|
//#region src/amqp-module.d.ts
|
|
282
282
|
/** The starter's own module, as the sugar adds it to the application's imports. */
|
|
@@ -322,6 +322,6 @@ type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, Handler
|
|
|
322
322
|
* await runMain(OrderAmqpWorker);
|
|
323
323
|
* ```
|
|
324
324
|
*/
|
|
325
|
-
declare const AmqpModule: <const Name extends string>(name: Name) => <TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, Declared = never, Unit extends AnyUnitModule | undefined = undefined, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, TContract, Unit>, Provides<P, TContract, HandlersError, HandlersNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: AmqpModuleOptions<TContract, HandlersError, HandlersNeeds, Declared, Unit, I, P, X, N>) => Module<(Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof AmqpRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
|
|
325
|
+
export declare const AmqpModule: <const Name extends string>(name: Name) => <TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, Declared = never, Unit extends AnyUnitModule | undefined = undefined, const I extends readonly AnyModule[] = [], const P extends readonly AnyProvider[] = [], const X extends readonly Exportable<Imports<I, TContract, Unit>, Provides<P, TContract, HandlersError, HandlersNeeds>>[] = [], const N extends readonly AnyPort[] = []>(options: AmqpModuleOptions<TContract, HandlersError, HandlersNeeds, Declared, Unit, I, P, X, N>) => Module<(Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> extends (infer T) ? T extends Extract<(readonly [typeof AmqpRuntime, ...X])[number], AnyModule> ? T extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [typeof AmqpRuntime, ...X])[number] extends (infer E_1) ? E_1 extends AnyPort ? InstanceType<E_1> : E_1 extends AnyProvider ? InstanceType<E_1["port"]> : never : never), ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_1) ? T_1 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_1 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[1] | ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_2) ? T_2 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_2 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[1], Exclude<((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]> | Exclude<((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[2], ((readonly [...I, AmqpStarter<TContract, Unit>])[number] extends (infer T_4) ? T_4 extends (readonly [...I, AmqpStarter<TContract, Unit>])[number] ? T_4 extends Module<infer X_1, infer E, infer N_1> ? readonly [X_1, E, N_1] : never : never : never)[0] | ((readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] extends (infer T_3) ? T_3 extends (readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P])[number] ? T_3 extends Provider<infer P_1, infer E_2, infer N_2> ? readonly [P_1, E_2, N_2] : never : never : never)[0]>>;
|
|
326
326
|
//#endregion
|
|
327
|
-
export {
|
|
327
|
+
export type { AmqpConnectionOptions, AmqpInfo, AmqpMessageOf, AmqpMessagePortOf, AmqpModuleOptions, AmqpOptions, HandlerPortOf, HandlersInstanceOf, HandlersPortOf };
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,60 @@ import { Config, Env } from "@btravstack/config";
|
|
|
4
4
|
import { Observers, RuntimePort, RuntimeStartFailed, noObserver, observe, releasedBy, traceIdOfTraceparent } from "@btravstack/core";
|
|
5
5
|
import { P } from "unthrown";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
+
//#region src/broker-log.ts
|
|
8
|
+
/**
|
|
9
|
+
* The library's own diagnostics, as operations on `Observers`.
|
|
10
|
+
*
|
|
11
|
+
* **`@amqp-contract/worker` takes a `logger` and was given none**, so every
|
|
12
|
+
* line it writes was discarded: "Consumer cancelled by server", "poison message
|
|
13
|
+
* will be lost on nack", "Max retries exceeded, sending to DLQ", "Publish for
|
|
14
|
+
* retry failed; leaving original un-ack'd", "Failed to parse/validate message;
|
|
15
|
+
* sending to DLQ", and the channel's own `error`. Each of those is a fact an
|
|
16
|
+
* operator has no other way to learn: the first three are permanent outages
|
|
17
|
+
* this package's own `Serving` cannot see, and the last is where a poison
|
|
18
|
+
* stream goes — nacked before the handler middleware runs, so the `outcome`
|
|
19
|
+
* dimension a healthy-looking rate is read off never sees it.
|
|
20
|
+
*
|
|
21
|
+
* **Observers rather than the kernel's `Logger` port.** Forwarding `Logger`
|
|
22
|
+
* would put it in `amqp()`'s `Needs`, which is exactly the compile error the
|
|
23
|
+
* `instrumented` flag was deleted for: a root that wants a worker and no
|
|
24
|
+
* OpenTelemetry SDK should not be handed a port list. This costs a root
|
|
25
|
+
* nothing — the starter already injects `Observers` and contributes the no-op
|
|
26
|
+
* member — and a root composing `observability()` gets the lines for free.
|
|
27
|
+
*
|
|
28
|
+
* **`debug` and `info` are dropped, and that is the shape of the seam rather
|
|
29
|
+
* than a judgement about them.** An observer writes no line for a successful
|
|
30
|
+
* operation — the repository's own rule, and what keeps a per-request metric
|
|
31
|
+
* from also being a per-request line — so an `info` mapped to `outcome: "ok"`
|
|
32
|
+
* would be silently discarded anyway. Every diagnostic the issue named is a
|
|
33
|
+
* `warn` or an `error`, which is the half that survives.
|
|
34
|
+
*
|
|
35
|
+
* `traced: false`: these have no duration, and a zero-length span per broker
|
|
36
|
+
* line is noise in a trace rather than information.
|
|
37
|
+
*/
|
|
38
|
+
const brokerLog = (observers) => {
|
|
39
|
+
const report = (level) => (message, context) => {
|
|
40
|
+
observe(observers, {
|
|
41
|
+
component: "amqp",
|
|
42
|
+
name: "broker",
|
|
43
|
+
attributes: { level },
|
|
44
|
+
details: { message },
|
|
45
|
+
traced: false
|
|
46
|
+
})({
|
|
47
|
+
outcome: "error",
|
|
48
|
+
attributes: {},
|
|
49
|
+
...context?.error === void 0 ? {} : { cause: context.error }
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const ignore = () => {};
|
|
53
|
+
return {
|
|
54
|
+
debug: ignore,
|
|
55
|
+
info: ignore,
|
|
56
|
+
warn: report("warn"),
|
|
57
|
+
error: report("error")
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
7
61
|
//#region src/unit.ts
|
|
8
62
|
/**
|
|
9
63
|
* Where `messageUnits` leaves the forked context for the piece wrappers to read.
|
|
@@ -267,6 +321,7 @@ const createWorker = (host, config, options, handlers, observers) => TypedAmqpWo
|
|
|
267
321
|
contract: options.contract,
|
|
268
322
|
handlers,
|
|
269
323
|
middleware: messageUnits(host, observers, options.unit?.message),
|
|
324
|
+
logger: brokerLog(observers),
|
|
270
325
|
urls: [config.url],
|
|
271
326
|
...options.connectionOptions === void 0 ? {} : { connectionOptions: options.connectionOptions },
|
|
272
327
|
...options.defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions: options.defaultConsumerOptions },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btravstack/amqp-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "The AMQP starter for @btravstack/core: the handlers as a port, one unit per delivery, and a drain the kernel's deadline releases",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"amqp",
|
|
@@ -47,29 +47,29 @@
|
|
|
47
47
|
"@amqp-contract/contract": "3.0.0-beta.7",
|
|
48
48
|
"@amqp-contract/testing": "3.0.0-beta.7",
|
|
49
49
|
"@amqp-contract/worker": "3.0.0-beta.7",
|
|
50
|
+
"@btravstack/config": "0.15.0",
|
|
51
|
+
"@btravstack/core": "0.15.0",
|
|
52
|
+
"@btravstack/di": "0.15.0",
|
|
53
|
+
"@btravstack/internal-test-infra": "0.0.0",
|
|
54
|
+
"@btravstack/testing": "0.15.0",
|
|
50
55
|
"@btravstack/tsconfig": "0.4.0",
|
|
51
56
|
"@opentelemetry/api": "1.9.1",
|
|
52
|
-
"@types/node": "26.4.
|
|
53
|
-
"@unthrown/vitest": "5.
|
|
57
|
+
"@types/node": "26.4.1",
|
|
58
|
+
"@unthrown/vitest": "5.8.0",
|
|
54
59
|
"@vitest/coverage-v8": "4.1.11",
|
|
55
|
-
"tsdown": "0.
|
|
60
|
+
"tsdown": "0.23.0",
|
|
56
61
|
"typescript": "7.0.2",
|
|
57
|
-
"unthrown": "5.
|
|
62
|
+
"unthrown": "5.8.0",
|
|
58
63
|
"vitest": "4.1.11",
|
|
59
|
-
"zod": "4.5.
|
|
60
|
-
"@btravstack/config": "0.13.0",
|
|
61
|
-
"@btravstack/core": "0.13.0",
|
|
62
|
-
"@btravstack/di": "0.13.0",
|
|
63
|
-
"@btravstack/internal-test-infra": "0.0.0",
|
|
64
|
-
"@btravstack/testing": "0.13.0"
|
|
64
|
+
"zod": "4.5.4"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@amqp-contract/worker": "^3.0.0-beta.7",
|
|
68
|
+
"@btravstack/config": "^0.15.0",
|
|
69
|
+
"@btravstack/core": "^0.15.0",
|
|
70
|
+
"@btravstack/di": "^0.15.0",
|
|
68
71
|
"@opentelemetry/api": "^1",
|
|
69
|
-
"unthrown": "^5.0.0"
|
|
70
|
-
"@btravstack/config": "^0.13.0",
|
|
71
|
-
"@btravstack/core": "^0.13.0",
|
|
72
|
-
"@btravstack/di": "^0.13.0"
|
|
72
|
+
"unthrown": "^5.0.0"
|
|
73
73
|
},
|
|
74
74
|
"engines": {
|
|
75
75
|
"node": ">=22"
|
|
@@ -78,7 +78,6 @@
|
|
|
78
78
|
"build": "tsdown src/index.ts --format cjs,esm --dts --clean",
|
|
79
79
|
"dev": "tsdown src/index.ts --format cjs,esm --dts --watch",
|
|
80
80
|
"test": "vitest run --coverage",
|
|
81
|
-
"test:types": "tsc --noEmit -p tsconfig.test-d.json",
|
|
82
81
|
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test-d.json"
|
|
83
82
|
}
|
|
84
83
|
}
|