@onlineapps/mq-client-core 1.0.14 → 1.0.15
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/package.json
CHANGED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* queueConfig.js
|
|
5
|
+
*
|
|
6
|
+
* Central configuration for INFRASTRUCTURE queues only.
|
|
7
|
+
* Business queues ({service}.workflow, {service}.queue, {service}.dlq) are created
|
|
8
|
+
* by individual services via QueueManager.setupServiceQueues().
|
|
9
|
+
*
|
|
10
|
+
* This ensures consistent configuration for infrastructure queues across all services.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: This is part of mq-client-core (spodní vrstva) because it's used by both:
|
|
13
|
+
* - Infrastructure services (via mq-client-core)
|
|
14
|
+
* - Business services (via conn-infra-mq connector)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
/**
|
|
19
|
+
* Workflow infrastructure queue configurations
|
|
20
|
+
* These are shared infrastructure queues used by all services
|
|
21
|
+
*/
|
|
22
|
+
workflow: {
|
|
23
|
+
/**
|
|
24
|
+
* workflow.init - Entry point for all workflows
|
|
25
|
+
* All services listen as competing consumers
|
|
26
|
+
*/
|
|
27
|
+
init: {
|
|
28
|
+
durable: true,
|
|
29
|
+
arguments: {
|
|
30
|
+
'x-message-ttl': 300000, // 5 minutes TTL
|
|
31
|
+
'x-max-length': 10000 // Max 10k messages
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* workflow.completed - Completed workflows
|
|
37
|
+
*/
|
|
38
|
+
completed: {
|
|
39
|
+
durable: true,
|
|
40
|
+
arguments: {
|
|
41
|
+
'x-message-ttl': 300000, // 5 minutes TTL
|
|
42
|
+
'x-max-length': 10000
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* workflow.failed - Failed workflows
|
|
48
|
+
*/
|
|
49
|
+
failed: {
|
|
50
|
+
durable: true,
|
|
51
|
+
arguments: {
|
|
52
|
+
'x-message-ttl': 300000, // 5 minutes TTL
|
|
53
|
+
'x-max-length': 10000
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* workflow.dlq - Dead letter queue for workflows
|
|
59
|
+
*/
|
|
60
|
+
dlq: {
|
|
61
|
+
durable: true,
|
|
62
|
+
arguments: {
|
|
63
|
+
// No TTL for DLQ - messages should persist
|
|
64
|
+
'x-max-length': 50000 // Higher limit for DLQ
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Business queue templates
|
|
71
|
+
* These are templates for service-specific queues ({service}.workflow, {service}.queue, {service}.dlq)
|
|
72
|
+
* Used by QueueManager.setupServiceQueues() to ensure consistent configuration
|
|
73
|
+
*/
|
|
74
|
+
business: {
|
|
75
|
+
/**
|
|
76
|
+
* {service}.workflow - Service-specific workflow queue
|
|
77
|
+
* Used for routing workflow steps to specific services
|
|
78
|
+
*/
|
|
79
|
+
workflow: {
|
|
80
|
+
durable: true,
|
|
81
|
+
arguments: {
|
|
82
|
+
'x-message-ttl': 300000, // 5 minutes TTL
|
|
83
|
+
'x-max-length': 10000, // Max 10k messages
|
|
84
|
+
'x-dead-letter-exchange': 'dlx',
|
|
85
|
+
'x-dead-letter-routing-key': '{service}.dlq' // Placeholder, replaced with actual service name
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* {service}.queue - Service main processing queue
|
|
91
|
+
* Used for direct service-to-service communication
|
|
92
|
+
*/
|
|
93
|
+
queue: {
|
|
94
|
+
durable: true,
|
|
95
|
+
arguments: {
|
|
96
|
+
'x-message-ttl': 30000, // 30 seconds TTL
|
|
97
|
+
'x-max-length': 10000, // Max 10k messages
|
|
98
|
+
'x-dead-letter-exchange': 'dlx',
|
|
99
|
+
'x-dead-letter-routing-key': '{service}.dlq' // Placeholder, replaced with actual service name
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* {service}.dlq - Service dead letter queue
|
|
105
|
+
* Receives failed messages from service.queue and service.workflow
|
|
106
|
+
*/
|
|
107
|
+
dlq: {
|
|
108
|
+
durable: true,
|
|
109
|
+
arguments: {
|
|
110
|
+
// No TTL for DLQ - messages should persist
|
|
111
|
+
'x-max-length': 50000 // Higher limit for DLQ
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Registry infrastructure queue configurations
|
|
118
|
+
*/
|
|
119
|
+
registry: {
|
|
120
|
+
/**
|
|
121
|
+
* registry.register - Registration requests
|
|
122
|
+
*/
|
|
123
|
+
register: {
|
|
124
|
+
durable: true,
|
|
125
|
+
arguments: {
|
|
126
|
+
'x-message-ttl': 60000, // 1 minute TTL
|
|
127
|
+
'x-max-length': 1000
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* registry.heartbeats - Service heartbeats
|
|
133
|
+
*/
|
|
134
|
+
heartbeats: {
|
|
135
|
+
durable: true,
|
|
136
|
+
arguments: {
|
|
137
|
+
'x-message-ttl': 120000, // 2 minutes TTL
|
|
138
|
+
'x-max-length': 5000
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* registry.changes - Registry event fanout exchange
|
|
144
|
+
* (This is an exchange, not a queue, but included for reference)
|
|
145
|
+
*/
|
|
146
|
+
changes: {
|
|
147
|
+
type: 'exchange',
|
|
148
|
+
durable: true
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get infrastructure queue configuration by type and name
|
|
154
|
+
* @param {string} type - Queue type: 'workflow', 'registry'
|
|
155
|
+
* @param {string} name - Queue name: 'init', 'completed', 'register', etc.
|
|
156
|
+
* @returns {Object} Queue configuration
|
|
157
|
+
*/
|
|
158
|
+
getQueueConfig(type, name) {
|
|
159
|
+
const config = this[type]?.[name];
|
|
160
|
+
if (!config) {
|
|
161
|
+
throw new Error(`Infrastructure queue config not found: ${type}.${name}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Deep clone to avoid modifying original
|
|
165
|
+
return JSON.parse(JSON.stringify(config));
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get workflow infrastructure queue configuration
|
|
170
|
+
* @param {string} queueName - Queue name (e.g., 'workflow.init', 'workflow.completed')
|
|
171
|
+
* @returns {Object} Queue configuration
|
|
172
|
+
*/
|
|
173
|
+
getWorkflowQueueConfig(queueName) {
|
|
174
|
+
const parts = queueName.split('.');
|
|
175
|
+
if (parts.length !== 2 || parts[0] !== 'workflow') {
|
|
176
|
+
throw new Error(`Invalid workflow queue name: ${queueName}. Expected format: workflow.{name}`);
|
|
177
|
+
}
|
|
178
|
+
return this.getQueueConfig('workflow', parts[1]);
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get registry infrastructure queue configuration
|
|
183
|
+
* @param {string} queueName - Queue name (e.g., 'registry.register', 'registry.heartbeats')
|
|
184
|
+
* @returns {Object} Queue configuration
|
|
185
|
+
*/
|
|
186
|
+
getRegistryQueueConfig(queueName) {
|
|
187
|
+
const parts = queueName.split('.');
|
|
188
|
+
if (parts.length !== 2 || parts[0] !== 'registry') {
|
|
189
|
+
throw new Error(`Invalid registry queue name: ${queueName}. Expected format: registry.{name}`);
|
|
190
|
+
}
|
|
191
|
+
return this.getQueueConfig('registry', parts[1]);
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check if queue name is an infrastructure queue
|
|
196
|
+
* @param {string} queueName - Queue name to check
|
|
197
|
+
* @returns {boolean} True if infrastructure queue
|
|
198
|
+
*/
|
|
199
|
+
isInfrastructureQueue(queueName) {
|
|
200
|
+
return queueName.startsWith('workflow.') || queueName.startsWith('registry.');
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Check if queue name is a business queue
|
|
205
|
+
* @param {string} queueName - Queue name to check
|
|
206
|
+
* @returns {boolean} True if business queue
|
|
207
|
+
*/
|
|
208
|
+
isBusinessQueue(queueName) {
|
|
209
|
+
// Business queues follow pattern: {service}.{type}
|
|
210
|
+
// where type is: workflow, queue, dlq
|
|
211
|
+
const parts = queueName.split('.');
|
|
212
|
+
if (parts.length !== 2) return false;
|
|
213
|
+
return ['workflow', 'queue', 'dlq'].includes(parts[1]);
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Parse business queue name to extract service name and queue type
|
|
218
|
+
* @param {string} queueName - Business queue name (e.g., 'hello-service.workflow')
|
|
219
|
+
* @returns {Object} { serviceName, queueType } or null if not a business queue
|
|
220
|
+
*/
|
|
221
|
+
parseBusinessQueue(queueName) {
|
|
222
|
+
if (!this.isBusinessQueue(queueName)) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
const parts = queueName.split('.');
|
|
226
|
+
return {
|
|
227
|
+
serviceName: parts[0],
|
|
228
|
+
queueType: parts[1]
|
|
229
|
+
};
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get business queue configuration template
|
|
234
|
+
* @param {string} queueType - Queue type: 'workflow', 'queue', 'dlq'
|
|
235
|
+
* @param {string} serviceName - Service name (replaces {service} placeholder)
|
|
236
|
+
* @returns {Object} Queue configuration
|
|
237
|
+
*/
|
|
238
|
+
getBusinessQueueConfig(queueType, serviceName) {
|
|
239
|
+
const template = this.business?.[queueType];
|
|
240
|
+
if (!template) {
|
|
241
|
+
throw new Error(`Business queue template not found: ${queueType}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Deep clone to avoid modifying original
|
|
245
|
+
const config = JSON.parse(JSON.stringify(template));
|
|
246
|
+
|
|
247
|
+
// Replace {service} placeholder in routing keys
|
|
248
|
+
if (config.arguments && serviceName) {
|
|
249
|
+
const routingKey = config.arguments['x-dead-letter-routing-key'];
|
|
250
|
+
if (routingKey && typeof routingKey === 'string') {
|
|
251
|
+
config.arguments['x-dead-letter-routing-key'] = routingKey.replace('{service}', serviceName);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return config;
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get infrastructure queue configuration by queue name (auto-detect type)
|
|
260
|
+
* @param {string} queueName - Full queue name (e.g., 'workflow.init', 'registry.register')
|
|
261
|
+
* @returns {Object} Queue configuration
|
|
262
|
+
*/
|
|
263
|
+
getInfrastructureQueueConfig(queueName) {
|
|
264
|
+
if (queueName.startsWith('workflow.')) {
|
|
265
|
+
return this.getWorkflowQueueConfig(queueName);
|
|
266
|
+
} else if (queueName.startsWith('registry.')) {
|
|
267
|
+
return this.getRegistryQueueConfig(queueName);
|
|
268
|
+
} else {
|
|
269
|
+
throw new Error(`Queue ${queueName} is not an infrastructure queue. Infrastructure queues must start with 'workflow.' or 'registry.'`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
@@ -21,12 +21,14 @@
|
|
|
21
21
|
async function initInfrastructureQueues(channel, options = {}) {
|
|
22
22
|
const logger = options.logger || console;
|
|
23
23
|
|
|
24
|
-
// Load queueConfig from @onlineapps/conn-infra-mq
|
|
25
|
-
let queueConfig;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
// Load queueConfig - either from options or try to load from @onlineapps/conn-infra-mq
|
|
25
|
+
let queueConfig = options.queueConfig;
|
|
26
|
+
if (!queueConfig) {
|
|
27
|
+
try {
|
|
28
|
+
queueConfig = require('@onlineapps/conn-infra-mq/src/config/queueConfig');
|
|
29
|
+
} catch (requireError) {
|
|
30
|
+
throw new Error(`Cannot load queueConfig. Either provide queueConfig in options, or ensure @onlineapps/conn-infra-mq is installed: ${requireError.message}`);
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
const queuesToCreate = options.queues || [
|