@zetra/citrineos-util 1.8.3-fork.1
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/authorization/ApiAuthPlugin.d.ts +52 -0
- package/dist/authorization/ApiAuthPlugin.js +122 -0
- package/dist/authorization/ApiAuthPlugin.js.map +1 -0
- package/dist/authorization/OidcTokenProvider.d.ts +15 -0
- package/dist/authorization/OidcTokenProvider.js +47 -0
- package/dist/authorization/OidcTokenProvider.js.map +1 -0
- package/dist/authorization/index.d.ts +4 -0
- package/dist/authorization/index.js +8 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/authorization/provider/LocalByPassAuthProvider.d.ts +34 -0
- package/dist/authorization/provider/LocalByPassAuthProvider.js +62 -0
- package/dist/authorization/provider/LocalByPassAuthProvider.js.map +1 -0
- package/dist/authorization/provider/OIDCAuthProvider.d.ts +62 -0
- package/dist/authorization/provider/OIDCAuthProvider.js +173 -0
- package/dist/authorization/provider/OIDCAuthProvider.js.map +1 -0
- package/dist/authorization/rbac/RbacRulesLoader.d.ts +32 -0
- package/dist/authorization/rbac/RbacRulesLoader.js +105 -0
- package/dist/authorization/rbac/RbacRulesLoader.js.map +1 -0
- package/dist/authorization/rbac/UrlMatcher.d.ts +14 -0
- package/dist/authorization/rbac/UrlMatcher.js +44 -0
- package/dist/authorization/rbac/UrlMatcher.js.map +1 -0
- package/dist/authorizer/RealTimeAuthorizer.d.ts +28 -0
- package/dist/authorizer/RealTimeAuthorizer.js +152 -0
- package/dist/authorizer/RealTimeAuthorizer.js.map +1 -0
- package/dist/authorizer/index.d.ts +1 -0
- package/dist/authorizer/index.js +5 -0
- package/dist/authorizer/index.js.map +1 -0
- package/dist/cache/memory.d.ts +19 -0
- package/dist/cache/memory.js +147 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/redis.d.ts +16 -0
- package/dist/cache/redis.js +120 -0
- package/dist/cache/redis.js.map +1 -0
- package/dist/certificate/CertificateAuthority.d.ts +38 -0
- package/dist/certificate/CertificateAuthority.js +233 -0
- package/dist/certificate/CertificateAuthority.js.map +1 -0
- package/dist/certificate/CertificateUtil.d.ts +60 -0
- package/dist/certificate/CertificateUtil.js +317 -0
- package/dist/certificate/CertificateUtil.js.map +1 -0
- package/dist/certificate/client/acme.d.ts +37 -0
- package/dist/certificate/client/acme.js +138 -0
- package/dist/certificate/client/acme.js.map +1 -0
- package/dist/certificate/client/hubject.d.ts +41 -0
- package/dist/certificate/client/hubject.js +221 -0
- package/dist/certificate/client/hubject.js.map +1 -0
- package/dist/certificate/client/interface.d.ts +12 -0
- package/dist/certificate/client/interface.js +5 -0
- package/dist/certificate/client/interface.js.map +1 -0
- package/dist/certificate/index.d.ts +2 -0
- package/dist/certificate/index.js +6 -0
- package/dist/certificate/index.js.map +1 -0
- package/dist/files/ftpServer.d.ts +4 -0
- package/dist/files/ftpServer.js +9 -0
- package/dist/files/ftpServer.js.map +1 -0
- package/dist/files/gcpCloudStorage.d.ts +39 -0
- package/dist/files/gcpCloudStorage.js +130 -0
- package/dist/files/gcpCloudStorage.js.map +1 -0
- package/dist/files/localStorage.d.ts +14 -0
- package/dist/files/localStorage.js +57 -0
- package/dist/files/localStorage.js.map +1 -0
- package/dist/files/s3Storage.d.ts +17 -0
- package/dist/files/s3Storage.js +118 -0
- package/dist/files/s3Storage.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/networkconnection/WebsocketNetworkConnection.d.ts +135 -0
- package/dist/networkconnection/WebsocketNetworkConnection.js +474 -0
- package/dist/networkconnection/WebsocketNetworkConnection.js.map +1 -0
- package/dist/networkconnection/authenticator/Authenticator.d.ts +20 -0
- package/dist/networkconnection/authenticator/Authenticator.js +39 -0
- package/dist/networkconnection/authenticator/Authenticator.js.map +1 -0
- package/dist/networkconnection/authenticator/AuthenticatorFilter.d.ts +11 -0
- package/dist/networkconnection/authenticator/AuthenticatorFilter.js +30 -0
- package/dist/networkconnection/authenticator/AuthenticatorFilter.js.map +1 -0
- package/dist/networkconnection/authenticator/BasicAuthenticationFilter.d.ts +17 -0
- package/dist/networkconnection/authenticator/BasicAuthenticationFilter.js +51 -0
- package/dist/networkconnection/authenticator/BasicAuthenticationFilter.js.map +1 -0
- package/dist/networkconnection/authenticator/ConnectedStationFilter.d.ts +14 -0
- package/dist/networkconnection/authenticator/ConnectedStationFilter.js +25 -0
- package/dist/networkconnection/authenticator/ConnectedStationFilter.js.map +1 -0
- package/dist/networkconnection/authenticator/NetworkProfileFilter.d.ts +16 -0
- package/dist/networkconnection/authenticator/NetworkProfileFilter.js +84 -0
- package/dist/networkconnection/authenticator/NetworkProfileFilter.js.map +1 -0
- package/dist/networkconnection/authenticator/UnknownStationFilter.d.ts +16 -0
- package/dist/networkconnection/authenticator/UnknownStationFilter.js +25 -0
- package/dist/networkconnection/authenticator/UnknownStationFilter.js.map +1 -0
- package/dist/networkconnection/authenticator/errors/AuthenticationError.d.ts +6 -0
- package/dist/networkconnection/authenticator/errors/AuthenticationError.js +25 -0
- package/dist/networkconnection/authenticator/errors/AuthenticationError.js.map +1 -0
- package/dist/networkconnection/authenticator/errors/IUpgradeError.d.ts +9 -0
- package/dist/networkconnection/authenticator/errors/IUpgradeError.js +5 -0
- package/dist/networkconnection/authenticator/errors/IUpgradeError.js.map +1 -0
- package/dist/networkconnection/authenticator/errors/UnknownError.d.ts +6 -0
- package/dist/networkconnection/authenticator/errors/UnknownError.js +24 -0
- package/dist/networkconnection/authenticator/errors/UnknownError.js.map +1 -0
- package/dist/networkconnection/index.d.ts +5 -0
- package/dist/networkconnection/index.js +9 -0
- package/dist/networkconnection/index.js.map +1 -0
- package/dist/queue/index.d.ts +4 -0
- package/dist/queue/index.js +8 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/kafka/receiver.d.ts +35 -0
- package/dist/queue/kafka/receiver.js +179 -0
- package/dist/queue/kafka/receiver.js.map +1 -0
- package/dist/queue/kafka/sender.d.ts +53 -0
- package/dist/queue/kafka/sender.js +189 -0
- package/dist/queue/kafka/sender.js.map +1 -0
- package/dist/queue/rabbit-mq/receiver.d.ts +89 -0
- package/dist/queue/rabbit-mq/receiver.js +472 -0
- package/dist/queue/rabbit-mq/receiver.js.map +1 -0
- package/dist/queue/rabbit-mq/sender.d.ts +90 -0
- package/dist/queue/rabbit-mq/sender.js +251 -0
- package/dist/queue/rabbit-mq/sender.js.map +1 -0
- package/dist/security/SignedMeterValuesUtil.d.ts +44 -0
- package/dist/security/SignedMeterValuesUtil.js +135 -0
- package/dist/security/SignedMeterValuesUtil.js.map +1 -0
- package/dist/security/authentication.d.ts +2 -0
- package/dist/security/authentication.js +26 -0
- package/dist/security/authentication.js.map +1 -0
- package/dist/util/RequestOperations.d.ts +14 -0
- package/dist/util/RequestOperations.js +25 -0
- package/dist/util/RequestOperations.js.map +1 -0
- package/dist/util/StringOperations.d.ts +1 -0
- package/dist/util/StringOperations.js +8 -0
- package/dist/util/StringOperations.js.map +1 -0
- package/dist/util/emaidCheckDigitCalculator.d.ts +15 -0
- package/dist/util/emaidCheckDigitCalculator.js +179 -0
- package/dist/util/emaidCheckDigitCalculator.js.map +1 -0
- package/dist/util/idGenerator.d.ts +7 -0
- package/dist/util/idGenerator.js +10 -0
- package/dist/util/idGenerator.js.map +1 -0
- package/dist/util/parser.d.ts +31 -0
- package/dist/util/parser.js +60 -0
- package/dist/util/parser.js.map +1 -0
- package/dist/util/swagger.d.ts +5 -0
- package/dist/util/swagger.js +154 -0
- package/dist/util/swagger.js.map +1 -0
- package/dist/util/validator.d.ts +110 -0
- package/dist/util/validator.js +534 -0
- package/dist/util/validator.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { IMessage, IMessageConfirmation, IMessageSender, OcppRequest, OcppResponse, SystemConfig } from '@citrineos/base';
|
|
2
|
+
import { AbstractMessageSender, CircuitBreaker, MessageState, OcppError } from '@citrineos/base';
|
|
3
|
+
import type { ILogObj } from 'tslog';
|
|
4
|
+
import { Logger } from 'tslog';
|
|
5
|
+
/**
|
|
6
|
+
* Implementation of a {@link IMessageSender} using Kafka as the underlying transport.
|
|
7
|
+
*/
|
|
8
|
+
export declare class KafkaSender extends AbstractMessageSender implements IMessageSender {
|
|
9
|
+
/**
|
|
10
|
+
* Fields
|
|
11
|
+
*/
|
|
12
|
+
private _client;
|
|
13
|
+
private _topicName;
|
|
14
|
+
private _producers;
|
|
15
|
+
private _circuitBreaker;
|
|
16
|
+
private _reconnectInterval?;
|
|
17
|
+
/**
|
|
18
|
+
* Constructor
|
|
19
|
+
*
|
|
20
|
+
* @param topicPrefix Custom topic prefix, defaults to "ocpp"
|
|
21
|
+
*/
|
|
22
|
+
constructor(config: SystemConfig, logger?: Logger<ILogObj>, circuitBreaker?: CircuitBreaker);
|
|
23
|
+
private _initAdmin;
|
|
24
|
+
/**
|
|
25
|
+
* Convenience method to send a request message.
|
|
26
|
+
*
|
|
27
|
+
* @param message The {@link IMessage} to send
|
|
28
|
+
* @param payload The payload to send
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
sendRequest(message: IMessage<OcppRequest>, payload?: OcppRequest): Promise<IMessageConfirmation>;
|
|
32
|
+
/**
|
|
33
|
+
* Convenience method to send a confirmation message.
|
|
34
|
+
* @param message The {@link IMessage} to send
|
|
35
|
+
* @param payload The payload to send
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
sendResponse(message: IMessage<OcppResponse | OcppError>, payload?: OcppResponse | OcppError): Promise<IMessageConfirmation>;
|
|
39
|
+
/**
|
|
40
|
+
* Publishes the given message to kafka.
|
|
41
|
+
*
|
|
42
|
+
* @param message The {@link IMessage} to publish
|
|
43
|
+
* @param payload The payload to within the {@link IMessage}
|
|
44
|
+
* @param state The {@link MessageState} of the {@link IMessage}
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
send(message: IMessage<OcppRequest | OcppResponse | OcppError>, payload?: OcppRequest | OcppResponse | OcppError, state?: MessageState): Promise<IMessageConfirmation>;
|
|
48
|
+
/**
|
|
49
|
+
* Interface implementation
|
|
50
|
+
*/
|
|
51
|
+
shutdown(): Promise<void>;
|
|
52
|
+
private _onCircuitBreakerStateChange;
|
|
53
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { AbstractMessageSender, CircuitBreaker, MessageState, OcppError } from '@citrineos/base';
|
|
2
|
+
import { Kafka } from 'kafkajs';
|
|
3
|
+
import { Logger } from 'tslog';
|
|
4
|
+
/**
|
|
5
|
+
* Implementation of a {@link IMessageSender} using Kafka as the underlying transport.
|
|
6
|
+
*/
|
|
7
|
+
export class KafkaSender extends AbstractMessageSender {
|
|
8
|
+
/**
|
|
9
|
+
* Fields
|
|
10
|
+
*/
|
|
11
|
+
_client;
|
|
12
|
+
_topicName;
|
|
13
|
+
_producers;
|
|
14
|
+
_circuitBreaker;
|
|
15
|
+
_reconnectInterval;
|
|
16
|
+
/**
|
|
17
|
+
* Constructor
|
|
18
|
+
*
|
|
19
|
+
* @param topicPrefix Custom topic prefix, defaults to "ocpp"
|
|
20
|
+
*/
|
|
21
|
+
constructor(config, logger, circuitBreaker) {
|
|
22
|
+
super(config, logger);
|
|
23
|
+
this._circuitBreaker = circuitBreaker ?? new CircuitBreaker();
|
|
24
|
+
this._circuitBreaker.onStateChange(this._onCircuitBreakerStateChange.bind(this));
|
|
25
|
+
this._client = new Kafka({
|
|
26
|
+
brokers: config.util.messageBroker.kafka?.brokers || [],
|
|
27
|
+
ssl: true,
|
|
28
|
+
sasl: {
|
|
29
|
+
mechanism: 'plain',
|
|
30
|
+
username: config.util.messageBroker.kafka?.sasl.username || '',
|
|
31
|
+
password: config.util.messageBroker.kafka?.sasl.password || '',
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
this._producers = new Array();
|
|
35
|
+
this._topicName = `${this._config.util.messageBroker.kafka?.topicPrefix}-${this._config.util.messageBroker.kafka?.topicName}`;
|
|
36
|
+
this._initAdmin();
|
|
37
|
+
}
|
|
38
|
+
_initAdmin() {
|
|
39
|
+
const admin = this._client.admin();
|
|
40
|
+
admin
|
|
41
|
+
.connect()
|
|
42
|
+
.then(() => admin.listTopics())
|
|
43
|
+
.then((topics) => {
|
|
44
|
+
if (!topics || topics.filter((topic) => topic === this._topicName).length === 0) {
|
|
45
|
+
this._client
|
|
46
|
+
.admin()
|
|
47
|
+
.createTopics({ topics: [{ topic: this._topicName }] })
|
|
48
|
+
.then(() => {
|
|
49
|
+
this._logger.debug(`Topic ${this._topicName} created.`);
|
|
50
|
+
this._circuitBreaker.triggerSuccess();
|
|
51
|
+
})
|
|
52
|
+
.catch((error) => {
|
|
53
|
+
this._logger.error('Failed to create topic', error);
|
|
54
|
+
this._circuitBreaker.triggerFailure(error?.message);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
this._circuitBreaker.triggerSuccess();
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.then(() => admin.disconnect())
|
|
62
|
+
.catch((error) => {
|
|
63
|
+
this._logger.error('Failed to connect to Kafka', error);
|
|
64
|
+
this._circuitBreaker.triggerFailure(error?.message);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Convenience method to send a request message.
|
|
69
|
+
*
|
|
70
|
+
* @param message The {@link IMessage} to send
|
|
71
|
+
* @param payload The payload to send
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
sendRequest(message, payload) {
|
|
75
|
+
return this.send(message, payload, MessageState.Request);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Convenience method to send a confirmation message.
|
|
79
|
+
* @param message The {@link IMessage} to send
|
|
80
|
+
* @param payload The payload to send
|
|
81
|
+
* @returns
|
|
82
|
+
*/
|
|
83
|
+
sendResponse(message, payload) {
|
|
84
|
+
return this.send(message, payload, MessageState.Response);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Publishes the given message to kafka.
|
|
88
|
+
*
|
|
89
|
+
* @param message The {@link IMessage} to publish
|
|
90
|
+
* @param payload The payload to within the {@link IMessage}
|
|
91
|
+
* @param state The {@link MessageState} of the {@link IMessage}
|
|
92
|
+
* @returns
|
|
93
|
+
*/
|
|
94
|
+
send(message, payload, state) {
|
|
95
|
+
if (this._circuitBreaker.state === 'CLOSED') {
|
|
96
|
+
return Promise.resolve({
|
|
97
|
+
success: false,
|
|
98
|
+
payload: 'Circuit breaker is CLOSED. Cannot send message.',
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (payload) {
|
|
102
|
+
message.payload = payload;
|
|
103
|
+
}
|
|
104
|
+
if (state) {
|
|
105
|
+
message.state = state;
|
|
106
|
+
}
|
|
107
|
+
if (!message.state) {
|
|
108
|
+
throw new Error('Message state must be set');
|
|
109
|
+
}
|
|
110
|
+
if (!message.payload) {
|
|
111
|
+
throw new Error('Message payload must be set');
|
|
112
|
+
}
|
|
113
|
+
this._logger.debug(`Publishing to ${this._topicName}:`, message);
|
|
114
|
+
const producer = this._client.producer();
|
|
115
|
+
return producer
|
|
116
|
+
.connect()
|
|
117
|
+
.then(() => producer.send({
|
|
118
|
+
topic: this._topicName,
|
|
119
|
+
messages: [
|
|
120
|
+
{
|
|
121
|
+
headers: {
|
|
122
|
+
origin: message.origin.toString(),
|
|
123
|
+
eventGroup: message.eventGroup.toString(),
|
|
124
|
+
action: message.action.toString(),
|
|
125
|
+
state: message.state.toString(),
|
|
126
|
+
...message.context,
|
|
127
|
+
tenantId: message.context.tenantId.toString(),
|
|
128
|
+
},
|
|
129
|
+
value: JSON.stringify(message),
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
}))
|
|
133
|
+
.then(() => this._producers.push(producer))
|
|
134
|
+
.then((result) => ({ success: true, result }))
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
this._circuitBreaker.triggerFailure(error?.message);
|
|
137
|
+
return { success: false, error };
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Interface implementation
|
|
142
|
+
*/
|
|
143
|
+
async shutdown() {
|
|
144
|
+
for (const producer of this._producers) {
|
|
145
|
+
await producer.disconnect();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
_onCircuitBreakerStateChange(state, reason) {
|
|
149
|
+
this._logger.info(`[CircuitBreaker] State changed to ${state}${reason ? `: ${reason}` : ''}`);
|
|
150
|
+
switch (state) {
|
|
151
|
+
case 'FAILING':
|
|
152
|
+
this._logger.warn('Circuit breaker is FAILING. Kafka sender will not send messages until recovery. Reason:', reason);
|
|
153
|
+
break;
|
|
154
|
+
case 'CLOSED': {
|
|
155
|
+
this._logger.error('Circuit breaker is CLOSED. Shutting down Kafka sender. Reason:', reason);
|
|
156
|
+
void this.shutdown();
|
|
157
|
+
if (this._reconnectInterval) {
|
|
158
|
+
clearInterval(this._reconnectInterval);
|
|
159
|
+
}
|
|
160
|
+
const delay = (this._config.maxReconnectDelay || 30) * 1000;
|
|
161
|
+
this._logger.warn(`Starting continuous reconnect attempts every ${delay / 1000} seconds while circuit breaker is CLOSED.`);
|
|
162
|
+
this._reconnectInterval = setInterval(() => {
|
|
163
|
+
this._logger.info('Attempting Kafka reconnect due to circuit breaker CLOSED...');
|
|
164
|
+
try {
|
|
165
|
+
this._initAdmin();
|
|
166
|
+
this._logger.info('Kafka reconnect attempt finished (success or already open).');
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
this._logger.error('Kafka reconnect attempt failed.', err);
|
|
170
|
+
}
|
|
171
|
+
}, delay);
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
case 'OPEN':
|
|
175
|
+
this._logger.info('Circuit breaker is OPEN. Will attempt to (re)initialize Kafka admin connection.');
|
|
176
|
+
if (this._reconnectInterval) {
|
|
177
|
+
this._logger.info('Clearing reconnect interval as circuit breaker is now OPEN.');
|
|
178
|
+
clearInterval(this._reconnectInterval);
|
|
179
|
+
this._reconnectInterval = undefined;
|
|
180
|
+
}
|
|
181
|
+
this._initAdmin();
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
this._logger.warn('Unknown circuit breaker state:', state);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=sender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sender.js","sourceRoot":"","sources":["../../../src/queue/kafka/sender.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { CallAction, ICache, IModule, SystemConfig } from '@citrineos/base';
|
|
2
|
+
import { AbstractMessageHandler, CircuitBreaker } from '@citrineos/base';
|
|
3
|
+
import * as amqplib from 'amqplib';
|
|
4
|
+
import type { ILogObj } from 'tslog';
|
|
5
|
+
import { Logger } from 'tslog';
|
|
6
|
+
/**
|
|
7
|
+
* Implementation of a {@link IMessageHandler} using RabbitMQ as the underlying transport.
|
|
8
|
+
*/
|
|
9
|
+
export declare class RabbitMqReceiver extends AbstractMessageHandler {
|
|
10
|
+
/**
|
|
11
|
+
* Constants
|
|
12
|
+
*/
|
|
13
|
+
private static readonly QUEUE_PREFIX;
|
|
14
|
+
private static readonly CACHE_PREFIX;
|
|
15
|
+
private static readonly METADATA_PREFIX;
|
|
16
|
+
private static readonly REGISTRY_KEY;
|
|
17
|
+
private static readonly RECONNECT_DELAY;
|
|
18
|
+
/**
|
|
19
|
+
* Fields
|
|
20
|
+
*/
|
|
21
|
+
protected _cache: ICache;
|
|
22
|
+
protected _connection?: amqplib.Connection;
|
|
23
|
+
protected _channel?: amqplib.Channel;
|
|
24
|
+
private _abortReconnectController?;
|
|
25
|
+
private _circuitBreaker;
|
|
26
|
+
private _reconnectInterval?;
|
|
27
|
+
constructor(config: SystemConfig, logger?: Logger<ILogObj>, module?: IModule, cache?: ICache, circuitBreaker?: CircuitBreaker);
|
|
28
|
+
initConnection(): Promise<any>;
|
|
29
|
+
/**
|
|
30
|
+
* Methods
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Binds queue to an exchange given identifier and optional actions and filter.
|
|
34
|
+
* Note: Due to the nature of AMQP 0-9-1 model, if you need to filter for the identifier, you **MUST** provide it in the filter object.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} identifier - The identifier of the channel to subscribe to.
|
|
37
|
+
* @param {CallAction[]} actions - Optional. An array of actions to filter the messages.
|
|
38
|
+
* @param {{ [k: string]: string; }} filter - Optional. An object representing the filter to apply on the messages.
|
|
39
|
+
* @return {Promise<boolean>} A promise that resolves to true if the subscription is successful, false otherwise.
|
|
40
|
+
*/
|
|
41
|
+
subscribe(identifier: string, actions?: CallAction[], filter?: {
|
|
42
|
+
[k: string]: string;
|
|
43
|
+
}): Promise<boolean>;
|
|
44
|
+
unsubscribe(identifier: string): Promise<boolean>;
|
|
45
|
+
shutdown(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Protected Methods
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* Connect to RabbitMQ with retry logic.
|
|
51
|
+
* This method will keep trying to connect until successful, unless aborted.
|
|
52
|
+
*
|
|
53
|
+
* @param {AbortSignal} [abortSignal] - Optional abort signal to stop retrying.
|
|
54
|
+
* @return {Promise<amqplib.Channel>} A promise that resolves to the AMQP channel.
|
|
55
|
+
*/
|
|
56
|
+
protected _connectWithRetry(abortSignal?: AbortSignal): Promise<amqplib.Channel>;
|
|
57
|
+
private _startReconnectInterval;
|
|
58
|
+
private _onCircuitBreakerStateChange;
|
|
59
|
+
/**
|
|
60
|
+
* Setup listeners for connection and channel events.
|
|
61
|
+
* This will handle disconnections and errors.
|
|
62
|
+
* Ensures listeners are not attached multiple times to the same connection.
|
|
63
|
+
*/
|
|
64
|
+
private _setupConnectionListeners;
|
|
65
|
+
/**
|
|
66
|
+
* Handle RabbitMQ disconnection.
|
|
67
|
+
* This method will attempt to reconnect to RabbitMQ when the connection is lost.
|
|
68
|
+
* Debounces concurrent reconnects.
|
|
69
|
+
*/
|
|
70
|
+
private _handleDisconnect;
|
|
71
|
+
/**
|
|
72
|
+
* Re-subscribe to all cached subscriptions after reconnection.
|
|
73
|
+
* This ensures queues are recreated with the same bindings.
|
|
74
|
+
* Uses cache to retrieve subscription metadata.
|
|
75
|
+
*/
|
|
76
|
+
private _resubscribeAll;
|
|
77
|
+
/**
|
|
78
|
+
* Internal method to re-subscribe without the channel check.
|
|
79
|
+
* Used during reconnection to recreate queues.
|
|
80
|
+
*/
|
|
81
|
+
private _resubscribe;
|
|
82
|
+
/**
|
|
83
|
+
* Underlying RabbitMQ message handler.
|
|
84
|
+
*
|
|
85
|
+
* @param message The AMQPMessage to process
|
|
86
|
+
* @param channel
|
|
87
|
+
*/
|
|
88
|
+
protected _onMessage(message: amqplib.ConsumeMessage | null, channel: amqplib.Channel): Promise<void>;
|
|
89
|
+
}
|