@diia-inhouse/diia-queue 13.3.3 → 14.0.10
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/dist/constants.js +9 -9
- package/dist/index.d.ts +27 -0
- package/dist/index.js +23 -21
- package/dist/interfaces/deps.d.ts +30 -0
- package/dist/interfaces/externalCommunicator.d.ts +58 -0
- package/dist/interfaces/index.d.ts +95 -0
- package/dist/interfaces/index.js +7 -30
- package/dist/interfaces/messageBrokerServiceConfig.d.ts +80 -0
- package/dist/interfaces/messageBrokerServiceConfig.js +27 -24
- package/dist/interfaces/messageHandler.d.ts +6 -0
- package/dist/interfaces/metrics/index.d.ts +23 -0
- package/dist/interfaces/metrics/index.js +12 -16
- package/dist/interfaces/options.d.ts +52 -0
- package/dist/interfaces/providers/rabbitmq/amqpConnection.d.ts +33 -0
- package/dist/interfaces/providers/rabbitmq/amqpConnection.js +14 -17
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.d.ts +20 -0
- package/dist/interfaces/providers/rabbitmq/index.d.ts +107 -0
- package/dist/interfaces/providers/rabbitmq/index.js +35 -47
- package/dist/interfaces/queueConfig/configs.d.ts +47 -0
- package/dist/interfaces/queueConfig/configs.js +8 -9
- package/dist/interfaces/queueConfig/index.d.ts +1 -0
- package/dist/interfaces/queueContext.d.ts +8 -0
- package/dist/interfaces/queueStatus.d.ts +15 -0
- package/dist/interfaces/queueStatus.js +8 -9
- package/dist/metrics/index.js +5 -8
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +6 -22
- package/dist/providers/rabbitmq/amqpAsserter.d.ts +53 -0
- package/dist/providers/rabbitmq/amqpAsserter.js +369 -416
- package/dist/providers/rabbitmq/amqpConnection.d.ts +24 -0
- package/dist/providers/rabbitmq/amqpConnection.js +97 -150
- package/dist/providers/rabbitmq/amqpListener.d.ts +47 -0
- package/dist/providers/rabbitmq/amqpListener.js +218 -225
- package/dist/providers/rabbitmq/amqpPublisher.d.ts +38 -0
- package/dist/providers/rabbitmq/amqpPublisher.js +184 -191
- package/dist/providers/rabbitmq/index.d.ts +56 -0
- package/dist/providers/rabbitmq/index.js +161 -186
- package/dist/services/communicator.d.ts +66 -0
- package/dist/services/communicator.js +164 -186
- package/dist/services/eventBus.d.ts +25 -0
- package/dist/services/eventBus.js +45 -57
- package/dist/services/eventCommunicator.js +75 -124
- package/dist/services/eventMessageHandler.d.ts +25 -0
- package/dist/services/eventMessageHandler.js +112 -129
- package/dist/services/eventMessageValidator.d.ts +13 -0
- package/dist/services/eventMessageValidator.js +59 -44
- package/dist/services/externalCommunicator.d.ts +114 -0
- package/dist/services/externalCommunicator.js +149 -140
- package/dist/services/externalEventBus.d.ts +39 -0
- package/dist/services/externalEventBus.js +144 -162
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.js +10 -26
- package/dist/services/metrics.d.ts +15 -0
- package/dist/services/metrics.js +46 -49
- package/dist/services/optionsBuilder.d.ts +14 -0
- package/dist/services/optionsBuilder.js +43 -58
- package/dist/services/queue.d.ts +29 -0
- package/dist/services/queue.js +78 -93
- package/dist/services/scheduledTask.d.ts +30 -0
- package/dist/services/scheduledTask.js +60 -68
- package/dist/services/task.d.ts +33 -0
- package/dist/services/task.js +160 -176
- package/dist/utils.js +7 -11
- package/package.json +44 -50
- package/dist/constants.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interfaces/deps.js +0 -3
- package/dist/interfaces/deps.js.map +0 -1
- package/dist/interfaces/externalCommunicator.js +0 -3
- package/dist/interfaces/externalCommunicator.js.map +0 -1
- package/dist/interfaces/index.js.map +0 -1
- package/dist/interfaces/messageBrokerServiceConfig.js.map +0 -1
- package/dist/interfaces/messageHandler.js +0 -3
- package/dist/interfaces/messageHandler.js.map +0 -1
- package/dist/interfaces/metrics/index.js.map +0 -1
- package/dist/interfaces/options.js +0 -3
- package/dist/interfaces/options.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/amqpConnection.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.js +0 -4
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/index.js.map +0 -1
- package/dist/interfaces/queueConfig/configs.js.map +0 -1
- package/dist/interfaces/queueConfig/index.js +0 -18
- package/dist/interfaces/queueConfig/index.js.map +0 -1
- package/dist/interfaces/queueContext.js +0 -3
- package/dist/interfaces/queueContext.js.map +0 -1
- package/dist/interfaces/queueStatus.js.map +0 -1
- package/dist/interfaces/services/eventMessageHandler.js +0 -3
- package/dist/interfaces/services/eventMessageHandler.js.map +0 -1
- package/dist/metrics/index.js.map +0 -1
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/rabbitmq/amqpAsserter.js.map +0 -1
- package/dist/providers/rabbitmq/amqpConnection.js.map +0 -1
- package/dist/providers/rabbitmq/amqpListener.js.map +0 -1
- package/dist/providers/rabbitmq/amqpPublisher.js.map +0 -1
- package/dist/providers/rabbitmq/index.js.map +0 -1
- package/dist/services/communicator.js.map +0 -1
- package/dist/services/eventBus.js.map +0 -1
- package/dist/services/eventCommunicator.js.map +0 -1
- package/dist/services/eventMessageHandler.js.map +0 -1
- package/dist/services/eventMessageValidator.js.map +0 -1
- package/dist/services/externalCommunicator.js.map +0 -1
- package/dist/services/externalEventBus.js.map +0 -1
- package/dist/services/index.js.map +0 -1
- package/dist/services/metrics.js.map +0 -1
- package/dist/services/optionsBuilder.js.map +0 -1
- package/dist/services/queue.js.map +0 -1
- package/dist/services/scheduledTask.js.map +0 -1
- package/dist/services/task.js.map +0 -1
- package/dist/types/constants.d.ts +0 -8
- package/dist/types/index.d.ts +0 -4
- package/dist/types/interfaces/deps.d.ts +0 -26
- package/dist/types/interfaces/externalCommunicator.d.ts +0 -54
- package/dist/types/interfaces/index.d.ts +0 -99
- package/dist/types/interfaces/messageBrokerServiceConfig.d.ts +0 -79
- package/dist/types/interfaces/messageHandler.d.ts +0 -2
- package/dist/types/interfaces/metrics/index.d.ts +0 -20
- package/dist/types/interfaces/options.d.ts +0 -49
- package/dist/types/interfaces/providers/rabbitmq/amqpConnection.d.ts +0 -29
- package/dist/types/interfaces/providers/rabbitmq/amqpPublisher.d.ts +0 -16
- package/dist/types/interfaces/providers/rabbitmq/index.d.ts +0 -114
- package/dist/types/interfaces/queueConfig/configs.d.ts +0 -47
- package/dist/types/interfaces/queueConfig/index.d.ts +0 -1
- package/dist/types/interfaces/queueContext.d.ts +0 -4
- package/dist/types/interfaces/queueStatus.d.ts +0 -11
- package/dist/types/interfaces/services/eventMessageHandler.d.ts +0 -5
- package/dist/types/metrics/index.d.ts +0 -3
- package/dist/types/providers/index.d.ts +0 -5
- package/dist/types/providers/rabbitmq/amqpAsserter.d.ts +0 -49
- package/dist/types/providers/rabbitmq/amqpConnection.d.ts +0 -20
- package/dist/types/providers/rabbitmq/amqpListener.d.ts +0 -42
- package/dist/types/providers/rabbitmq/amqpPublisher.d.ts +0 -34
- package/dist/types/providers/rabbitmq/index.d.ts +0 -52
- package/dist/types/services/communicator.d.ts +0 -57
- package/dist/types/services/eventBus.d.ts +0 -20
- package/dist/types/services/eventCommunicator.d.ts +0 -15
- package/dist/types/services/eventMessageHandler.d.ts +0 -19
- package/dist/types/services/eventMessageValidator.d.ts +0 -9
- package/dist/types/services/externalCommunicator.d.ts +0 -110
- package/dist/types/services/externalEventBus.d.ts +0 -33
- package/dist/types/services/index.d.ts +0 -9
- package/dist/types/services/metrics.d.ts +0 -11
- package/dist/types/services/optionsBuilder.d.ts +0 -10
- package/dist/types/services/queue.d.ts +0 -23
- package/dist/types/services/scheduledTask.d.ts +0 -25
- package/dist/types/services/task.d.ts +0 -28
- package/dist/types/utils.d.ts +0 -3
- package/dist/utils.js.map +0 -1
|
@@ -1,140 +1,149 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
import { ExternalCommunicatorError } from "@diia-inhouse/errors";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
//#region src/services/externalCommunicator.ts
|
|
4
|
+
var ExternalCommunicator = class {
|
|
5
|
+
externalEventBus;
|
|
6
|
+
eventMessageValidator;
|
|
7
|
+
logger;
|
|
8
|
+
constructor(externalEventBus, eventMessageValidator, logger) {
|
|
9
|
+
this.externalEventBus = externalEventBus;
|
|
10
|
+
this.eventMessageValidator = eventMessageValidator;
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Synchronous request/response over the external event bus.
|
|
15
|
+
*
|
|
16
|
+
* Publishes `event` to the configured external exchange wrapped as
|
|
17
|
+
* `{ uuid, request }` and awaits the subscriber's response on the same call.
|
|
18
|
+
* The response envelope is validated against `ops.validationRules`, and any embedded error is rethrown as
|
|
19
|
+
* {@link ExternalCommunicatorError}.
|
|
20
|
+
*
|
|
21
|
+
* Use this when the caller needs the response inline (e.g. a user-facing
|
|
22
|
+
* request that must block on `AGateway`). For fire-and-forget or fan-out
|
|
23
|
+
* flows, use the `default` publish + listener pattern instead.
|
|
24
|
+
*
|
|
25
|
+
* ### Transport
|
|
26
|
+
*
|
|
27
|
+
* Implemented on top of RabbitMQ's
|
|
28
|
+
* [direct reply-to](https://www.rabbitmq.com/docs/direct-reply-to)
|
|
29
|
+
* feature: the publisher consumes the pseudo-queue
|
|
30
|
+
* `amq.rabbitmq.reply-to` and stamps each request with `replyTo` +
|
|
31
|
+
* `correlationId`. The subscriber publishes its response back to that
|
|
32
|
+
* `replyTo` on the default exchange, and this call resolves when the
|
|
33
|
+
* matching `correlationId` arrives. No reply queue is declared per
|
|
34
|
+
* request, so there is no per-call broker setup overhead.
|
|
35
|
+
*
|
|
36
|
+
* ### Response contract
|
|
37
|
+
*
|
|
38
|
+
* The subscriber must respond with an
|
|
39
|
+
* {@link ExternalCommunicatorResponse} envelope:
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* { uuid: string, response: T, error?: { http_code, message?, data? } }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* On success this method returns **only the `response` field** typed as
|
|
46
|
+
* `T` — the wrapping `uuid` and the envelope itself are not exposed to
|
|
47
|
+
* the caller. Therefore `T` should describe the shape of `response`, not
|
|
48
|
+
* of the full envelope.
|
|
49
|
+
*
|
|
50
|
+
* ### Error contract
|
|
51
|
+
*
|
|
52
|
+
* Errors travel through the same envelope (`error` field on the
|
|
53
|
+
* subscriber's response — this is **not** a transport-level failure),
|
|
54
|
+
* but on the caller side they are surfaced as a thrown
|
|
55
|
+
* {@link ExternalCommunicatorError} instead of being returned. The
|
|
56
|
+
* envelope's `error` payload is mapped onto the exception so no data is
|
|
57
|
+
* lost:
|
|
58
|
+
*
|
|
59
|
+
* - `error.message` → `Error.message` (falls back to `'unknown error'`
|
|
60
|
+
* when missing).
|
|
61
|
+
* - `error.http_code` → exception's status code (read via `getCode()`).
|
|
62
|
+
* - `error.data` → exception's data bag (read via `getData()`), spread
|
|
63
|
+
* alongside `event` (the event name) and `httpCode` (a duplicate of
|
|
64
|
+
* the status code, kept on `data` for downstream consumers).
|
|
65
|
+
*
|
|
66
|
+
* Callers that need to inspect the original status or payload should
|
|
67
|
+
* `catch` the error and read those fields:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* try {
|
|
71
|
+
* await externalCommunicator.receiveDirect<T>(event, req, ops)
|
|
72
|
+
* } catch (err) {
|
|
73
|
+
* if (err instanceof ExternalCommunicatorError) {
|
|
74
|
+
* err.getCode() // original error.http_code
|
|
75
|
+
* err.getData() // { event, httpCode, ...error.data }
|
|
76
|
+
* err.message // error.message || 'unknown error'
|
|
77
|
+
* }
|
|
78
|
+
* throw err
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @typeParam T - shape of the successful `response` payload returned by the subscriber.
|
|
83
|
+
* @param event - external event name. Must be declared in
|
|
84
|
+
* `serviceRulesConfig.topicsConfig[QueueConfigType.External][topicName].events[]`
|
|
85
|
+
* so the event resolves to an exchange (or pass `ops.exchangeName`
|
|
86
|
+
* to override the lookup).
|
|
87
|
+
* @param request - payload forwarded to the subscriber. Defaults to `{}`.
|
|
88
|
+
* @param ops - direct-call options. See {@link ReceiveDirectOps}.
|
|
89
|
+
* @returns the subscriber's `response` field, typed as `T`. The envelope's
|
|
90
|
+
* `uuid` and `error` fields are not returned.
|
|
91
|
+
*
|
|
92
|
+
* @throws {ExternalCommunicatorError} when the subscriber responds with an
|
|
93
|
+
* `error` envelope. The original `http_code`, `message`, and `data`
|
|
94
|
+
* fields are preserved on the thrown error.
|
|
95
|
+
* @throws {Error} `'Message in a wrong format was received from a direct channel'`
|
|
96
|
+
* when `validationRules` are provided and the response fails validation.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* const result = await externalCommunicator.receiveDirect<{ data: string }>(
|
|
101
|
+
* 'notary.lookup',
|
|
102
|
+
* { notaryCertificateNumber: '1234', requestId: '-0' },
|
|
103
|
+
* {
|
|
104
|
+
* // Describes the inner `response` only; the envelope (uuid,
|
|
105
|
+
* // error, meta, ...) is wrapped by the validator.
|
|
106
|
+
* validationRules: { data: { type: 'string' } },
|
|
107
|
+
* timeout: DurationMs.Second * 5,
|
|
108
|
+
* },
|
|
109
|
+
* )
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
async receiveDirect(event, request = {}, ops) {
|
|
113
|
+
const { exchangeName, validationRules, ignoreCache, timeout, registryApiVersion, requestUuid = randomUUID() } = ops;
|
|
114
|
+
const payload = {
|
|
115
|
+
uuid: requestUuid,
|
|
116
|
+
request
|
|
117
|
+
};
|
|
118
|
+
const options = {
|
|
119
|
+
ignoreCache,
|
|
120
|
+
timeout,
|
|
121
|
+
exchangeName,
|
|
122
|
+
registryApiVersion
|
|
123
|
+
};
|
|
124
|
+
const externalResponse = await this.externalEventBus.publishDirect(event, payload, options);
|
|
125
|
+
this.logger.debug("External direct response", externalResponse);
|
|
126
|
+
if (validationRules) try {
|
|
127
|
+
this.eventMessageValidator.validateSyncedEventMessage(externalResponse, validationRules);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
const errorMsg = "Message in a wrong format was received from a direct channel";
|
|
130
|
+
this.logger.error(errorMsg, {
|
|
131
|
+
err,
|
|
132
|
+
externalResponse
|
|
133
|
+
});
|
|
134
|
+
throw new Error(errorMsg, { cause: err });
|
|
135
|
+
}
|
|
136
|
+
const { error, response } = externalResponse.payload;
|
|
137
|
+
if (error) {
|
|
138
|
+
this.logger.error(`Error received by an external event ${event}: ${error.http_code} ${error.message}`, { requestUuid });
|
|
139
|
+
throw new ExternalCommunicatorError(error.message || "unknown error", error.http_code, {
|
|
140
|
+
event,
|
|
141
|
+
httpCode: error.http_code,
|
|
142
|
+
...error.data
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return response;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
//#endregion
|
|
149
|
+
export { ExternalCommunicator };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ExchangeName, ExchangeOptions } from "../interfaces/messageBrokerServiceConfig.js";
|
|
2
|
+
import { PublishDirectOptions, PublishOptions } from "../interfaces/options.js";
|
|
3
|
+
import { EventName } from "../interfaces/queueConfig/configs.js";
|
|
4
|
+
import { MessagePayload, PublishingResult } from "../interfaces/providers/rabbitmq/amqpPublisher.js";
|
|
5
|
+
import { EventBusListener, ExternalEventBusQueue, MessageBrokerServiceEventsListener } from "../interfaces/index.js";
|
|
6
|
+
import { RabbitMQProvider } from "../providers/rabbitmq/index.js";
|
|
7
|
+
import { Communicator } from "./communicator.js";
|
|
8
|
+
import { EventMessageHandler } from "./eventMessageHandler.js";
|
|
9
|
+
import { OnInit } from "@diia-inhouse/types";
|
|
10
|
+
import Logger$1 from "@diia-inhouse/diia-logger";
|
|
11
|
+
import { EnvService } from "@diia-inhouse/env";
|
|
12
|
+
|
|
13
|
+
//#region src/services/externalEventBus.d.ts
|
|
14
|
+
declare class ExternalEventBus extends Communicator implements ExternalEventBusQueue, OnInit {
|
|
15
|
+
private readonly envService;
|
|
16
|
+
private readonly eventCommunicator;
|
|
17
|
+
private readonly publishEventsSet;
|
|
18
|
+
private readonly subscribeEventsSet;
|
|
19
|
+
private readonly exchangePrefixName;
|
|
20
|
+
private readonly eventQueueMap;
|
|
21
|
+
constructor(logger: Logger$1, systemServiceName: string, envService: EnvService, queueProvider: RabbitMQProvider, externalEventListenerList: EventBusListener[], eventMessageHandler: EventMessageHandler, hostName: string);
|
|
22
|
+
static BuildRequestRoutingKey(eventName: string): string;
|
|
23
|
+
static BuildResponseRoutingKey(eventName: EventName, portalEvents?: string[]): string;
|
|
24
|
+
private static prepareQueuePrefix;
|
|
25
|
+
publish(eventName: EventName, payload: MessagePayload, options?: PublishOptions): Promise<PublishingResult>;
|
|
26
|
+
publishDirect<T>(eventName: EventName, payload: MessagePayload, options?: PublishDirectOptions): Promise<T>;
|
|
27
|
+
protected getUnicastListeners(): MessageBrokerServiceEventsListener[];
|
|
28
|
+
protected getExchangeNameWithSuffix(topic: ExchangeName): string;
|
|
29
|
+
protected getProducerExchangesOptions(): ExchangeOptions[];
|
|
30
|
+
protected override getMulticastListeners(): MessageBrokerServiceEventsListener[];
|
|
31
|
+
private getPublishMessage;
|
|
32
|
+
private getPublishRoutingKey;
|
|
33
|
+
private defineQueuesAndExchangesOptionsBasedOnGlobalConfig;
|
|
34
|
+
private buildEventQueueMap;
|
|
35
|
+
private buildResponseQueueName;
|
|
36
|
+
private buildRequestQueueName;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ExternalEventBus };
|
|
@@ -1,163 +1,145 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Message } from "../interfaces/providers/rabbitmq/index.js";
|
|
2
|
+
import { QueueTypes } from "../interfaces/messageBrokerServiceConfig.js";
|
|
3
|
+
import "../interfaces/index.js";
|
|
4
|
+
import constants_default from "../constants.js";
|
|
5
|
+
import Communicator from "./communicator.js";
|
|
6
|
+
import { EventCommunicator } from "./eventCommunicator.js";
|
|
7
|
+
import { ErrorType, ExternalCommunicatorError } from "@diia-inhouse/errors";
|
|
8
|
+
import { HttpStatusCode } from "@diia-inhouse/types";
|
|
9
|
+
//#region src/services/externalEventBus.ts
|
|
10
|
+
var ExternalEventBus = class ExternalEventBus extends Communicator {
|
|
11
|
+
envService;
|
|
12
|
+
eventCommunicator;
|
|
13
|
+
publishEventsSet;
|
|
14
|
+
subscribeEventsSet;
|
|
15
|
+
exchangePrefixName = "TopicExternal";
|
|
16
|
+
eventQueueMap = /* @__PURE__ */ new Map();
|
|
17
|
+
constructor(logger, systemServiceName, envService, queueProvider, externalEventListenerList, eventMessageHandler, hostName) {
|
|
18
|
+
super(logger, queueProvider, hostName, systemServiceName);
|
|
19
|
+
this.envService = envService;
|
|
20
|
+
const { rabbit: { custom }, service: { publish = [], subscribe = [] } } = this.queueProvider.getConfig();
|
|
21
|
+
if (custom?.responseRoutingKeyPrefix && !this.envService.isLocal() && !this.envService.isTest()) throw new Error("Response routing key could be used only on local env");
|
|
22
|
+
this.publishEventsSet = new Set(publish);
|
|
23
|
+
this.subscribeEventsSet = new Set(subscribe);
|
|
24
|
+
this.eventQueueMap = this.buildEventQueueMap();
|
|
25
|
+
this.eventCommunicator = new EventCommunicator(logger, queueProvider, eventMessageHandler, externalEventListenerList);
|
|
26
|
+
}
|
|
27
|
+
static BuildRequestRoutingKey(eventName) {
|
|
28
|
+
return `queue.${constants_default.PROJECT_NAME}.${eventName}.req`;
|
|
29
|
+
}
|
|
30
|
+
static BuildResponseRoutingKey(eventName, portalEvents = []) {
|
|
31
|
+
return `${ExternalEventBus.prepareQueuePrefix(eventName, portalEvents)}.${eventName}.res`;
|
|
32
|
+
}
|
|
33
|
+
static prepareQueuePrefix(event, portalEvents = []) {
|
|
34
|
+
if (portalEvents.includes(event)) return `queue.${constants_default.PORTAL_NAME}`;
|
|
35
|
+
return `queue.${constants_default.PROJECT_NAME}`;
|
|
36
|
+
}
|
|
37
|
+
async publish(eventName, payload, options) {
|
|
38
|
+
const message = this.getPublishMessage(eventName, payload, options);
|
|
39
|
+
const routingKey = this.getPublishRoutingKey(eventName);
|
|
40
|
+
return await this.publishEventToExchange(eventName, message, {
|
|
41
|
+
...options,
|
|
42
|
+
routingKey
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async publishDirect(eventName, payload, options = {}) {
|
|
46
|
+
const { exchangeName: customExchangeName } = options;
|
|
47
|
+
const exchangeName = customExchangeName ?? this.eventNameToExchangeNameMap.get(eventName);
|
|
48
|
+
if (!exchangeName) throw new ExternalCommunicatorError(`Exchange name for event ${eventName} is not defined`, HttpStatusCode.INTERNAL_SERVER_ERROR, {
|
|
49
|
+
event: eventName,
|
|
50
|
+
customExchangeName
|
|
51
|
+
}, ErrorType.Unoperated);
|
|
52
|
+
const routingKey = ExternalEventBus.BuildRequestRoutingKey(eventName);
|
|
53
|
+
const { data } = this.getPublishMessage(eventName, payload, options);
|
|
54
|
+
return await this.queueProvider.publishExternalDirect(data, exchangeName, routingKey, options);
|
|
55
|
+
}
|
|
56
|
+
getUnicastListeners() {
|
|
57
|
+
return this.eventCommunicator.getUnicastListeners();
|
|
58
|
+
}
|
|
59
|
+
getExchangeNameWithSuffix(topic) {
|
|
60
|
+
return `${this.exchangePrefixName}${topic}`;
|
|
61
|
+
}
|
|
62
|
+
getProducerExchangesOptions() {
|
|
63
|
+
const [exchangesOptions] = this.defineQueuesAndExchangesOptionsBasedOnGlobalConfig();
|
|
64
|
+
return exchangesOptions;
|
|
65
|
+
}
|
|
66
|
+
getMulticastListeners() {
|
|
67
|
+
const [exchangesOptions, queuesOptions] = this.defineQueuesAndExchangesOptionsBasedOnGlobalConfig();
|
|
68
|
+
return this.eventCommunicator.getMulticastListeners(queuesOptions, exchangesOptions, this.eventQueueMap);
|
|
69
|
+
}
|
|
70
|
+
getPublishMessage(eventName, message, options) {
|
|
71
|
+
const { rabbit: { custom: { responseRoutingKeyPrefix } = {} } } = this.queueProvider.getConfig();
|
|
72
|
+
const responseRoutingKey = this.buildResponseQueueName(eventName, responseRoutingKeyPrefix);
|
|
73
|
+
const partialMeta = {
|
|
74
|
+
ignoreCache: options?.ignoreCache,
|
|
75
|
+
registryApiVersion: options?.registryApiVersion,
|
|
76
|
+
...this.publishEventsSet.has(eventName) ? { responseRoutingKey } : {}
|
|
77
|
+
};
|
|
78
|
+
return new Message(this.getPublishQueueMessageData(eventName, message, partialMeta));
|
|
79
|
+
}
|
|
80
|
+
getPublishRoutingKey(eventName) {
|
|
81
|
+
if (this.publishEventsSet.has(eventName)) return ExternalEventBus.BuildRequestRoutingKey(eventName);
|
|
82
|
+
else if (this.subscribeEventsSet.has(eventName)) {
|
|
83
|
+
const { portalEvents } = this.queueProvider.getConfig();
|
|
84
|
+
return ExternalEventBus.BuildResponseRoutingKey(eventName, portalEvents);
|
|
85
|
+
}
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
defineQueuesAndExchangesOptionsBasedOnGlobalConfig() {
|
|
89
|
+
const { rabbit: { listenerOptions, declareOptions: { assertQueues, assertExchanges, queuesOptions: overriddenQueuesOptions = {} } = {} } } = this.queueProvider.getConfig();
|
|
90
|
+
const queuesOptions = [];
|
|
91
|
+
const exchangesMap = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const [eventName, queueName] of this.eventQueueMap.entries()) {
|
|
93
|
+
const exchangeName = this.eventNameToExchangeNameMap.get(eventName);
|
|
94
|
+
if (!exchangeName) {
|
|
95
|
+
this.logger.error(`Can't find external topic name for event [${eventName}]`);
|
|
96
|
+
return [[], []];
|
|
97
|
+
}
|
|
98
|
+
const queueOptions = {
|
|
99
|
+
name: queueName,
|
|
100
|
+
declare: assertQueues,
|
|
101
|
+
type: QueueTypes.Quorum,
|
|
102
|
+
options: listenerOptions?.queueOptions,
|
|
103
|
+
bindTo: [{
|
|
104
|
+
bind: assertQueues,
|
|
105
|
+
routingKey: queueName,
|
|
106
|
+
exchangeName
|
|
107
|
+
}],
|
|
108
|
+
consumerOptions: this.optionsBuilder.defineConsumerOptionsBasedOnGlobalConfig(),
|
|
109
|
+
...overriddenQueuesOptions
|
|
110
|
+
};
|
|
111
|
+
queuesOptions.push(queueOptions);
|
|
112
|
+
const exchangeOptions = {
|
|
113
|
+
name: exchangeName,
|
|
114
|
+
type: "topic",
|
|
115
|
+
declare: assertExchanges
|
|
116
|
+
};
|
|
117
|
+
exchangesMap.set(exchangeName, exchangeOptions);
|
|
118
|
+
}
|
|
119
|
+
return [[...exchangesMap.values()], queuesOptions];
|
|
120
|
+
}
|
|
121
|
+
buildEventQueueMap() {
|
|
122
|
+
const eventQueueMap = /* @__PURE__ */ new Map();
|
|
123
|
+
const { service: { publish = [], subscribe = [] }, rabbit: { custom: { responseRoutingKeyPrefix } = {} } } = this.queueProvider.getConfig();
|
|
124
|
+
if (publish.length === 0 && subscribe.length === 0) {
|
|
125
|
+
this.logger.info("No one external events to listen");
|
|
126
|
+
return eventQueueMap;
|
|
127
|
+
}
|
|
128
|
+
for (const responseEvent of publish) eventQueueMap.set(responseEvent, this.buildResponseQueueName(responseEvent, responseRoutingKeyPrefix));
|
|
129
|
+
for (const requestEvent of subscribe) eventQueueMap.set(requestEvent, this.buildRequestQueueName(requestEvent, responseRoutingKeyPrefix));
|
|
130
|
+
return eventQueueMap;
|
|
131
|
+
}
|
|
132
|
+
buildResponseQueueName(eventName, prefix) {
|
|
133
|
+
const result = `queue.${constants_default.PROJECT_NAME}.${eventName}.res`;
|
|
134
|
+
if (prefix) return `${prefix}.${result}`;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
buildRequestQueueName(eventName, prefix) {
|
|
138
|
+
const { portalEvents } = this.queueProvider.getConfig();
|
|
139
|
+
const result = `${ExternalEventBus.prepareQueuePrefix(eventName, portalEvents)}.${eventName}.req`;
|
|
140
|
+
if (prefix) return `${prefix}.${result}`;
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
4
143
|
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const errors_1 = require("@diia-inhouse/errors");
|
|
8
|
-
const types_1 = require("@diia-inhouse/types");
|
|
9
|
-
const constants_1 = __importDefault(require("../constants"));
|
|
10
|
-
const interfaces_1 = require("../interfaces");
|
|
11
|
-
const communicator_1 = __importDefault(require("./communicator"));
|
|
12
|
-
const eventCommunicator_1 = require("./eventCommunicator");
|
|
13
|
-
class ExternalEventBus extends communicator_1.default {
|
|
14
|
-
envService;
|
|
15
|
-
eventCommunicator;
|
|
16
|
-
publishEventsSet;
|
|
17
|
-
subscribeEventsSet;
|
|
18
|
-
exchangePrefixName = 'TopicExternal';
|
|
19
|
-
eventQueueMap = new Map();
|
|
20
|
-
constructor(logger, systemServiceName, envService, queueProvider, externalEventListenerList, eventMessageHandler, hostName) {
|
|
21
|
-
super(logger, queueProvider, hostName, systemServiceName);
|
|
22
|
-
this.envService = envService;
|
|
23
|
-
const { rabbit: { custom }, service: { publish = [], subscribe = [] }, } = this.queueProvider.getConfig();
|
|
24
|
-
if (custom?.responseRoutingKeyPrefix && !this.envService.isLocal() && !this.envService.isTest()) {
|
|
25
|
-
throw new Error('Response routing key could be used only on local env');
|
|
26
|
-
}
|
|
27
|
-
this.publishEventsSet = new Set(publish);
|
|
28
|
-
this.subscribeEventsSet = new Set(subscribe);
|
|
29
|
-
this.eventQueueMap = this.buildEventQueueMap();
|
|
30
|
-
this.eventCommunicator = new eventCommunicator_1.EventCommunicator(logger, queueProvider, eventMessageHandler, externalEventListenerList);
|
|
31
|
-
}
|
|
32
|
-
static BuildRequestRoutingKey(eventName) {
|
|
33
|
-
return `queue.${constants_1.default.PROJECT_NAME}.${eventName}.req`;
|
|
34
|
-
}
|
|
35
|
-
static BuildResponseRoutingKey(eventName, portalEvents = []) {
|
|
36
|
-
const queuePrefix = ExternalEventBus.prepareQueuePrefix(eventName, portalEvents);
|
|
37
|
-
return `${queuePrefix}.${eventName}.res`;
|
|
38
|
-
}
|
|
39
|
-
static prepareQueuePrefix(event, portalEvents = []) {
|
|
40
|
-
if (portalEvents.includes(event)) {
|
|
41
|
-
return `queue.${constants_1.default.PORTAL_NAME}`;
|
|
42
|
-
}
|
|
43
|
-
return `queue.${constants_1.default.PROJECT_NAME}`;
|
|
44
|
-
}
|
|
45
|
-
async publish(eventName, payload, options) {
|
|
46
|
-
const message = this.getPublishMessage(eventName, payload, options);
|
|
47
|
-
const routingKey = this.getPublishRoutingKey(eventName);
|
|
48
|
-
return await this.publishEventToExchange(eventName, message, { ...options, routingKey });
|
|
49
|
-
}
|
|
50
|
-
async publishDirect(eventName, payload, options = {}) {
|
|
51
|
-
const { exchangeName: customExchangeName } = options;
|
|
52
|
-
const exchangeName = customExchangeName ?? this.eventNameToExchangeNameMap.get(eventName);
|
|
53
|
-
if (!exchangeName) {
|
|
54
|
-
throw new errors_1.ExternalCommunicatorError(`Exchange name for event ${eventName} is not defined`, types_1.HttpStatusCode.INTERNAL_SERVER_ERROR, { event: eventName, customExchangeName }, errors_1.ErrorType.Unoperated);
|
|
55
|
-
}
|
|
56
|
-
const routingKey = ExternalEventBus.BuildRequestRoutingKey(eventName);
|
|
57
|
-
const { data } = this.getPublishMessage(eventName, payload, options);
|
|
58
|
-
return await this.queueProvider.publishExternalDirect(data, exchangeName, routingKey, options);
|
|
59
|
-
}
|
|
60
|
-
getUnicastListeners() {
|
|
61
|
-
return this.eventCommunicator.getUnicastListeners();
|
|
62
|
-
}
|
|
63
|
-
getExchangeNameWithSuffix(topic) {
|
|
64
|
-
return `${this.exchangePrefixName}${topic}`;
|
|
65
|
-
}
|
|
66
|
-
getProducerExchangesOptions() {
|
|
67
|
-
const [exchangesOptions] = this.defineQueuesAndExchangesOptionsBasedOnGlobalConfig();
|
|
68
|
-
return exchangesOptions;
|
|
69
|
-
}
|
|
70
|
-
getMulticastListeners() {
|
|
71
|
-
const [exchangesOptions, queuesOptions] = this.defineQueuesAndExchangesOptionsBasedOnGlobalConfig();
|
|
72
|
-
return this.eventCommunicator.getMulticastListeners(queuesOptions, exchangesOptions, this.eventQueueMap);
|
|
73
|
-
}
|
|
74
|
-
getPublishMessage(eventName, message, options) {
|
|
75
|
-
const { rabbit: { custom: { responseRoutingKeyPrefix } = {} }, } = this.queueProvider.getConfig();
|
|
76
|
-
const responseRoutingKey = this.buildResponseQueueName(eventName, responseRoutingKeyPrefix);
|
|
77
|
-
const partialMeta = {
|
|
78
|
-
ignoreCache: options?.ignoreCache,
|
|
79
|
-
registryApiVersion: options?.registryApiVersion,
|
|
80
|
-
...(this.publishEventsSet.has(eventName) ? { responseRoutingKey } : {}),
|
|
81
|
-
};
|
|
82
|
-
const data = this.getPublishQueueMessageData(eventName, message, partialMeta);
|
|
83
|
-
return new interfaces_1.Message(data);
|
|
84
|
-
}
|
|
85
|
-
getPublishRoutingKey(eventName) {
|
|
86
|
-
if (this.publishEventsSet.has(eventName)) {
|
|
87
|
-
return ExternalEventBus.BuildRequestRoutingKey(eventName);
|
|
88
|
-
}
|
|
89
|
-
else if (this.subscribeEventsSet.has(eventName)) {
|
|
90
|
-
const { portalEvents } = this.queueProvider.getConfig();
|
|
91
|
-
return ExternalEventBus.BuildResponseRoutingKey(eventName, portalEvents);
|
|
92
|
-
}
|
|
93
|
-
return '';
|
|
94
|
-
}
|
|
95
|
-
defineQueuesAndExchangesOptionsBasedOnGlobalConfig() {
|
|
96
|
-
const { rabbit: { listenerOptions, declareOptions: { assertQueues, assertExchanges, queuesOptions: overriddenQueuesOptions = {} } = {}, }, } = this.queueProvider.getConfig();
|
|
97
|
-
const queuesOptions = [];
|
|
98
|
-
const exchangesMap = new Map();
|
|
99
|
-
for (const [eventName, queueName] of this.eventQueueMap.entries()) {
|
|
100
|
-
const exchangeName = this.eventNameToExchangeNameMap.get(eventName);
|
|
101
|
-
if (!exchangeName) {
|
|
102
|
-
this.logger.error(`Can't find external topic name for event [${eventName}]`);
|
|
103
|
-
return [[], []];
|
|
104
|
-
}
|
|
105
|
-
const queueOptions = {
|
|
106
|
-
name: queueName,
|
|
107
|
-
declare: assertQueues,
|
|
108
|
-
type: interfaces_1.QueueTypes.Quorum,
|
|
109
|
-
options: listenerOptions?.queueOptions,
|
|
110
|
-
bindTo: [
|
|
111
|
-
{
|
|
112
|
-
bind: assertQueues,
|
|
113
|
-
routingKey: queueName,
|
|
114
|
-
exchangeName: exchangeName,
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
consumerOptions: this.optionsBuilder.defineConsumerOptionsBasedOnGlobalConfig(),
|
|
118
|
-
...overriddenQueuesOptions,
|
|
119
|
-
};
|
|
120
|
-
queuesOptions.push(queueOptions);
|
|
121
|
-
const exchangeOptions = {
|
|
122
|
-
name: exchangeName,
|
|
123
|
-
type: interfaces_1.ExchangeType.Topic,
|
|
124
|
-
declare: assertExchanges,
|
|
125
|
-
};
|
|
126
|
-
exchangesMap.set(exchangeName, exchangeOptions);
|
|
127
|
-
}
|
|
128
|
-
const exchangesOptions = [...exchangesMap.values()];
|
|
129
|
-
return [exchangesOptions, queuesOptions];
|
|
130
|
-
}
|
|
131
|
-
buildEventQueueMap() {
|
|
132
|
-
const eventQueueMap = new Map();
|
|
133
|
-
const { service: { publish = [], subscribe = [] }, rabbit: { custom: { responseRoutingKeyPrefix } = {} }, } = this.queueProvider.getConfig();
|
|
134
|
-
if (publish.length === 0 && subscribe.length === 0) {
|
|
135
|
-
this.logger.info('No one external events to listen');
|
|
136
|
-
return eventQueueMap;
|
|
137
|
-
}
|
|
138
|
-
for (const responseEvent of publish) {
|
|
139
|
-
eventQueueMap.set(responseEvent, this.buildResponseQueueName(responseEvent, responseRoutingKeyPrefix));
|
|
140
|
-
}
|
|
141
|
-
for (const requestEvent of subscribe) {
|
|
142
|
-
eventQueueMap.set(requestEvent, this.buildRequestQueueName(requestEvent, responseRoutingKeyPrefix));
|
|
143
|
-
}
|
|
144
|
-
return eventQueueMap;
|
|
145
|
-
}
|
|
146
|
-
buildResponseQueueName(eventName, prefix) {
|
|
147
|
-
const result = `queue.${constants_1.default.PROJECT_NAME}.${eventName}.res`;
|
|
148
|
-
if (prefix) {
|
|
149
|
-
return `${prefix}.${result}`;
|
|
150
|
-
}
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
buildRequestQueueName(eventName, prefix) {
|
|
154
|
-
const { portalEvents } = this.queueProvider.getConfig();
|
|
155
|
-
const result = `${ExternalEventBus.prepareQueuePrefix(eventName, portalEvents)}.${eventName}.req`;
|
|
156
|
-
if (prefix) {
|
|
157
|
-
return `${prefix}.${result}`;
|
|
158
|
-
}
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
exports.ExternalEventBus = ExternalEventBus;
|
|
163
|
-
//# sourceMappingURL=externalEventBus.js.map
|
|
144
|
+
//#endregion
|
|
145
|
+
export { ExternalEventBus };
|