@btravstack/amqp-worker 0.5.0 → 0.7.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 CHANGED
@@ -115,14 +115,14 @@ module lists (`imports`, `provides`, `exports`, `needs`). The `amqp()`
115
115
  primitive does not take `handlers` as an option — it **needs** the handlers
116
116
  provider on its own port, which is how the composition root supplies it:
117
117
 
118
- | Option | What it is |
119
- | ------------------------ | --------------------------------------------------------------------------------------------------------------- |
120
- | `contract` | the `amqp-contract` contract; the queues consumed are read off it |
121
- | `handlers` | the handlers provider — what `AmqpHandlers(contract)(...)` returns for this contract |
122
- | `url` | pins the broker instead of reading `AMQP_URL` (default `amqp://127.0.0.1:5672`) — a test's container |
123
- | `connectionOptions` | `AmqpConnectionOptions`, the library's own connection tuning: heartbeat, reconnect interval, `findServers`, TLS |
124
- | `defaultConsumerOptions` | the library's `ConsumerOptions`, applied to every handler: `prefetch` (the throughput knob), `priority`, … |
125
- | `connectTimeoutMs` | how long startup waits before an unreachable broker is a `RuntimeStartFailed` (the library defaults to 30 s) |
118
+ | Option | What it is |
119
+ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
120
+ | `contract` | the `amqp-contract` contract; the queues consumed are read off it |
121
+ | `handlers` | the handlers provider — what `AmqpHandlers(contract)(...)` returns for this contract |
122
+ | `url` | pins `AMQP_URL` (default `amqp://127.0.0.1:5672`) — a test's container |
123
+ | `connectionOptions` | `AmqpConnectionOptions`, the library's own connection tuning: heartbeat, reconnect interval, `findServers`, TLS |
124
+ | `defaultConsumerOptions` | the library's `ConsumerOptions`, applied to every handler: `prefetch` (the throughput knob), `priority`, … |
125
+ | `connectTimeoutMs` | pins `AMQP_CONNECT_TIMEOUT_MS` — how long startup waits before an unreachable broker is a `RuntimeStartFailed` (default `5000`) |
126
126
 
127
127
  The full table — required/optional, defaults, and the reasoning — lives on
128
128
  [the reference page](https://btravstack.github.io/btravstack/reference/amqp-worker),
package/dist/index.cjs CHANGED
@@ -75,10 +75,17 @@ const traceIdOfTraceparent = (header) => {
75
75
  //#region src/amqp-runtime.ts
76
76
  /**
77
77
  * The broker, as a service: `amqp()` binds it from `AMQP_URL` (default
78
- * `amqp://127.0.0.1:5672`) unless pinned, and anything else in the graph may
79
- * read it — a publisher sharing the consumer's broker, say.
78
+ * `amqp://127.0.0.1:5672`) and `AMQP_CONNECT_TIMEOUT_MS` (default `5_000`)
79
+ * unless pinned, and anything else in the graph may read it — a publisher
80
+ * sharing the consumer's broker, say.
80
81
  */
81
82
  var AmqpConfig = class extends (0, _btravstack_di.Port)("AmqpConfig") {};
83
+ /**
84
+ * Five seconds. The library's own default is 30, which is longer than most
85
+ * orchestrators wait before restarting the pod — an unreachable broker should
86
+ * be reported, not sat on.
87
+ */
88
+ const DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
82
89
  /** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
83
90
  var AmqpRuntime = class extends _btravstack_core.RuntimePort {};
84
91
  /**
@@ -99,7 +106,13 @@ const AmqpHandlersPort = (0, _btravstack_di.Port)("AmqpHandlers");
99
106
  * With `url` pinned the module reads nothing from the environment.
100
107
  */
101
108
  const amqp = (options) => {
102
- const config = options.url === void 0 ? _btravstack_config.Config.provider(AmqpConfig)(_btravstack_config.Config.object({ url: _btravstack_config.Config.string("AMQP_URL", { default: "amqp://127.0.0.1:5672" }) })) : (0, _btravstack_di.Provider)(AmqpConfig)({ value: { url: options.url } });
109
+ const config = _btravstack_config.Config.provider(AmqpConfig)(_btravstack_config.Config.object({
110
+ url: _btravstack_config.Config.pinned(options.url, _btravstack_config.Config.string("AMQP_URL", { default: "amqp://127.0.0.1:5672" })),
111
+ connectTimeoutMs: _btravstack_config.Config.pinned(options.connectTimeoutMs, _btravstack_config.Config.integer("AMQP_CONNECT_TIMEOUT_MS", {
112
+ default: DEFAULT_CONNECT_TIMEOUT_MS,
113
+ min: 0
114
+ }))
115
+ }));
103
116
  return (0, _btravstack_di.Module)("Amqp")({
104
117
  needs: [_btravstack_config.Env, AmqpHandlersPort],
105
118
  provides: [config, (0, _btravstack_di.Provider)(AmqpRuntime)({
@@ -153,7 +166,7 @@ const createWorker = (host, config, options, handlers) => _amqp_contract_worker.
153
166
  urls: [config.url],
154
167
  ...options.connectionOptions === void 0 ? {} : { connectionOptions: options.connectionOptions },
155
168
  ...options.defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions: options.defaultConsumerOptions },
156
- ...options.connectTimeoutMs === void 0 ? {} : { connectTimeoutMs: options.connectTimeoutMs }
169
+ connectTimeoutMs: config.connectTimeoutMs
157
170
  }).map((worker) => consume(worker, queuesOf(options.contract))).recoverDefect((cause) => (0, unthrown.ErrAsync)(startFailed(cause)));
158
171
  const consume = (worker, queues) => {
159
172
  let closing;
@@ -188,17 +201,11 @@ const consume = (worker, queues) => {
188
201
  * ```
189
202
  */
190
203
  const AmqpModule = (name) => (options) => {
191
- const { contract, handlers, url, connectionOptions, defaultConsumerOptions, connectTimeoutMs } = options;
204
+ const { handlers } = options;
192
205
  const imports = options.imports ?? [];
193
206
  const provides = options.provides ?? [];
194
207
  const exports = options.exports ?? [];
195
- const starter = amqp({
196
- contract,
197
- ...url === void 0 ? {} : { url },
198
- ...connectionOptions === void 0 ? {} : { connectionOptions },
199
- ...defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions },
200
- ...connectTimeoutMs === void 0 ? {} : { connectTimeoutMs }
201
- });
208
+ const starter = amqp(options);
202
209
  return (0, _btravstack_di.Module)(name)({
203
210
  imports: [...imports, starter],
204
211
  provides: [handlers, ...provides],
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { ConsumerOptions, TypedAmqpWorker, WorkerInferHandlers } from "@amqp-contract/worker";
2
1
  import { ConfigInvalid, Env } from "@btravstack/config";
3
2
  import { AnyModule, AnyPort, AnyProvider, Exportable, Module, NeedsGate, PortClassOf, PortInstance, Provider } from "@btravstack/di";
3
+ import { ConsumerOptions, TypedAmqpWorker, WorkerInferHandlers } from "@amqp-contract/worker";
4
4
  import { Runtime, RuntimePort } from "@btravstack/core";
5
5
  //#region src/handler.d.ts
6
6
  /** The consumer and rpc names `C` declares — the keys of its handlers record. */
@@ -33,11 +33,14 @@ type AmqpInfo = {
33
33
  declare const AmqpConfig_base: import("@btravstack/di").PortClass<"AmqpConfig">;
34
34
  /**
35
35
  * The broker, as a service: `amqp()` binds it from `AMQP_URL` (default
36
- * `amqp://127.0.0.1:5672`) unless pinned, and anything else in the graph may
37
- * read it — a publisher sharing the consumer's broker, say.
36
+ * `amqp://127.0.0.1:5672`) and `AMQP_CONNECT_TIMEOUT_MS` (default `5_000`)
37
+ * unless pinned, and anything else in the graph may read it — a publisher
38
+ * sharing the consumer's broker, say.
38
39
  */
39
40
  declare class AmqpConfig extends AmqpConfig_base<{
40
41
  readonly url: string;
42
+ /** How long `create` waits for the connection before failing. */
43
+ readonly connectTimeoutMs: number;
41
44
  }> {}
42
45
  /** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
43
46
  declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
@@ -64,17 +67,25 @@ type AmqpOptions<TContract extends AnyAmqpContract> = {
64
67
  * built by di from the services it declares.
65
68
  */
66
69
  readonly contract: TContract;
67
- /** Pins the broker instead of reading `AMQP_URL` — a test's container. */
70
+ } & AmqpTuning;
71
+ /**
72
+ * What an AMQP deployment tunes, shared verbatim by `amqp()` and `AmqpModule` —
73
+ * spelled once so the two cannot drift, which is what a second copy of an
74
+ * option list always eventually does.
75
+ */
76
+ type AmqpTuning = {
77
+ /** Pins `AmqpConfig.url` instead of reading `AMQP_URL` — a test's container. */
68
78
  readonly url?: string;
69
79
  /** Connection tuning, `@amqp-contract/worker`'s own type: heartbeat, reconnect interval, `findServers`, TLS/socket options. */
70
80
  readonly connectionOptions?: AmqpConnectionOptions;
71
81
  /** Consumer defaults applied to every handler, the library's own type: `prefetch`, `priority`, `arguments`, `consumerTag`, `exclusive`. */
72
82
  readonly defaultConsumerOptions?: ConsumerOptions;
73
83
  /**
74
- * How long `create` waits for the connection before failing. Passed straight
75
- * through — it is a top-level `CreateWorkerOptions` field, NOT nested under
76
- * `connectionOptions`, where setting it is silently inert. Without it an
77
- * unreachable broker takes the library's 30s default to report.
84
+ * Pins `AmqpConfig.connectTimeoutMs` instead of reading
85
+ * `AMQP_CONNECT_TIMEOUT_MS` (default {@link DEFAULT_CONNECT_TIMEOUT_MS}) —
86
+ * how long `create` waits for the connection before failing. Passed straight
87
+ * through as a top-level `CreateWorkerOptions` field, NOT nested under
88
+ * `connectionOptions`, where setting it is silently inert.
78
89
  */
79
90
  readonly connectTimeoutMs?: number;
80
91
  };
@@ -135,18 +146,10 @@ type AmqpStarter<TContract extends AnyAmqpContract> = Module<AmqpRuntime | AmqpC
135
146
  type Imports<I extends readonly AnyModule[], TContract extends AnyAmqpContract> = readonly [...I, AmqpStarter<TContract>];
136
147
  /** The handlers provider plus the application's own — the tuple `Module(name)` is handed. */
137
148
  type Provides<P extends readonly AnyProvider[], TContract extends AnyAmqpContract, HandlersError, HandlersNeeds> = readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P];
138
- type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, TContract>, Provides<P, TContract, HandlersError, HandlersNeeds>>[], N extends readonly AnyPort[]> = {
149
+ type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, TContract>, Provides<P, TContract, HandlersError, HandlersNeeds>>[], N extends readonly AnyPort[]> = AmqpTuning & {
139
150
  readonly contract: TContract;
140
151
  /** The application's handlers — what `AmqpHandlers(contract)(…)` returns for THIS contract. */
141
152
  readonly handlers: Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>;
142
- /** Pins the broker instead of reading `AMQP_URL` — a test's container. */
143
- readonly url?: string;
144
- /** See `AmqpOptions.connectionOptions`. */
145
- readonly connectionOptions?: AmqpConnectionOptions;
146
- /** See `AmqpOptions.defaultConsumerOptions`. */
147
- readonly defaultConsumerOptions?: ConsumerOptions;
148
- /** See `AmqpOptions.connectTimeoutMs`. */
149
- readonly connectTimeoutMs?: number;
150
153
  readonly imports?: I;
151
154
  readonly provides?: P;
152
155
  /** The application's own exports; `AmqpRuntime` is added, since `start` resolves it. */
package/dist/index.d.mts CHANGED
@@ -33,11 +33,14 @@ type AmqpInfo = {
33
33
  declare const AmqpConfig_base: import("@btravstack/di").PortClass<"AmqpConfig">;
34
34
  /**
35
35
  * The broker, as a service: `amqp()` binds it from `AMQP_URL` (default
36
- * `amqp://127.0.0.1:5672`) unless pinned, and anything else in the graph may
37
- * read it — a publisher sharing the consumer's broker, say.
36
+ * `amqp://127.0.0.1:5672`) and `AMQP_CONNECT_TIMEOUT_MS` (default `5_000`)
37
+ * unless pinned, and anything else in the graph may read it — a publisher
38
+ * sharing the consumer's broker, say.
38
39
  */
39
40
  declare class AmqpConfig extends AmqpConfig_base<{
40
41
  readonly url: string;
42
+ /** How long `create` waits for the connection before failing. */
43
+ readonly connectTimeoutMs: number;
41
44
  }> {}
42
45
  /** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
43
46
  declare class AmqpRuntime extends RuntimePort<Runtime<never, AmqpInfo>> {}
@@ -64,17 +67,25 @@ type AmqpOptions<TContract extends AnyAmqpContract> = {
64
67
  * built by di from the services it declares.
65
68
  */
66
69
  readonly contract: TContract;
67
- /** Pins the broker instead of reading `AMQP_URL` — a test's container. */
70
+ } & AmqpTuning;
71
+ /**
72
+ * What an AMQP deployment tunes, shared verbatim by `amqp()` and `AmqpModule` —
73
+ * spelled once so the two cannot drift, which is what a second copy of an
74
+ * option list always eventually does.
75
+ */
76
+ type AmqpTuning = {
77
+ /** Pins `AmqpConfig.url` instead of reading `AMQP_URL` — a test's container. */
68
78
  readonly url?: string;
69
79
  /** Connection tuning, `@amqp-contract/worker`'s own type: heartbeat, reconnect interval, `findServers`, TLS/socket options. */
70
80
  readonly connectionOptions?: AmqpConnectionOptions;
71
81
  /** Consumer defaults applied to every handler, the library's own type: `prefetch`, `priority`, `arguments`, `consumerTag`, `exclusive`. */
72
82
  readonly defaultConsumerOptions?: ConsumerOptions;
73
83
  /**
74
- * How long `create` waits for the connection before failing. Passed straight
75
- * through — it is a top-level `CreateWorkerOptions` field, NOT nested under
76
- * `connectionOptions`, where setting it is silently inert. Without it an
77
- * unreachable broker takes the library's 30s default to report.
84
+ * Pins `AmqpConfig.connectTimeoutMs` instead of reading
85
+ * `AMQP_CONNECT_TIMEOUT_MS` (default {@link DEFAULT_CONNECT_TIMEOUT_MS}) —
86
+ * how long `create` waits for the connection before failing. Passed straight
87
+ * through as a top-level `CreateWorkerOptions` field, NOT nested under
88
+ * `connectionOptions`, where setting it is silently inert.
78
89
  */
79
90
  readonly connectTimeoutMs?: number;
80
91
  };
@@ -135,18 +146,10 @@ type AmqpStarter<TContract extends AnyAmqpContract> = Module<AmqpRuntime | AmqpC
135
146
  type Imports<I extends readonly AnyModule[], TContract extends AnyAmqpContract> = readonly [...I, AmqpStarter<TContract>];
136
147
  /** The handlers provider plus the application's own — the tuple `Module(name)` is handed. */
137
148
  type Provides<P extends readonly AnyProvider[], TContract extends AnyAmqpContract, HandlersError, HandlersNeeds> = readonly [Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>, ...P];
138
- type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, TContract>, Provides<P, TContract, HandlersError, HandlersNeeds>>[], N extends readonly AnyPort[]> = {
149
+ type AmqpModuleOptions<TContract extends AnyAmqpContract, HandlersError, HandlersNeeds, I extends readonly AnyModule[], P extends readonly AnyProvider[], X extends readonly Exportable<Imports<I, TContract>, Provides<P, TContract, HandlersError, HandlersNeeds>>[], N extends readonly AnyPort[]> = AmqpTuning & {
139
150
  readonly contract: TContract;
140
151
  /** The application's handlers — what `AmqpHandlers(contract)(…)` returns for THIS contract. */
141
152
  readonly handlers: Provider<HandlersInstanceOf<TContract>, HandlersError, HandlersNeeds>;
142
- /** Pins the broker instead of reading `AMQP_URL` — a test's container. */
143
- readonly url?: string;
144
- /** See `AmqpOptions.connectionOptions`. */
145
- readonly connectionOptions?: AmqpConnectionOptions;
146
- /** See `AmqpOptions.defaultConsumerOptions`. */
147
- readonly defaultConsumerOptions?: ConsumerOptions;
148
- /** See `AmqpOptions.connectTimeoutMs`. */
149
- readonly connectTimeoutMs?: number;
150
153
  readonly imports?: I;
151
154
  readonly provides?: P;
152
155
  /** The application's own exports; `AmqpRuntime` is added, since `start` resolves it. */
package/dist/index.mjs CHANGED
@@ -74,10 +74,17 @@ const traceIdOfTraceparent = (header) => {
74
74
  //#region src/amqp-runtime.ts
75
75
  /**
76
76
  * The broker, as a service: `amqp()` binds it from `AMQP_URL` (default
77
- * `amqp://127.0.0.1:5672`) unless pinned, and anything else in the graph may
78
- * read it — a publisher sharing the consumer's broker, say.
77
+ * `amqp://127.0.0.1:5672`) and `AMQP_CONNECT_TIMEOUT_MS` (default `5_000`)
78
+ * unless pinned, and anything else in the graph may read it — a publisher
79
+ * sharing the consumer's broker, say.
79
80
  */
80
81
  var AmqpConfig = class extends Port("AmqpConfig") {};
82
+ /**
83
+ * Five seconds. The library's own default is 30, which is longer than most
84
+ * orchestrators wait before restarting the pod — an unreachable broker should
85
+ * be reported, not sat on.
86
+ */
87
+ const DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
81
88
  /** The runtime's port: what `amqp()` provides, and what the module `start` boots must export. */
82
89
  var AmqpRuntime = class extends RuntimePort {};
83
90
  /**
@@ -98,7 +105,13 @@ const AmqpHandlersPort = Port("AmqpHandlers");
98
105
  * With `url` pinned the module reads nothing from the environment.
99
106
  */
100
107
  const amqp = (options) => {
101
- const config = options.url === void 0 ? Config.provider(AmqpConfig)(Config.object({ url: Config.string("AMQP_URL", { default: "amqp://127.0.0.1:5672" }) })) : Provider(AmqpConfig)({ value: { url: options.url } });
108
+ const config = Config.provider(AmqpConfig)(Config.object({
109
+ url: Config.pinned(options.url, Config.string("AMQP_URL", { default: "amqp://127.0.0.1:5672" })),
110
+ connectTimeoutMs: Config.pinned(options.connectTimeoutMs, Config.integer("AMQP_CONNECT_TIMEOUT_MS", {
111
+ default: DEFAULT_CONNECT_TIMEOUT_MS,
112
+ min: 0
113
+ }))
114
+ }));
102
115
  return Module("Amqp")({
103
116
  needs: [Env, AmqpHandlersPort],
104
117
  provides: [config, Provider(AmqpRuntime)({
@@ -152,7 +165,7 @@ const createWorker = (host, config, options, handlers) => TypedAmqpWorker.create
152
165
  urls: [config.url],
153
166
  ...options.connectionOptions === void 0 ? {} : { connectionOptions: options.connectionOptions },
154
167
  ...options.defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions: options.defaultConsumerOptions },
155
- ...options.connectTimeoutMs === void 0 ? {} : { connectTimeoutMs: options.connectTimeoutMs }
168
+ connectTimeoutMs: config.connectTimeoutMs
156
169
  }).map((worker) => consume(worker, queuesOf(options.contract))).recoverDefect((cause) => ErrAsync(startFailed(cause)));
157
170
  const consume = (worker, queues) => {
158
171
  let closing;
@@ -187,17 +200,11 @@ const consume = (worker, queues) => {
187
200
  * ```
188
201
  */
189
202
  const AmqpModule = (name) => (options) => {
190
- const { contract, handlers, url, connectionOptions, defaultConsumerOptions, connectTimeoutMs } = options;
203
+ const { handlers } = options;
191
204
  const imports = options.imports ?? [];
192
205
  const provides = options.provides ?? [];
193
206
  const exports = options.exports ?? [];
194
- const starter = amqp({
195
- contract,
196
- ...url === void 0 ? {} : { url },
197
- ...connectionOptions === void 0 ? {} : { connectionOptions },
198
- ...defaultConsumerOptions === void 0 ? {} : { defaultConsumerOptions },
199
- ...connectTimeoutMs === void 0 ? {} : { connectTimeoutMs }
200
- });
207
+ const starter = amqp(options);
201
208
  return Module(name)({
202
209
  imports: [...imports, starter],
203
210
  provides: [handlers, ...provides],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/amqp-worker",
3
- "version": "0.5.0",
3
+ "version": "0.7.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",
@@ -57,19 +57,19 @@
57
57
  "unthrown": "5.7.0",
58
58
  "vitest": "4.1.11",
59
59
  "zod": "4.4.3",
60
- "@btravstack/config": "0.5.0",
61
- "@btravstack/core": "0.5.0",
62
- "@btravstack/di": "0.5.0",
60
+ "@btravstack/config": "0.7.0",
61
+ "@btravstack/core": "0.7.0",
62
+ "@btravstack/di": "0.7.0",
63
63
  "@btravstack/internal-test-infra": "0.0.0",
64
- "@btravstack/testing": "0.5.0"
64
+ "@btravstack/testing": "0.7.0"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@amqp-contract/worker": "^3.0.0-beta.6",
68
68
  "@opentelemetry/api": "^1",
69
69
  "unthrown": "^5.0.0",
70
- "@btravstack/config": "^0.5.0",
71
- "@btravstack/di": "^0.5.0",
72
- "@btravstack/core": "^0.5.0"
70
+ "@btravstack/config": "^0.7.0",
71
+ "@btravstack/core": "^0.7.0",
72
+ "@btravstack/di": "^0.7.0"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=22"