@warlock.js/herald 4.0.174 → 4.1.2
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 +36 -33
- package/cjs/index.cjs +1355 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/communicators/broker-registry.d.mts +157 -0
- package/esm/communicators/broker-registry.d.mts.map +1 -0
- package/esm/communicators/broker-registry.mjs +204 -0
- package/esm/communicators/broker-registry.mjs.map +1 -0
- package/esm/communicators/broker.d.mts +104 -0
- package/esm/communicators/broker.d.mts.map +1 -0
- package/esm/communicators/broker.mjs +104 -0
- package/esm/communicators/broker.mjs.map +1 -0
- package/esm/communicators/index.d.mts +2 -0
- package/esm/communicators/index.mjs +4 -0
- package/esm/contracts/broker-driver.contract.d.mts +200 -0
- package/esm/contracts/broker-driver.contract.d.mts.map +1 -0
- package/esm/contracts/channel.contract.d.mts +197 -0
- package/esm/contracts/channel.contract.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +2 -0
- package/esm/decorators/consumable.d.mts +17 -0
- package/esm/decorators/consumable.d.mts.map +1 -0
- package/esm/decorators/consumable.mjs +36 -0
- package/esm/decorators/consumable.mjs.map +1 -0
- package/esm/decorators/index.d.mts +1 -0
- package/esm/decorators/index.mjs +3 -0
- package/esm/drivers/index.d.mts +2 -0
- package/esm/drivers/index.mjs +5 -0
- package/esm/drivers/rabbitmq/index.d.mts +2 -0
- package/esm/drivers/rabbitmq/index.mjs +4 -0
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.mts +85 -0
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.mts.map +1 -0
- package/esm/drivers/rabbitmq/rabbitmq-channel.mjs +352 -0
- package/esm/drivers/rabbitmq/rabbitmq-channel.mjs.map +1 -0
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.mts +130 -0
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.mts.map +1 -0
- package/esm/drivers/rabbitmq/rabbitmq-driver.mjs +291 -0
- package/esm/drivers/rabbitmq/rabbitmq-driver.mjs.map +1 -0
- package/esm/index.d.mts +20 -0
- package/esm/index.mjs +16 -0
- package/esm/message-managers/event-consumer.d.mts +61 -0
- package/esm/message-managers/event-consumer.d.mts.map +1 -0
- package/esm/message-managers/event-consumer.mjs +63 -0
- package/esm/message-managers/event-consumer.mjs.map +1 -0
- package/esm/message-managers/event-message.d.mts +87 -0
- package/esm/message-managers/event-message.d.mts.map +1 -0
- package/esm/message-managers/event-message.mjs +68 -0
- package/esm/message-managers/event-message.mjs.map +1 -0
- package/esm/message-managers/index.d.mts +3 -0
- package/esm/message-managers/index.mjs +4 -0
- package/esm/message-managers/prepare-consumer-subscription.mjs +42 -0
- package/esm/message-managers/prepare-consumer-subscription.mjs.map +1 -0
- package/esm/message-managers/types.d.mts +23 -0
- package/esm/message-managers/types.d.mts.map +1 -0
- package/esm/types/channel.types.d.mts +23 -0
- package/esm/types/channel.types.d.mts.map +1 -0
- package/esm/types/connection.types.d.mts +67 -0
- package/esm/types/connection.types.d.mts.map +1 -0
- package/esm/types/driver.types.d.mts +13 -0
- package/esm/types/driver.types.d.mts.map +1 -0
- package/esm/types/index.d.mts +7 -0
- package/esm/types/message.types.d.mts +37 -0
- package/esm/types/message.types.d.mts.map +1 -0
- package/esm/types/publish.types.d.mts +16 -0
- package/esm/types/publish.types.d.mts.map +1 -0
- package/esm/types/registry.types.d.mts +8 -0
- package/esm/types/registry.types.d.mts.map +1 -0
- package/esm/types/subscribe.types.d.mts +21 -0
- package/esm/types/subscribe.types.d.mts.map +1 -0
- package/esm/use-case-broadcast.d.mts +41 -0
- package/esm/use-case-broadcast.d.mts.map +1 -0
- package/esm/use-case-broadcast.mjs +30 -0
- package/esm/use-case-broadcast.mjs.map +1 -0
- package/esm/utils/{connect-to-broker.d.ts → connect-to-broker.d.mts} +15 -10
- package/esm/utils/connect-to-broker.d.mts.map +1 -0
- package/esm/utils/connect-to-broker.mjs +168 -0
- package/esm/utils/connect-to-broker.mjs.map +1 -0
- package/esm/utils/index.d.mts +1 -0
- package/esm/utils/index.mjs +3 -0
- package/llms-full.txt +581 -0
- package/llms.txt +12 -0
- package/package.json +46 -46
- package/skills/README.md +21 -0
- package/skills/consume-message/SKILL.md +217 -0
- package/skills/herald-basics/SKILL.md +96 -0
- package/skills/publish-message/SKILL.md +172 -0
- package/skills/request-and-respond/SKILL.md +74 -0
- package/cjs/communicators/broker-registry.d.ts +0 -155
- package/cjs/communicators/broker-registry.d.ts.map +0 -1
- package/cjs/communicators/broker-registry.js +0 -206
- package/cjs/communicators/broker-registry.js.map +0 -1
- package/cjs/communicators/broker.d.ts +0 -100
- package/cjs/communicators/broker.d.ts.map +0 -1
- package/cjs/communicators/broker.js +0 -105
- package/cjs/communicators/broker.js.map +0 -1
- package/cjs/communicators/index.d.ts +0 -3
- package/cjs/communicators/index.d.ts.map +0 -1
- package/cjs/contracts/broker-driver.contract.d.ts +0 -196
- package/cjs/contracts/broker-driver.contract.d.ts.map +0 -1
- package/cjs/contracts/channel.contract.d.ts +0 -191
- package/cjs/contracts/channel.contract.d.ts.map +0 -1
- package/cjs/contracts/index.d.ts +0 -3
- package/cjs/contracts/index.d.ts.map +0 -1
- package/cjs/decorators/consumable.d.ts +0 -13
- package/cjs/decorators/consumable.d.ts.map +0 -1
- package/cjs/decorators/consumable.js +0 -33
- package/cjs/decorators/consumable.js.map +0 -1
- package/cjs/decorators/index.d.ts +0 -2
- package/cjs/decorators/index.d.ts.map +0 -1
- package/cjs/drivers/index.d.ts +0 -2
- package/cjs/drivers/index.d.ts.map +0 -1
- package/cjs/drivers/rabbitmq/index.d.ts +0 -3
- package/cjs/drivers/rabbitmq/index.d.ts.map +0 -1
- package/cjs/drivers/rabbitmq/rabbitmq-channel.d.ts +0 -79
- package/cjs/drivers/rabbitmq/rabbitmq-channel.d.ts.map +0 -1
- package/cjs/drivers/rabbitmq/rabbitmq-channel.js +0 -414
- package/cjs/drivers/rabbitmq/rabbitmq-channel.js.map +0 -1
- package/cjs/drivers/rabbitmq/rabbitmq-driver.d.ts +0 -124
- package/cjs/drivers/rabbitmq/rabbitmq-driver.d.ts.map +0 -1
- package/cjs/drivers/rabbitmq/rabbitmq-driver.js +0 -347
- package/cjs/drivers/rabbitmq/rabbitmq-driver.js.map +0 -1
- package/cjs/index.d.ts +0 -47
- package/cjs/index.d.ts.map +0 -1
- package/cjs/index.js +0 -1
- package/cjs/index.js.map +0 -1
- package/cjs/message-managers/event-consumer.d.ts +0 -64
- package/cjs/message-managers/event-consumer.d.ts.map +0 -1
- package/cjs/message-managers/event-consumer.js +0 -71
- package/cjs/message-managers/event-consumer.js.map +0 -1
- package/cjs/message-managers/event-message.d.ts +0 -90
- package/cjs/message-managers/event-message.d.ts.map +0 -1
- package/cjs/message-managers/event-message.js +0 -84
- package/cjs/message-managers/event-message.js.map +0 -1
- package/cjs/message-managers/index.d.ts +0 -4
- package/cjs/message-managers/index.d.ts.map +0 -1
- package/cjs/message-managers/prepare-consumer-subscription.d.ts +0 -4
- package/cjs/message-managers/prepare-consumer-subscription.d.ts.map +0 -1
- package/cjs/message-managers/prepare-consumer-subscription.js +0 -40
- package/cjs/message-managers/prepare-consumer-subscription.js.map +0 -1
- package/cjs/message-managers/types.d.ts +0 -20
- package/cjs/message-managers/types.d.ts.map +0 -1
- package/cjs/types/channel.types.d.ts +0 -19
- package/cjs/types/channel.types.d.ts.map +0 -1
- package/cjs/types/connection.types.d.ts +0 -65
- package/cjs/types/connection.types.d.ts.map +0 -1
- package/cjs/types/driver.types.d.ts +0 -10
- package/cjs/types/driver.types.d.ts.map +0 -1
- package/cjs/types/index.d.ts +0 -8
- package/cjs/types/index.d.ts.map +0 -1
- package/cjs/types/message.types.d.ts +0 -34
- package/cjs/types/message.types.d.ts.map +0 -1
- package/cjs/types/publish.types.d.ts +0 -13
- package/cjs/types/publish.types.d.ts.map +0 -1
- package/cjs/types/registry.types.d.ts +0 -4
- package/cjs/types/registry.types.d.ts.map +0 -1
- package/cjs/types/subscribe.types.d.ts +0 -18
- package/cjs/types/subscribe.types.d.ts.map +0 -1
- package/cjs/utils/connect-to-broker.d.ts +0 -131
- package/cjs/utils/connect-to-broker.d.ts.map +0 -1
- package/cjs/utils/connect-to-broker.js +0 -171
- package/cjs/utils/connect-to-broker.js.map +0 -1
- package/cjs/utils/index.d.ts +0 -2
- package/cjs/utils/index.d.ts.map +0 -1
- package/esm/communicators/broker-registry.d.ts +0 -155
- package/esm/communicators/broker-registry.d.ts.map +0 -1
- package/esm/communicators/broker-registry.js +0 -206
- package/esm/communicators/broker-registry.js.map +0 -1
- package/esm/communicators/broker.d.ts +0 -100
- package/esm/communicators/broker.d.ts.map +0 -1
- package/esm/communicators/broker.js +0 -105
- package/esm/communicators/broker.js.map +0 -1
- package/esm/communicators/index.d.ts +0 -3
- package/esm/communicators/index.d.ts.map +0 -1
- package/esm/contracts/broker-driver.contract.d.ts +0 -196
- package/esm/contracts/broker-driver.contract.d.ts.map +0 -1
- package/esm/contracts/channel.contract.d.ts +0 -191
- package/esm/contracts/channel.contract.d.ts.map +0 -1
- package/esm/contracts/index.d.ts +0 -3
- package/esm/contracts/index.d.ts.map +0 -1
- package/esm/decorators/consumable.d.ts +0 -13
- package/esm/decorators/consumable.d.ts.map +0 -1
- package/esm/decorators/consumable.js +0 -33
- package/esm/decorators/consumable.js.map +0 -1
- package/esm/decorators/index.d.ts +0 -2
- package/esm/decorators/index.d.ts.map +0 -1
- package/esm/drivers/index.d.ts +0 -2
- package/esm/drivers/index.d.ts.map +0 -1
- package/esm/drivers/rabbitmq/index.d.ts +0 -3
- package/esm/drivers/rabbitmq/index.d.ts.map +0 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.ts +0 -79
- package/esm/drivers/rabbitmq/rabbitmq-channel.d.ts.map +0 -1
- package/esm/drivers/rabbitmq/rabbitmq-channel.js +0 -414
- package/esm/drivers/rabbitmq/rabbitmq-channel.js.map +0 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.ts +0 -124
- package/esm/drivers/rabbitmq/rabbitmq-driver.d.ts.map +0 -1
- package/esm/drivers/rabbitmq/rabbitmq-driver.js +0 -347
- package/esm/drivers/rabbitmq/rabbitmq-driver.js.map +0 -1
- package/esm/index.d.ts +0 -47
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +0 -1
- package/esm/message-managers/event-consumer.d.ts +0 -64
- package/esm/message-managers/event-consumer.d.ts.map +0 -1
- package/esm/message-managers/event-consumer.js +0 -71
- package/esm/message-managers/event-consumer.js.map +0 -1
- package/esm/message-managers/event-message.d.ts +0 -90
- package/esm/message-managers/event-message.d.ts.map +0 -1
- package/esm/message-managers/event-message.js +0 -84
- package/esm/message-managers/event-message.js.map +0 -1
- package/esm/message-managers/index.d.ts +0 -4
- package/esm/message-managers/index.d.ts.map +0 -1
- package/esm/message-managers/prepare-consumer-subscription.d.ts +0 -4
- package/esm/message-managers/prepare-consumer-subscription.d.ts.map +0 -1
- package/esm/message-managers/prepare-consumer-subscription.js +0 -40
- package/esm/message-managers/prepare-consumer-subscription.js.map +0 -1
- package/esm/message-managers/types.d.ts +0 -20
- package/esm/message-managers/types.d.ts.map +0 -1
- package/esm/types/channel.types.d.ts +0 -19
- package/esm/types/channel.types.d.ts.map +0 -1
- package/esm/types/connection.types.d.ts +0 -65
- package/esm/types/connection.types.d.ts.map +0 -1
- package/esm/types/driver.types.d.ts +0 -10
- package/esm/types/driver.types.d.ts.map +0 -1
- package/esm/types/index.d.ts +0 -8
- package/esm/types/index.d.ts.map +0 -1
- package/esm/types/message.types.d.ts +0 -34
- package/esm/types/message.types.d.ts.map +0 -1
- package/esm/types/publish.types.d.ts +0 -13
- package/esm/types/publish.types.d.ts.map +0 -1
- package/esm/types/registry.types.d.ts +0 -4
- package/esm/types/registry.types.d.ts.map +0 -1
- package/esm/types/subscribe.types.d.ts +0 -18
- package/esm/types/subscribe.types.d.ts.map +0 -1
- package/esm/utils/connect-to-broker.d.ts.map +0 -1
- package/esm/utils/connect-to-broker.js +0 -171
- package/esm/utils/connect-to-broker.js.map +0 -1
- package/esm/utils/index.d.ts +0 -2
- package/esm/utils/index.d.ts.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { SubscribeOptions } from "../../types/subscribe.types.mjs";
|
|
2
|
+
import { ChannelOptions, ChannelStats } from "../../types/channel.types.mjs";
|
|
3
|
+
import { MessageHandler, ResponseHandler, Subscription } from "../../types/message.types.mjs";
|
|
4
|
+
import { PublishOptions, RequestOptions } from "../../types/publish.types.mjs";
|
|
5
|
+
import { ChannelContract } from "../../contracts/channel.contract.mjs";
|
|
6
|
+
//#region ../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-channel.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* RabbitMQ Channel Implementation
|
|
9
|
+
*
|
|
10
|
+
* Wraps a RabbitMQ queue/exchange with a unified API.
|
|
11
|
+
*
|
|
12
|
+
* @template TPayload - The typed payload
|
|
13
|
+
*/
|
|
14
|
+
declare class RabbitMQChannel<TPayload = unknown> implements ChannelContract<TPayload> {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly options: ChannelOptions<TPayload>;
|
|
17
|
+
private readonly amqpChannel;
|
|
18
|
+
private readonly subscriptions;
|
|
19
|
+
private asserted;
|
|
20
|
+
/**
|
|
21
|
+
* Create a new RabbitMQ channel
|
|
22
|
+
*/
|
|
23
|
+
constructor(name: string, amqpChannel: any, options?: ChannelOptions<TPayload>);
|
|
24
|
+
/**
|
|
25
|
+
* Assert the queue exists
|
|
26
|
+
*/
|
|
27
|
+
assert(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Publish a message
|
|
30
|
+
*/
|
|
31
|
+
publish(payload: TPayload, options?: PublishOptions): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Publish multiple messages
|
|
34
|
+
*/
|
|
35
|
+
publishBatch(messages: TPayload[], options?: PublishOptions): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Subscribe to messages
|
|
38
|
+
*
|
|
39
|
+
* Smart auto-ack behavior (when autoAck is not true):
|
|
40
|
+
* - If handler completes successfully without explicit ack/nack/reject → auto-ack
|
|
41
|
+
* - If handler throws an error → auto-nack (with retry if configured)
|
|
42
|
+
* - If handler explicitly calls ack/nack/reject → respects that call
|
|
43
|
+
*/
|
|
44
|
+
subscribe(handler: MessageHandler<TPayload>, options?: SubscribeOptions): Promise<Subscription>;
|
|
45
|
+
/**
|
|
46
|
+
* Unsubscribe by consumer ID
|
|
47
|
+
*/
|
|
48
|
+
unsubscribeById(consumerId: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Stop consuming messages on this channel.
|
|
51
|
+
* Cancels all active subscriptions gracefully.
|
|
52
|
+
*/
|
|
53
|
+
stopConsuming(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Send message to dead-letter queue
|
|
56
|
+
*/
|
|
57
|
+
private sendToDeadLetter;
|
|
58
|
+
/**
|
|
59
|
+
* Request-response pattern
|
|
60
|
+
*/
|
|
61
|
+
request<TResponse = unknown>(payload: TPayload, options?: RequestOptions): Promise<TResponse>;
|
|
62
|
+
/**
|
|
63
|
+
* Register response handler for RPC
|
|
64
|
+
*/
|
|
65
|
+
respond<TResponse = unknown>(handler: ResponseHandler<TPayload, TResponse>): Promise<Subscription>;
|
|
66
|
+
/**
|
|
67
|
+
* Get queue statistics
|
|
68
|
+
*/
|
|
69
|
+
stats(): Promise<ChannelStats>;
|
|
70
|
+
/**
|
|
71
|
+
* Purge all messages
|
|
72
|
+
*/
|
|
73
|
+
purge(): Promise<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Check if queue exists
|
|
76
|
+
*/
|
|
77
|
+
exists(): Promise<boolean>;
|
|
78
|
+
/**
|
|
79
|
+
* Delete the queue
|
|
80
|
+
*/
|
|
81
|
+
delete(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
export { RabbitMQChannel };
|
|
85
|
+
//# sourceMappingURL=rabbitmq-channel.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabbitmq-channel.d.mts","names":[],"sources":["../../../../../../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-channel.ts"],"mappings":";;;;;;;;;;;;;cAwBa,eAAA,gCAA+C,eAAA,CAAgB,QAAA;EAAA,SAC1D,IAAA;EAAA,SACA,OAAA,EAAS,cAAA,CAAe,QAAA;EAAA,iBAEvB,WAAA;EAAA,iBACA,aAAA;EAAA,QACT,QAAA;EAKoE;;;cAAzD,IAAA,UAAc,WAAA,OAAkB,OAAA,GAAU,cAAA,CAAe,QAAA;EA6B1B;;;EApBrC,MAAA,CAAA,GAAU,OAAA;EAyEoD;;;EArD9D,OAAA,CAAQ,OAAA,EAAS,QAAA,EAAU,OAAA,GAAU,cAAA,GAAiB,OAAA;EAsExD;;;EAjBE,YAAA,CAAa,QAAA,EAAU,QAAA,IAAY,OAAA,GAAU,cAAA,GAAiB,OAAA;EA4OhE;;;;;;;;EA9NE,SAAA,CACX,OAAA,EAAS,cAAA,CAAe,QAAA,GACxB,OAAA,GAAU,gBAAA,GACT,OAAA,CAAQ,YAAA;EA8RmB;;;EA5GjB,eAAA,CAAgB,UAAA,WAAqB,OAAA;EAiJ3B;;;;EArIV,aAAA,CAAA,GAAiB,OAAA;EA5S4B;;;EAAA,QAsT5C,gBAAA;EApTW;;;EAsUZ,OAAA,qBAAA,CACX,OAAA,EAAS,QAAA,EACT,OAAA,GAAU,cAAA,GACT,OAAA,CAAQ,SAAA;EArUH;;;EAyXK,OAAA,qBAAA,CACX,OAAA,EAAS,eAAA,CAAgB,QAAA,EAAU,SAAA,IAClC,OAAA,CAAQ,YAAA;EAtXkD;;;EAiYhD,KAAA,CAAA,GAAS,OAAA,CAAQ,YAAA;EAxXP;;;EAuYV,KAAA,CAAA,GAAS,OAAA;EAnX4B;;;EA6XrC,MAAA,CAAA,GAAU,OAAA;EAxUa;;;EAoVvB,MAAA,CAAA,GAAU,OAAA;AAAA"}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { v } from "@warlock.js/seal";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
|
|
4
|
+
//#region ../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-channel.ts
|
|
5
|
+
/**
|
|
6
|
+
* RabbitMQ Channel Implementation
|
|
7
|
+
*
|
|
8
|
+
* Wraps a RabbitMQ queue/exchange with a unified API.
|
|
9
|
+
*
|
|
10
|
+
* @template TPayload - The typed payload
|
|
11
|
+
*/
|
|
12
|
+
var RabbitMQChannel = class {
|
|
13
|
+
/**
|
|
14
|
+
* Create a new RabbitMQ channel
|
|
15
|
+
*/
|
|
16
|
+
constructor(name, amqpChannel, options) {
|
|
17
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
18
|
+
this.asserted = false;
|
|
19
|
+
this.name = name;
|
|
20
|
+
this.amqpChannel = amqpChannel;
|
|
21
|
+
this.options = options ?? {};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Assert the queue exists
|
|
25
|
+
*/
|
|
26
|
+
async assert() {
|
|
27
|
+
if (this.asserted) return;
|
|
28
|
+
const queueOptions = {
|
|
29
|
+
durable: this.options.durable ?? true,
|
|
30
|
+
autoDelete: this.options.autoDelete ?? false,
|
|
31
|
+
exclusive: this.options.exclusive ?? false,
|
|
32
|
+
messageTtl: this.options.messageTtl,
|
|
33
|
+
maxLength: this.options.maxLength,
|
|
34
|
+
deadLetterExchange: this.options.deadLetter?.channel ? "" : void 0,
|
|
35
|
+
deadLetterRoutingKey: this.options.deadLetter?.channel
|
|
36
|
+
};
|
|
37
|
+
await this.amqpChannel.assertQueue(this.name, queueOptions);
|
|
38
|
+
this.asserted = true;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Publish a message
|
|
42
|
+
*/
|
|
43
|
+
async publish(payload, options) {
|
|
44
|
+
await this.assert();
|
|
45
|
+
if (this.options.schema) {
|
|
46
|
+
const context = {
|
|
47
|
+
allValues: payload,
|
|
48
|
+
value: payload
|
|
49
|
+
};
|
|
50
|
+
const result = await v.validate(this.options.schema, payload, { context });
|
|
51
|
+
if (!result.isValid) throw new Error(`Message validation failed: ${JSON.stringify(result.errors)}`);
|
|
52
|
+
payload = result.data;
|
|
53
|
+
}
|
|
54
|
+
const messageId = randomUUID();
|
|
55
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
56
|
+
const messageContent = JSON.stringify({
|
|
57
|
+
payload,
|
|
58
|
+
metadata: {
|
|
59
|
+
messageId,
|
|
60
|
+
timestamp: timestamp.toISOString(),
|
|
61
|
+
correlationId: options?.correlationId,
|
|
62
|
+
headers: options?.headers
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const publishOptions = {
|
|
66
|
+
persistent: options?.persistent ?? true,
|
|
67
|
+
messageId,
|
|
68
|
+
timestamp: timestamp.getTime(),
|
|
69
|
+
correlationId: options?.correlationId,
|
|
70
|
+
expiration: options?.expiration?.toString(),
|
|
71
|
+
priority: options?.priority,
|
|
72
|
+
headers: options?.headers
|
|
73
|
+
};
|
|
74
|
+
if (options?.delay) publishOptions.headers = {
|
|
75
|
+
...publishOptions.headers,
|
|
76
|
+
"x-delay": options.delay
|
|
77
|
+
};
|
|
78
|
+
this.amqpChannel.sendToQueue(this.name, Buffer.from(messageContent), publishOptions);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Publish multiple messages
|
|
82
|
+
*/
|
|
83
|
+
async publishBatch(messages, options) {
|
|
84
|
+
for (const payload of messages) await this.publish(payload, options);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Subscribe to messages
|
|
88
|
+
*
|
|
89
|
+
* Smart auto-ack behavior (when autoAck is not true):
|
|
90
|
+
* - If handler completes successfully without explicit ack/nack/reject → auto-ack
|
|
91
|
+
* - If handler throws an error → auto-nack (with retry if configured)
|
|
92
|
+
* - If handler explicitly calls ack/nack/reject → respects that call
|
|
93
|
+
*/
|
|
94
|
+
async subscribe(handler, options) {
|
|
95
|
+
await this.assert();
|
|
96
|
+
const subscriptionId = options?.consumerId ?? randomUUID();
|
|
97
|
+
if (options?.prefetch) await this.amqpChannel.prefetch(options.prefetch);
|
|
98
|
+
const isFireAndForget = options?.autoAck === true;
|
|
99
|
+
const consumerOptions = {
|
|
100
|
+
noAck: isFireAndForget,
|
|
101
|
+
exclusive: options?.exclusive ?? false,
|
|
102
|
+
consumerTag: options?.group ?? subscriptionId
|
|
103
|
+
};
|
|
104
|
+
const { consumerTag } = await this.amqpChannel.consume(this.name, async (msg) => {
|
|
105
|
+
if (!msg) return;
|
|
106
|
+
let ackHandled = isFireAndForget;
|
|
107
|
+
try {
|
|
108
|
+
const content = JSON.parse(msg.content.toString());
|
|
109
|
+
let payload = content.payload;
|
|
110
|
+
if (this.options.schema) {
|
|
111
|
+
const context = {
|
|
112
|
+
allValues: payload,
|
|
113
|
+
value: payload
|
|
114
|
+
};
|
|
115
|
+
const result = await v.validate(this.options.schema, payload, { context });
|
|
116
|
+
if (!result.isValid) {
|
|
117
|
+
this.amqpChannel.nack(msg, false, false);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
payload = result.data;
|
|
121
|
+
}
|
|
122
|
+
const metadata = {
|
|
123
|
+
messageId: msg.properties.messageId || content.metadata?.messageId || randomUUID(),
|
|
124
|
+
timestamp: new Date(msg.properties.timestamp || content.metadata?.timestamp),
|
|
125
|
+
correlationId: msg.properties.correlationId || content.metadata?.correlationId,
|
|
126
|
+
replyTo: msg.properties.replyTo,
|
|
127
|
+
priority: msg.properties.priority,
|
|
128
|
+
headers: msg.properties.headers,
|
|
129
|
+
retryCount: msg.properties.headers?.["x-retry-count"] || 0,
|
|
130
|
+
originalChannel: this.name
|
|
131
|
+
};
|
|
132
|
+
const message = {
|
|
133
|
+
metadata,
|
|
134
|
+
payload,
|
|
135
|
+
raw: msg
|
|
136
|
+
};
|
|
137
|
+
await handler(message, {
|
|
138
|
+
ack: async () => {
|
|
139
|
+
if (!ackHandled) {
|
|
140
|
+
ackHandled = true;
|
|
141
|
+
this.amqpChannel.ack(msg);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
nack: async (requeue = true) => {
|
|
145
|
+
if (!ackHandled) {
|
|
146
|
+
ackHandled = true;
|
|
147
|
+
this.amqpChannel.nack(msg, false, requeue);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
reject: async () => {
|
|
151
|
+
if (!ackHandled) {
|
|
152
|
+
ackHandled = true;
|
|
153
|
+
this.amqpChannel.reject(msg, false);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
reply: async (replyPayload) => {
|
|
157
|
+
if (msg.properties.replyTo) {
|
|
158
|
+
const replyContent = JSON.stringify({
|
|
159
|
+
payload: replyPayload,
|
|
160
|
+
metadata: {
|
|
161
|
+
messageId: randomUUID(),
|
|
162
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
163
|
+
correlationId: msg.properties.correlationId
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
this.amqpChannel.sendToQueue(msg.properties.replyTo, Buffer.from(replyContent), { correlationId: msg.properties.correlationId });
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
retry: async (delay) => {
|
|
170
|
+
if (ackHandled) return;
|
|
171
|
+
ackHandled = true;
|
|
172
|
+
const retryCount = (metadata.retryCount || 0) + 1;
|
|
173
|
+
if (retryCount > (options?.retry?.maxRetries ?? 3)) {
|
|
174
|
+
if (options?.deadLetter) await this.sendToDeadLetter(message, options.deadLetter.channel);
|
|
175
|
+
this.amqpChannel.ack(msg);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const headers = {
|
|
179
|
+
...msg.properties.headers,
|
|
180
|
+
"x-retry-count": retryCount
|
|
181
|
+
};
|
|
182
|
+
if (delay) headers["x-delay"] = delay;
|
|
183
|
+
this.amqpChannel.sendToQueue(this.name, msg.content, {
|
|
184
|
+
...msg.properties,
|
|
185
|
+
headers
|
|
186
|
+
});
|
|
187
|
+
this.amqpChannel.ack(msg);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
if (!ackHandled) this.amqpChannel.ack(msg);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (ackHandled) return;
|
|
193
|
+
if (options?.retry) if ((msg.properties.headers?.["x-retry-count"] || 0) < options.retry.maxRetries) this.amqpChannel.nack(msg, false, true);
|
|
194
|
+
else if (options.deadLetter) this.amqpChannel.nack(msg, false, false);
|
|
195
|
+
else this.amqpChannel.reject(msg, false);
|
|
196
|
+
else this.amqpChannel.nack(msg, false, false);
|
|
197
|
+
}
|
|
198
|
+
}, consumerOptions);
|
|
199
|
+
const subscription = new RabbitMQSubscription(subscriptionId, this.name, consumerTag, this.amqpChannel);
|
|
200
|
+
this.subscriptions.set(subscriptionId, subscription);
|
|
201
|
+
return subscription;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Unsubscribe by consumer ID
|
|
205
|
+
*/
|
|
206
|
+
async unsubscribeById(consumerId) {
|
|
207
|
+
const subscription = this.subscriptions.get(consumerId);
|
|
208
|
+
if (subscription) {
|
|
209
|
+
await subscription.unsubscribe();
|
|
210
|
+
this.subscriptions.delete(consumerId);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Stop consuming messages on this channel.
|
|
215
|
+
* Cancels all active subscriptions gracefully.
|
|
216
|
+
*/
|
|
217
|
+
async stopConsuming() {
|
|
218
|
+
const cancellations = Array.from(this.subscriptions.values()).map((sub) => sub.unsubscribe());
|
|
219
|
+
await Promise.all(cancellations);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Send message to dead-letter queue
|
|
223
|
+
*/
|
|
224
|
+
async sendToDeadLetter(message, deadLetterChannel) {
|
|
225
|
+
const content = JSON.stringify({
|
|
226
|
+
payload: message.payload,
|
|
227
|
+
metadata: {
|
|
228
|
+
...message.metadata,
|
|
229
|
+
originalChannel: this.name
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
this.amqpChannel.sendToQueue(deadLetterChannel, Buffer.from(content), { persistent: true });
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Request-response pattern
|
|
236
|
+
*/
|
|
237
|
+
async request(payload, options) {
|
|
238
|
+
await this.assert();
|
|
239
|
+
const correlationId = randomUUID();
|
|
240
|
+
const timeout = options?.timeout ?? 3e4;
|
|
241
|
+
const { queue: replyQueue } = await this.amqpChannel.assertQueue("", {
|
|
242
|
+
exclusive: true,
|
|
243
|
+
autoDelete: true
|
|
244
|
+
});
|
|
245
|
+
return new Promise((resolve, reject) => {
|
|
246
|
+
const timeoutId = setTimeout(() => {
|
|
247
|
+
reject(/* @__PURE__ */ new Error(`Request timeout after ${timeout}ms`));
|
|
248
|
+
}, timeout);
|
|
249
|
+
this.amqpChannel.consume(replyQueue, (msg) => {
|
|
250
|
+
if (msg?.properties.correlationId === correlationId) {
|
|
251
|
+
clearTimeout(timeoutId);
|
|
252
|
+
resolve(JSON.parse(msg.content.toString()).payload);
|
|
253
|
+
}
|
|
254
|
+
}, { noAck: true });
|
|
255
|
+
const messageContent = JSON.stringify({
|
|
256
|
+
payload,
|
|
257
|
+
metadata: {
|
|
258
|
+
messageId: randomUUID(),
|
|
259
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
260
|
+
correlationId
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
this.amqpChannel.sendToQueue(this.name, Buffer.from(messageContent), {
|
|
264
|
+
correlationId,
|
|
265
|
+
replyTo: replyQueue,
|
|
266
|
+
expiration: timeout.toString(),
|
|
267
|
+
...options
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Register response handler for RPC
|
|
273
|
+
*/
|
|
274
|
+
async respond(handler) {
|
|
275
|
+
return this.subscribe(async (message, ctx) => {
|
|
276
|
+
const response = await handler(message, ctx);
|
|
277
|
+
await ctx.reply(response);
|
|
278
|
+
await ctx.ack();
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get queue statistics
|
|
283
|
+
*/
|
|
284
|
+
async stats() {
|
|
285
|
+
await this.assert();
|
|
286
|
+
const queueInfo = await this.amqpChannel.checkQueue(this.name);
|
|
287
|
+
return {
|
|
288
|
+
name: this.name,
|
|
289
|
+
messageCount: queueInfo.messageCount,
|
|
290
|
+
consumerCount: queueInfo.consumerCount
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Purge all messages
|
|
295
|
+
*/
|
|
296
|
+
async purge() {
|
|
297
|
+
await this.assert();
|
|
298
|
+
return (await this.amqpChannel.purgeQueue(this.name)).messageCount;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Check if queue exists
|
|
302
|
+
*/
|
|
303
|
+
async exists() {
|
|
304
|
+
try {
|
|
305
|
+
await this.amqpChannel.checkQueue(this.name);
|
|
306
|
+
return true;
|
|
307
|
+
} catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Delete the queue
|
|
313
|
+
*/
|
|
314
|
+
async delete() {
|
|
315
|
+
for (const subscription of this.subscriptions.values()) await subscription.unsubscribe();
|
|
316
|
+
this.subscriptions.clear();
|
|
317
|
+
try {
|
|
318
|
+
await this.amqpChannel.deleteQueue(this.name);
|
|
319
|
+
} catch {}
|
|
320
|
+
this.asserted = false;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* RabbitMQ Subscription Implementation
|
|
325
|
+
*/
|
|
326
|
+
var RabbitMQSubscription = class {
|
|
327
|
+
constructor(id, channel, consumerTag, amqpChannel) {
|
|
328
|
+
this._isActive = true;
|
|
329
|
+
this.id = id;
|
|
330
|
+
this.channel = channel;
|
|
331
|
+
this.consumerTag = consumerTag;
|
|
332
|
+
this.amqpChannel = amqpChannel;
|
|
333
|
+
}
|
|
334
|
+
async unsubscribe() {
|
|
335
|
+
if (!this._isActive) return;
|
|
336
|
+
await this.amqpChannel.cancel(this.consumerTag);
|
|
337
|
+
this._isActive = false;
|
|
338
|
+
}
|
|
339
|
+
async pause() {
|
|
340
|
+
await this.amqpChannel.cancel(this.consumerTag);
|
|
341
|
+
}
|
|
342
|
+
async resume() {
|
|
343
|
+
throw new Error("Resume is not supported for RabbitMQ. Please create a new subscription.");
|
|
344
|
+
}
|
|
345
|
+
isActive() {
|
|
346
|
+
return this._isActive;
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
//#endregion
|
|
351
|
+
export { RabbitMQChannel };
|
|
352
|
+
//# sourceMappingURL=rabbitmq-channel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabbitmq-channel.mjs","names":[],"sources":["../../../../../../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-channel.ts"],"sourcesContent":["import { v } from \"@warlock.js/seal\";\r\nimport { randomUUID } from \"node:crypto\";\r\nimport type { ChannelContract } from \"../../contracts\";\r\nimport type {\r\n ChannelOptions,\r\n ChannelStats,\r\n Message,\r\n MessageContext,\r\n MessageHandler,\r\n MessageMetadata,\r\n PublishOptions,\r\n RequestOptions,\r\n ResponseHandler,\r\n SubscribeOptions,\r\n Subscription,\r\n} from \"../../types\";\r\n\r\n/**\r\n * RabbitMQ Channel Implementation\r\n *\r\n * Wraps a RabbitMQ queue/exchange with a unified API.\r\n *\r\n * @template TPayload - The typed payload\r\n */\r\nexport class RabbitMQChannel<TPayload = unknown> implements ChannelContract<TPayload> {\r\n public readonly name: string;\r\n public readonly options: ChannelOptions<TPayload>;\r\n\r\n private readonly amqpChannel: any;\r\n private readonly subscriptions = new Map<string, RabbitMQSubscription>();\r\n private asserted = false;\r\n\r\n /**\r\n * Create a new RabbitMQ channel\r\n */\r\n public constructor(name: string, amqpChannel: any, options?: ChannelOptions<TPayload>) {\r\n this.name = name;\r\n this.amqpChannel = amqpChannel;\r\n this.options = options ?? {};\r\n }\r\n\r\n /**\r\n * Assert the queue exists\r\n */\r\n public async assert(): Promise<void> {\r\n if (this.asserted) return;\r\n\r\n const queueOptions = {\r\n durable: this.options.durable ?? true,\r\n autoDelete: this.options.autoDelete ?? false,\r\n exclusive: this.options.exclusive ?? false,\r\n messageTtl: this.options.messageTtl,\r\n maxLength: this.options.maxLength,\r\n deadLetterExchange: this.options.deadLetter?.channel ? \"\" : undefined,\r\n deadLetterRoutingKey: this.options.deadLetter?.channel,\r\n };\r\n\r\n await this.amqpChannel.assertQueue(this.name, queueOptions);\r\n this.asserted = true;\r\n }\r\n\r\n /**\r\n * Publish a message\r\n */\r\n public async publish(payload: TPayload, options?: PublishOptions): Promise<void> {\r\n await this.assert();\r\n\r\n // Validate with schema if provided\r\n if (this.options.schema) {\r\n const context = {\r\n allValues: payload,\r\n value: payload,\r\n };\r\n const result = await v.validate(this.options.schema, payload, { context });\r\n if (!result.isValid) {\r\n throw new Error(`Message validation failed: ${JSON.stringify(result.errors)}`);\r\n }\r\n payload = result.data as TPayload;\r\n }\r\n\r\n const messageId = randomUUID();\r\n const timestamp = new Date();\r\n\r\n const messageContent = JSON.stringify({\r\n payload,\r\n metadata: {\r\n messageId,\r\n timestamp: timestamp.toISOString(),\r\n correlationId: options?.correlationId,\r\n headers: options?.headers,\r\n },\r\n });\r\n\r\n const publishOptions: any = {\r\n persistent: options?.persistent ?? true,\r\n messageId,\r\n timestamp: timestamp.getTime(),\r\n correlationId: options?.correlationId,\r\n expiration: options?.expiration?.toString(),\r\n priority: options?.priority,\r\n headers: options?.headers,\r\n };\r\n\r\n // Handle delayed messages (requires rabbitmq-delayed-message-exchange plugin)\r\n if (options?.delay) {\r\n publishOptions.headers = {\r\n ...publishOptions.headers,\r\n \"x-delay\": options.delay,\r\n };\r\n }\r\n\r\n this.amqpChannel.sendToQueue(this.name, Buffer.from(messageContent), publishOptions);\r\n }\r\n\r\n /**\r\n * Publish multiple messages\r\n */\r\n public async publishBatch(messages: TPayload[], options?: PublishOptions): Promise<void> {\r\n for (const payload of messages) {\r\n await this.publish(payload, options);\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to messages\r\n *\r\n * Smart auto-ack behavior (when autoAck is not true):\r\n * - If handler completes successfully without explicit ack/nack/reject → auto-ack\r\n * - If handler throws an error → auto-nack (with retry if configured)\r\n * - If handler explicitly calls ack/nack/reject → respects that call\r\n */\r\n public async subscribe(\r\n handler: MessageHandler<TPayload>,\r\n options?: SubscribeOptions,\r\n ): Promise<Subscription> {\r\n await this.assert();\r\n\r\n // Use consumerId from options if provided, otherwise generate a random one\r\n const subscriptionId = options?.consumerId ?? randomUUID();\r\n\r\n // Set prefetch if specified\r\n if (options?.prefetch) {\r\n await this.amqpChannel.prefetch(options.prefetch);\r\n }\r\n\r\n // If autoAck is true, RabbitMQ handles ack immediately (fire-and-forget)\r\n const isFireAndForget = options?.autoAck === true;\r\n\r\n const consumerOptions = {\r\n noAck: isFireAndForget,\r\n exclusive: options?.exclusive ?? false,\r\n consumerTag: options?.group ?? subscriptionId,\r\n };\r\n\r\n const { consumerTag } = await this.amqpChannel.consume(\r\n this.name,\r\n async (msg: any) => {\r\n if (!msg) return;\r\n\r\n // Track if acknowledgment was handled explicitly\r\n let ackHandled = isFireAndForget;\r\n\r\n try {\r\n const content = JSON.parse(msg.content.toString());\r\n let payload = content.payload as TPayload;\r\n\r\n // Validate with schema if provided\r\n if (this.options.schema) {\r\n const context = {\r\n allValues: payload,\r\n value: payload,\r\n };\r\n const result = await v.validate(this.options.schema, payload, { context });\r\n if (!result.isValid) {\r\n // Reject invalid messages\r\n this.amqpChannel.nack(msg, false, false);\r\n return;\r\n }\r\n payload = result.data as TPayload;\r\n }\r\n\r\n const metadata: MessageMetadata = {\r\n messageId: msg.properties.messageId || content.metadata?.messageId || randomUUID(),\r\n timestamp: new Date(msg.properties.timestamp || content.metadata?.timestamp),\r\n correlationId: msg.properties.correlationId || content.metadata?.correlationId,\r\n replyTo: msg.properties.replyTo,\r\n priority: msg.properties.priority,\r\n headers: msg.properties.headers,\r\n retryCount: msg.properties.headers?.[\"x-retry-count\"] || 0,\r\n originalChannel: this.name,\r\n };\r\n\r\n const message: Message<TPayload> = {\r\n metadata,\r\n payload,\r\n raw: msg,\r\n };\r\n\r\n const context: MessageContext = {\r\n ack: async () => {\r\n if (!ackHandled) {\r\n ackHandled = true;\r\n this.amqpChannel.ack(msg);\r\n }\r\n },\r\n nack: async (requeue = true) => {\r\n if (!ackHandled) {\r\n ackHandled = true;\r\n this.amqpChannel.nack(msg, false, requeue);\r\n }\r\n },\r\n reject: async () => {\r\n if (!ackHandled) {\r\n ackHandled = true;\r\n this.amqpChannel.reject(msg, false);\r\n }\r\n },\r\n reply: async <T>(replyPayload: T) => {\r\n if (msg.properties.replyTo) {\r\n const replyContent = JSON.stringify({\r\n payload: replyPayload,\r\n metadata: {\r\n messageId: randomUUID(),\r\n timestamp: new Date().toISOString(),\r\n correlationId: msg.properties.correlationId,\r\n },\r\n });\r\n\r\n this.amqpChannel.sendToQueue(msg.properties.replyTo, Buffer.from(replyContent), {\r\n correlationId: msg.properties.correlationId,\r\n });\r\n }\r\n },\r\n retry: async (delay?: number) => {\r\n if (ackHandled) return;\r\n ackHandled = true;\r\n\r\n const retryCount = (metadata.retryCount || 0) + 1;\r\n const maxRetries = options?.retry?.maxRetries ?? 3;\r\n\r\n if (retryCount > maxRetries) {\r\n // Send to dead-letter if configured\r\n if (options?.deadLetter) {\r\n await this.sendToDeadLetter(message, options.deadLetter.channel);\r\n }\r\n this.amqpChannel.ack(msg);\r\n return;\r\n }\r\n\r\n // Republish with retry count\r\n const headers = {\r\n ...msg.properties.headers,\r\n \"x-retry-count\": retryCount,\r\n };\r\n\r\n if (delay) {\r\n headers[\"x-delay\"] = delay;\r\n }\r\n\r\n this.amqpChannel.sendToQueue(this.name, msg.content, { ...msg.properties, headers });\r\n\r\n this.amqpChannel.ack(msg);\r\n },\r\n };\r\n\r\n // Execute handler\r\n await handler(message, context);\r\n\r\n // Smart auto-ack: if handler succeeded and didn't explicitly handle ack\r\n if (!ackHandled) {\r\n this.amqpChannel.ack(msg);\r\n }\r\n } catch (error) {\r\n // Smart auto-nack: if handler threw and didn't explicitly handle ack\r\n if (ackHandled) return;\r\n\r\n // Handle errors - nack and potentially retry\r\n if (options?.retry) {\r\n const retryCount = msg.properties.headers?.[\"x-retry-count\"] || 0;\r\n if (retryCount < options.retry.maxRetries) {\r\n // Requeue for retry\r\n this.amqpChannel.nack(msg, false, true);\r\n } else if (options.deadLetter) {\r\n // Send to dead-letter\r\n this.amqpChannel.nack(msg, false, false);\r\n } else {\r\n this.amqpChannel.reject(msg, false);\r\n }\r\n } else {\r\n // No retry configured - reject without requeue\r\n this.amqpChannel.nack(msg, false, false);\r\n }\r\n }\r\n },\r\n consumerOptions,\r\n );\r\n\r\n const subscription = new RabbitMQSubscription(\r\n subscriptionId,\r\n this.name,\r\n consumerTag,\r\n this.amqpChannel,\r\n );\r\n\r\n this.subscriptions.set(subscriptionId, subscription);\r\n\r\n return subscription;\r\n }\r\n\r\n /**\r\n * Unsubscribe by consumer ID\r\n */\r\n public async unsubscribeById(consumerId: string): Promise<void> {\r\n const subscription = this.subscriptions.get(consumerId);\r\n if (subscription) {\r\n await subscription.unsubscribe();\r\n this.subscriptions.delete(consumerId);\r\n }\r\n }\r\n\r\n /**\r\n * Stop consuming messages on this channel.\r\n * Cancels all active subscriptions gracefully.\r\n */\r\n public async stopConsuming(): Promise<void> {\r\n const cancellations = Array.from(this.subscriptions.values()).map(sub =>\r\n sub.unsubscribe(),\r\n );\r\n await Promise.all(cancellations);\r\n }\r\n\r\n /**\r\n * Send message to dead-letter queue\r\n */\r\n private async sendToDeadLetter(\r\n message: Message<TPayload>,\r\n deadLetterChannel: string,\r\n ): Promise<void> {\r\n const content = JSON.stringify({\r\n payload: message.payload,\r\n metadata: {\r\n ...message.metadata,\r\n originalChannel: this.name,\r\n },\r\n });\r\n\r\n this.amqpChannel.sendToQueue(deadLetterChannel, Buffer.from(content), { persistent: true });\r\n }\r\n\r\n /**\r\n * Request-response pattern\r\n */\r\n public async request<TResponse = unknown>(\r\n payload: TPayload,\r\n options?: RequestOptions,\r\n ): Promise<TResponse> {\r\n await this.assert();\r\n\r\n const correlationId = randomUUID();\r\n const timeout = options?.timeout ?? 30000;\r\n\r\n // Create exclusive reply queue\r\n const { queue: replyQueue } = await this.amqpChannel.assertQueue(\"\", {\r\n exclusive: true,\r\n autoDelete: true,\r\n });\r\n\r\n return new Promise<TResponse>((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n reject(new Error(`Request timeout after ${timeout}ms`));\r\n }, timeout);\r\n\r\n // Consume reply\r\n this.amqpChannel.consume(\r\n replyQueue,\r\n (msg: any) => {\r\n if (msg?.properties.correlationId === correlationId) {\r\n clearTimeout(timeoutId);\r\n const content = JSON.parse(msg.content.toString());\r\n resolve(content.payload as TResponse);\r\n }\r\n },\r\n { noAck: true },\r\n );\r\n\r\n // Send request\r\n const messageContent = JSON.stringify({\r\n payload,\r\n metadata: {\r\n messageId: randomUUID(),\r\n timestamp: new Date().toISOString(),\r\n correlationId,\r\n },\r\n });\r\n\r\n this.amqpChannel.sendToQueue(this.name, Buffer.from(messageContent), {\r\n correlationId,\r\n replyTo: replyQueue,\r\n expiration: timeout.toString(),\r\n ...options,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Register response handler for RPC\r\n */\r\n public async respond<TResponse = unknown>(\r\n handler: ResponseHandler<TPayload, TResponse>,\r\n ): Promise<Subscription> {\r\n return this.subscribe(async (message, ctx) => {\r\n const response = await handler(message, ctx);\r\n await ctx.reply(response);\r\n await ctx.ack();\r\n });\r\n }\r\n\r\n /**\r\n * Get queue statistics\r\n */\r\n public async stats(): Promise<ChannelStats> {\r\n await this.assert();\r\n\r\n const queueInfo = await this.amqpChannel.checkQueue(this.name);\r\n\r\n return {\r\n name: this.name,\r\n messageCount: queueInfo.messageCount,\r\n consumerCount: queueInfo.consumerCount,\r\n };\r\n }\r\n\r\n /**\r\n * Purge all messages\r\n */\r\n public async purge(): Promise<number> {\r\n await this.assert();\r\n\r\n const result = await this.amqpChannel.purgeQueue(this.name);\r\n return result.messageCount;\r\n }\r\n\r\n /**\r\n * Check if queue exists\r\n */\r\n public async exists(): Promise<boolean> {\r\n try {\r\n await this.amqpChannel.checkQueue(this.name);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Delete the queue\r\n */\r\n public async delete(): Promise<void> {\r\n // Cancel all subscriptions\r\n for (const subscription of this.subscriptions.values()) {\r\n await subscription.unsubscribe();\r\n }\r\n this.subscriptions.clear();\r\n\r\n try {\r\n await this.amqpChannel.deleteQueue(this.name);\r\n } catch {\r\n // Ignore if queue doesn't exist\r\n }\r\n\r\n this.asserted = false;\r\n }\r\n}\r\n\r\n/**\r\n * RabbitMQ Subscription Implementation\r\n */\r\nclass RabbitMQSubscription implements Subscription {\r\n public readonly id: string;\r\n public readonly channel: string;\r\n public readonly consumerTag: string;\r\n\r\n private readonly amqpChannel: any;\r\n private _isActive = true;\r\n\r\n public constructor(id: string, channel: string, consumerTag: string, amqpChannel: any) {\r\n this.id = id;\r\n this.channel = channel;\r\n this.consumerTag = consumerTag;\r\n this.amqpChannel = amqpChannel;\r\n }\r\n\r\n public async unsubscribe(): Promise<void> {\r\n if (!this._isActive) return;\r\n\r\n await this.amqpChannel.cancel(this.consumerTag);\r\n this._isActive = false;\r\n }\r\n\r\n public async pause(): Promise<void> {\r\n // RabbitMQ doesn't have native pause, cancel consumer\r\n await this.amqpChannel.cancel(this.consumerTag);\r\n }\r\n\r\n public async resume(): Promise<void> {\r\n // Would need to re-subscribe - not directly supported\r\n throw new Error(\"Resume is not supported for RabbitMQ. Please create a new subscription.\");\r\n }\r\n\r\n public isActive(): boolean {\r\n return this._isActive;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;AAwBA,IAAa,kBAAb,MAAsF;;;;CAWpF,AAAO,YAAY,MAAc,aAAkB,SAAoC;uCANtD,IAAI,IAAkC;kBACpD;EAMjB,KAAK,OAAO;EACZ,KAAK,cAAc;EACnB,KAAK,UAAU,WAAW,CAAC;CAC7B;;;;CAKA,MAAa,SAAwB;EACnC,IAAI,KAAK,UAAU;EAEnB,MAAM,eAAe;GACnB,SAAS,KAAK,QAAQ,WAAW;GACjC,YAAY,KAAK,QAAQ,cAAc;GACvC,WAAW,KAAK,QAAQ,aAAa;GACrC,YAAY,KAAK,QAAQ;GACzB,WAAW,KAAK,QAAQ;GACxB,oBAAoB,KAAK,QAAQ,YAAY,UAAU,KAAK;GAC5D,sBAAsB,KAAK,QAAQ,YAAY;EACjD;EAEA,MAAM,KAAK,YAAY,YAAY,KAAK,MAAM,YAAY;EAC1D,KAAK,WAAW;CAClB;;;;CAKA,MAAa,QAAQ,SAAmB,SAAyC;EAC/E,MAAM,KAAK,OAAO;EAGlB,IAAI,KAAK,QAAQ,QAAQ;GACvB,MAAM,UAAU;IACd,WAAW;IACX,OAAO;GACT;GACA,MAAM,SAAS,MAAM,EAAE,SAAS,KAAK,QAAQ,QAAQ,SAAS,EAAE,QAAQ,CAAC;GACzE,IAAI,CAAC,OAAO,SACV,MAAM,IAAI,MAAM,8BAA8B,KAAK,UAAU,OAAO,MAAM,GAAG;GAE/E,UAAU,OAAO;EACnB;EAEA,MAAM,YAAY,WAAW;EAC7B,MAAM,4BAAY,IAAI,KAAK;EAE3B,MAAM,iBAAiB,KAAK,UAAU;GACpC;GACA,UAAU;IACR;IACA,WAAW,UAAU,YAAY;IACjC,eAAe,SAAS;IACxB,SAAS,SAAS;GACpB;EACF,CAAC;EAED,MAAM,iBAAsB;GAC1B,YAAY,SAAS,cAAc;GACnC;GACA,WAAW,UAAU,QAAQ;GAC7B,eAAe,SAAS;GACxB,YAAY,SAAS,YAAY,SAAS;GAC1C,UAAU,SAAS;GACnB,SAAS,SAAS;EACpB;EAGA,IAAI,SAAS,OACX,eAAe,UAAU;GACvB,GAAG,eAAe;GAClB,WAAW,QAAQ;EACrB;EAGF,KAAK,YAAY,YAAY,KAAK,MAAM,OAAO,KAAK,cAAc,GAAG,cAAc;CACrF;;;;CAKA,MAAa,aAAa,UAAsB,SAAyC;EACvF,KAAK,MAAM,WAAW,UACpB,MAAM,KAAK,QAAQ,SAAS,OAAO;CAEvC;;;;;;;;;CAUA,MAAa,UACX,SACA,SACuB;EACvB,MAAM,KAAK,OAAO;EAGlB,MAAM,iBAAiB,SAAS,cAAc,WAAW;EAGzD,IAAI,SAAS,UACX,MAAM,KAAK,YAAY,SAAS,QAAQ,QAAQ;EAIlD,MAAM,kBAAkB,SAAS,YAAY;EAE7C,MAAM,kBAAkB;GACtB,OAAO;GACP,WAAW,SAAS,aAAa;GACjC,aAAa,SAAS,SAAS;EACjC;EAEA,MAAM,EAAE,gBAAgB,MAAM,KAAK,YAAY,QAC7C,KAAK,MACL,OAAO,QAAa;GAClB,IAAI,CAAC,KAAK;GAGV,IAAI,aAAa;GAEjB,IAAI;IACF,MAAM,UAAU,KAAK,MAAM,IAAI,QAAQ,SAAS,CAAC;IACjD,IAAI,UAAU,QAAQ;IAGtB,IAAI,KAAK,QAAQ,QAAQ;KACvB,MAAM,UAAU;MACd,WAAW;MACX,OAAO;KACT;KACA,MAAM,SAAS,MAAM,EAAE,SAAS,KAAK,QAAQ,QAAQ,SAAS,EAAE,QAAQ,CAAC;KACzE,IAAI,CAAC,OAAO,SAAS;MAEnB,KAAK,YAAY,KAAK,KAAK,OAAO,KAAK;MACvC;KACF;KACA,UAAU,OAAO;IACnB;IAEA,MAAM,WAA4B;KAChC,WAAW,IAAI,WAAW,aAAa,QAAQ,UAAU,aAAa,WAAW;KACjF,WAAW,IAAI,KAAK,IAAI,WAAW,aAAa,QAAQ,UAAU,SAAS;KAC3E,eAAe,IAAI,WAAW,iBAAiB,QAAQ,UAAU;KACjE,SAAS,IAAI,WAAW;KACxB,UAAU,IAAI,WAAW;KACzB,SAAS,IAAI,WAAW;KACxB,YAAY,IAAI,WAAW,UAAU,oBAAoB;KACzD,iBAAiB,KAAK;IACxB;IAEA,MAAM,UAA6B;KACjC;KACA;KACA,KAAK;IACP;IAsEA,MAAM,QAAQ,SAAS;KAnErB,KAAK,YAAY;MACf,IAAI,CAAC,YAAY;OACf,aAAa;OACb,KAAK,YAAY,IAAI,GAAG;MAC1B;KACF;KACA,MAAM,OAAO,UAAU,SAAS;MAC9B,IAAI,CAAC,YAAY;OACf,aAAa;OACb,KAAK,YAAY,KAAK,KAAK,OAAO,OAAO;MAC3C;KACF;KACA,QAAQ,YAAY;MAClB,IAAI,CAAC,YAAY;OACf,aAAa;OACb,KAAK,YAAY,OAAO,KAAK,KAAK;MACpC;KACF;KACA,OAAO,OAAU,iBAAoB;MACnC,IAAI,IAAI,WAAW,SAAS;OAC1B,MAAM,eAAe,KAAK,UAAU;QAClC,SAAS;QACT,UAAU;SACR,WAAW,WAAW;SACtB,4BAAW,IAAI,KAAK,GAAE,YAAY;SAClC,eAAe,IAAI,WAAW;QAChC;OACF,CAAC;OAED,KAAK,YAAY,YAAY,IAAI,WAAW,SAAS,OAAO,KAAK,YAAY,GAAG,EAC9E,eAAe,IAAI,WAAW,cAChC,CAAC;MACH;KACF;KACA,OAAO,OAAO,UAAmB;MAC/B,IAAI,YAAY;MAChB,aAAa;MAEb,MAAM,cAAc,SAAS,cAAc,KAAK;MAGhD,IAAI,cAFe,SAAS,OAAO,cAAc,IAEpB;OAE3B,IAAI,SAAS,YACX,MAAM,KAAK,iBAAiB,SAAS,QAAQ,WAAW,OAAO;OAEjE,KAAK,YAAY,IAAI,GAAG;OACxB;MACF;MAGA,MAAM,UAAU;OACd,GAAG,IAAI,WAAW;OAClB,iBAAiB;MACnB;MAEA,IAAI,OACF,QAAQ,aAAa;MAGvB,KAAK,YAAY,YAAY,KAAK,MAAM,IAAI,SAAS;OAAE,GAAG,IAAI;OAAY;MAAQ,CAAC;MAEnF,KAAK,YAAY,IAAI,GAAG;KAC1B;IAI2B,CAAC;IAG9B,IAAI,CAAC,YACH,KAAK,YAAY,IAAI,GAAG;GAE5B,SAAS,OAAO;IAEd,IAAI,YAAY;IAGhB,IAAI,SAAS,OAEX,KADmB,IAAI,WAAW,UAAU,oBAAoB,KAC/C,QAAQ,MAAM,YAE7B,KAAK,YAAY,KAAK,KAAK,OAAO,IAAI;SACjC,IAAI,QAAQ,YAEjB,KAAK,YAAY,KAAK,KAAK,OAAO,KAAK;SAEvC,KAAK,YAAY,OAAO,KAAK,KAAK;SAIpC,KAAK,YAAY,KAAK,KAAK,OAAO,KAAK;GAE3C;EACF,GACA,eACF;EAEA,MAAM,eAAe,IAAI,qBACvB,gBACA,KAAK,MACL,aACA,KAAK,WACP;EAEA,KAAK,cAAc,IAAI,gBAAgB,YAAY;EAEnD,OAAO;CACT;;;;CAKA,MAAa,gBAAgB,YAAmC;EAC9D,MAAM,eAAe,KAAK,cAAc,IAAI,UAAU;EACtD,IAAI,cAAc;GAChB,MAAM,aAAa,YAAY;GAC/B,KAAK,cAAc,OAAO,UAAU;EACtC;CACF;;;;;CAMA,MAAa,gBAA+B;EAC1C,MAAM,gBAAgB,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC,EAAE,KAAI,QAChE,IAAI,YAAY,CAClB;EACA,MAAM,QAAQ,IAAI,aAAa;CACjC;;;;CAKA,MAAc,iBACZ,SACA,mBACe;EACf,MAAM,UAAU,KAAK,UAAU;GAC7B,SAAS,QAAQ;GACjB,UAAU;IACR,GAAG,QAAQ;IACX,iBAAiB,KAAK;GACxB;EACF,CAAC;EAED,KAAK,YAAY,YAAY,mBAAmB,OAAO,KAAK,OAAO,GAAG,EAAE,YAAY,KAAK,CAAC;CAC5F;;;;CAKA,MAAa,QACX,SACA,SACoB;EACpB,MAAM,KAAK,OAAO;EAElB,MAAM,gBAAgB,WAAW;EACjC,MAAM,UAAU,SAAS,WAAW;EAGpC,MAAM,EAAE,OAAO,eAAe,MAAM,KAAK,YAAY,YAAY,IAAI;GACnE,WAAW;GACX,YAAY;EACd,CAAC;EAED,OAAO,IAAI,SAAoB,SAAS,WAAW;GACjD,MAAM,YAAY,iBAAiB;IACjC,uBAAO,IAAI,MAAM,yBAAyB,QAAQ,GAAG,CAAC;GACxD,GAAG,OAAO;GAGV,KAAK,YAAY,QACf,aACC,QAAa;IACZ,IAAI,KAAK,WAAW,kBAAkB,eAAe;KACnD,aAAa,SAAS;KAEtB,QADgB,KAAK,MAAM,IAAI,QAAQ,SAAS,CAClC,EAAE,OAAoB;IACtC;GACF,GACA,EAAE,OAAO,KAAK,CAChB;GAGA,MAAM,iBAAiB,KAAK,UAAU;IACpC;IACA,UAAU;KACR,WAAW,WAAW;KACtB,4BAAW,IAAI,KAAK,GAAE,YAAY;KAClC;IACF;GACF,CAAC;GAED,KAAK,YAAY,YAAY,KAAK,MAAM,OAAO,KAAK,cAAc,GAAG;IACnE;IACA,SAAS;IACT,YAAY,QAAQ,SAAS;IAC7B,GAAG;GACL,CAAC;EACH,CAAC;CACH;;;;CAKA,MAAa,QACX,SACuB;EACvB,OAAO,KAAK,UAAU,OAAO,SAAS,QAAQ;GAC5C,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG;GAC3C,MAAM,IAAI,MAAM,QAAQ;GACxB,MAAM,IAAI,IAAI;EAChB,CAAC;CACH;;;;CAKA,MAAa,QAA+B;EAC1C,MAAM,KAAK,OAAO;EAElB,MAAM,YAAY,MAAM,KAAK,YAAY,WAAW,KAAK,IAAI;EAE7D,OAAO;GACL,MAAM,KAAK;GACX,cAAc,UAAU;GACxB,eAAe,UAAU;EAC3B;CACF;;;;CAKA,MAAa,QAAyB;EACpC,MAAM,KAAK,OAAO;EAGlB,QAAO,MADc,KAAK,YAAY,WAAW,KAAK,IAAI,GAC5C;CAChB;;;;CAKA,MAAa,SAA2B;EACtC,IAAI;GACF,MAAM,KAAK,YAAY,WAAW,KAAK,IAAI;GAC3C,OAAO;EACT,QAAQ;GACN,OAAO;EACT;CACF;;;;CAKA,MAAa,SAAwB;EAEnC,KAAK,MAAM,gBAAgB,KAAK,cAAc,OAAO,GACnD,MAAM,aAAa,YAAY;EAEjC,KAAK,cAAc,MAAM;EAEzB,IAAI;GACF,MAAM,KAAK,YAAY,YAAY,KAAK,IAAI;EAC9C,QAAQ,CAER;EAEA,KAAK,WAAW;CAClB;AACF;;;;AAKA,IAAM,uBAAN,MAAmD;CAQjD,AAAO,YAAY,IAAY,SAAiB,aAAqB,aAAkB;mBAFnE;EAGlB,KAAK,KAAK;EACV,KAAK,UAAU;EACf,KAAK,cAAc;EACnB,KAAK,cAAc;CACrB;CAEA,MAAa,cAA6B;EACxC,IAAI,CAAC,KAAK,WAAW;EAErB,MAAM,KAAK,YAAY,OAAO,KAAK,WAAW;EAC9C,KAAK,YAAY;CACnB;CAEA,MAAa,QAAuB;EAElC,MAAM,KAAK,YAAY,OAAO,KAAK,WAAW;CAChD;CAEA,MAAa,SAAwB;EAEnC,MAAM,IAAI,MAAM,yEAAyE;CAC3F;CAEA,AAAO,WAAoB;EACzB,OAAO,KAAK;CACd;AACF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { ChannelOptions } from "../../types/channel.types.mjs";
|
|
2
|
+
import { RabbitMQConnectionOptions } from "../../types/connection.types.mjs";
|
|
3
|
+
import { BrokerEvent, BrokerEventListener, HealthCheckResult } from "../../types/driver.types.mjs";
|
|
4
|
+
import { ChannelContract } from "../../contracts/channel.contract.mjs";
|
|
5
|
+
import { EventMessage } from "../../message-managers/event-message.mjs";
|
|
6
|
+
import { EventConsumerClass } from "../../message-managers/types.mjs";
|
|
7
|
+
import { BrokerDriverContract } from "../../contracts/broker-driver.contract.mjs";
|
|
8
|
+
//#region ../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-driver.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* RabbitMQ Driver
|
|
11
|
+
*
|
|
12
|
+
* Implementation of BrokerDriverContract for RabbitMQ/AMQP.
|
|
13
|
+
*
|
|
14
|
+
* **Important:** This driver requires the `amqplib` package to be installed.
|
|
15
|
+
* Install it with: `npx warlock add herald --driver=rabbitmq` or `npm install amqplib`
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const driver = new RabbitMQDriver({
|
|
20
|
+
* driver: "rabbitmq",
|
|
21
|
+
* host: "localhost",
|
|
22
|
+
* port: 5672,
|
|
23
|
+
* username: "guest",
|
|
24
|
+
* password: "guest",
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await driver.connect();
|
|
28
|
+
* const channel = driver.channel("user.created");
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare class RabbitMQDriver implements BrokerDriverContract {
|
|
32
|
+
readonly name: "rabbitmq";
|
|
33
|
+
readonly consumers: EventConsumerClass[];
|
|
34
|
+
private readonly options;
|
|
35
|
+
private readonly events;
|
|
36
|
+
private readonly channels;
|
|
37
|
+
private connection;
|
|
38
|
+
private amqpChannel;
|
|
39
|
+
private _isConnected;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new RabbitMQ driver
|
|
42
|
+
*
|
|
43
|
+
* @param options - RabbitMQ connection options
|
|
44
|
+
*/
|
|
45
|
+
constructor(options: RabbitMQConnectionOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Whether connected to RabbitMQ
|
|
48
|
+
*/
|
|
49
|
+
get isConnected(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe the given consumer class to the driver
|
|
52
|
+
*
|
|
53
|
+
* @param consumer - Consumer class to subscribe
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* driver.subscribe(UserUpdatedConsumer);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
subscribe(Consumer: EventConsumerClass): () => void;
|
|
61
|
+
/**
|
|
62
|
+
* Unsubscribe the given consumer
|
|
63
|
+
*/
|
|
64
|
+
unsubscribe(Consumer: EventConsumerClass): void;
|
|
65
|
+
/**
|
|
66
|
+
* Publish the given event message.
|
|
67
|
+
* Auto-creates the channel if it hasn't been accessed before.
|
|
68
|
+
*/
|
|
69
|
+
publish<TPayload = Record<string, any>>(event: EventMessage<TPayload>): void;
|
|
70
|
+
/**
|
|
71
|
+
* Connect to RabbitMQ
|
|
72
|
+
*/
|
|
73
|
+
connect(): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Build connection URL from options
|
|
76
|
+
*/
|
|
77
|
+
private buildConnectionUrl;
|
|
78
|
+
/**
|
|
79
|
+
* Handle reconnection
|
|
80
|
+
*/
|
|
81
|
+
private handleReconnect;
|
|
82
|
+
/**
|
|
83
|
+
* Disconnect from RabbitMQ
|
|
84
|
+
*/
|
|
85
|
+
disconnect(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Register event listener
|
|
88
|
+
*/
|
|
89
|
+
on(event: BrokerEvent, listener: BrokerEventListener): void;
|
|
90
|
+
/**
|
|
91
|
+
* Remove event listener
|
|
92
|
+
*/
|
|
93
|
+
off(event: BrokerEvent, listener: BrokerEventListener): void;
|
|
94
|
+
/**
|
|
95
|
+
* Get or create a channel
|
|
96
|
+
*/
|
|
97
|
+
channel<TPayload = unknown>(name: string, options?: ChannelOptions<TPayload>): ChannelContract<TPayload>;
|
|
98
|
+
/**
|
|
99
|
+
* Start consuming messages
|
|
100
|
+
*/
|
|
101
|
+
startConsuming(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Stop consuming messages from all subscribed channels.
|
|
104
|
+
* Gracefully cancels all active consumers.
|
|
105
|
+
*/
|
|
106
|
+
stopConsuming(): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Health check
|
|
109
|
+
*/
|
|
110
|
+
healthCheck(): Promise<HealthCheckResult>;
|
|
111
|
+
/**
|
|
112
|
+
* Get all channel names
|
|
113
|
+
*/
|
|
114
|
+
getChannelNames(): string[];
|
|
115
|
+
/**
|
|
116
|
+
* Close a specific channel
|
|
117
|
+
*/
|
|
118
|
+
closeChannel(name: string): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Get the raw AMQP channel (for advanced use)
|
|
121
|
+
*/
|
|
122
|
+
getRawChannel(): any;
|
|
123
|
+
/**
|
|
124
|
+
* Get the raw connection (for advanced use)
|
|
125
|
+
*/
|
|
126
|
+
getRawConnection(): any;
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { RabbitMQDriver };
|
|
130
|
+
//# sourceMappingURL=rabbitmq-driver.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rabbitmq-driver.d.mts","names":[],"sources":["../../../../../../../@warlock.js/herald/src/drivers/rabbitmq/rabbitmq-driver.ts"],"mappings":";;;;;;;;;;;;;;;AAsFA;;;;;;;;;;;;;;;cAAa,cAAA,YAA0B,oBAAA;EAAA,SACrB,IAAA;EAAA,SAEA,SAAA,EAAW,kBAAA;EAAA,iBAEV,OAAA;EAAA,iBACA,MAAA;EAAA,iBACA,QAAA;EAAA,QAET,UAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;EA6SiC;;;;;cAtStB,OAAA,EAAS,yBAAA;EAfZ;;;EAAA,IAsBL,WAAA,CAAA;EAlBM;;;;;;;;;;EAgCV,SAAA,CAAU,QAAA,EAAU,kBAAA;EAsBpB;;;EAAA,WAAA,CAAY,QAAA,EAAU,kBAAA;EAcd;;;;EAAR,OAAA,YAAmB,MAAA,cAAA,CAAqB,KAAA,EAAO,YAAA,CAAa,QAAA;EAOtD;;;EAAA,OAAA,CAAA,GAAW,OAAA;EAgHX;;;EAAA,QAzCL,kBAAA;EAmEE;;;EAAA,QA/CI,eAAA;EAsDI;;;EAjCL,UAAA,CAAA,GAAc,OAAA;EAwCpB;;;EAdA,EAAA,CAAG,KAAA,EAAO,WAAA,EAAa,QAAA,EAAU,mBAAA;EAgBb;;;EATpB,GAAA,CAAI,KAAA,EAAO,WAAA,EAAa,QAAA,EAAU,mBAAA;EA2B5B;;;EApBN,OAAA,oBAAA,CACL,IAAA,UACA,OAAA,GAAU,cAAA,CAAe,QAAA,IACxB,eAAA,CAAgB,QAAA;EAoCN;;;EAnBA,cAAA,CAAA,GAAkB,OAAA;EA0DlB;;;;EAjDA,aAAA,CAAA,GAAiB,OAAA;EAmEP;AAAA;;EAzDV,WAAA,CAAA,GAAe,OAAA,CAAQ,iBAAA;;;;EAgC7B,eAAA,CAAA;;;;EAOM,YAAA,CAAa,IAAA,WAAe,OAAA;;;;EAWlC,aAAA,CAAA;;;;EAOA,gBAAA,CAAA;AAAA"}
|