@onlineapps/mq-client-core 1.0.23 → 1.0.25

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/mq-client-core",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "Core MQ client library for RabbitMQ - shared by infrastructure services and connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -113,6 +113,22 @@ module.exports = {
113
113
  }
114
114
  },
115
115
 
116
+ /**
117
+ * Infrastructure health tracking queue configurations
118
+ */
119
+ infrastructure: {
120
+ /**
121
+ * infrastructure.health.checks - Health check messages from infrastructure services
122
+ */
123
+ 'health.checks': {
124
+ durable: true,
125
+ arguments: {
126
+ 'x-message-ttl': 10000, // 10 seconds TTL (prevent stale data)
127
+ 'x-max-length': 1000
128
+ }
129
+ }
130
+ },
131
+
116
132
  /**
117
133
  * Registry infrastructure queue configurations
118
134
  */
@@ -197,7 +213,10 @@ module.exports = {
197
213
  * @returns {boolean} True if infrastructure queue
198
214
  */
199
215
  isInfrastructureQueue(queueName) {
200
- return queueName.startsWith('workflow.') || queueName.startsWith('registry.');
216
+ return queueName.startsWith('workflow.') ||
217
+ queueName.startsWith('registry.') ||
218
+ queueName.startsWith('infrastructure.') ||
219
+ queueName.startsWith('validation.');
201
220
  },
202
221
 
203
222
  /**
@@ -255,9 +274,23 @@ module.exports = {
255
274
  return config;
256
275
  },
257
276
 
277
+ /**
278
+ * Get infrastructure health queue configuration
279
+ * @param {string} queueName - Queue name (e.g., 'infrastructure.health.checks')
280
+ * @returns {Object} Queue configuration
281
+ */
282
+ getInfrastructureHealthQueueConfig(queueName) {
283
+ const parts = queueName.split('.');
284
+ if (parts.length < 2 || parts[0] !== 'infrastructure') {
285
+ throw new Error(`Invalid infrastructure health queue name: ${queueName}. Expected format: infrastructure.{name}`);
286
+ }
287
+ const name = parts.slice(1).join('.');
288
+ return this.getQueueConfig('infrastructure', name);
289
+ },
290
+
258
291
  /**
259
292
  * Get infrastructure queue configuration by queue name (auto-detect type)
260
- * @param {string} queueName - Full queue name (e.g., 'workflow.init', 'registry.register')
293
+ * @param {string} queueName - Full queue name (e.g., 'workflow.init', 'registry.register', 'infrastructure.health.checks')
261
294
  * @returns {Object} Queue configuration
262
295
  */
263
296
  getInfrastructureQueueConfig(queueName) {
@@ -265,8 +298,10 @@ module.exports = {
265
298
  return this.getWorkflowQueueConfig(queueName);
266
299
  } else if (queueName.startsWith('registry.')) {
267
300
  return this.getRegistryQueueConfig(queueName);
301
+ } else if (queueName.startsWith('infrastructure.')) {
302
+ return this.getInfrastructureHealthQueueConfig(queueName);
268
303
  } else {
269
- throw new Error(`Queue ${queueName} is not an infrastructure queue. Infrastructure queues must start with 'workflow.' or 'registry.'`);
304
+ throw new Error(`Queue ${queueName} is not an infrastructure queue. Infrastructure queues must start with 'workflow.', 'registry.', or 'infrastructure.'`);
270
305
  }
271
306
  }
272
307
  };
package/src/index.js CHANGED
@@ -5,6 +5,9 @@
5
5
  *
6
6
  * Core MQ client library for RabbitMQ - shared by infrastructure services and connectors.
7
7
  * Provides basic publish/consume functionality without business-specific features.
8
+ *
9
+ * NOTE: Infrastructure orchestration utilities (waitForInfrastructureReady, initInfrastructureQueues)
10
+ * have been moved to @onlineapps/infrastructure-tools to keep this library focused on core MQ operations.
8
11
  */
9
12
 
10
13
  const BaseClient = require('./BaseClient');
@@ -16,16 +19,14 @@ const {
16
19
  ConsumeError,
17
20
  SerializationError,
18
21
  } = require('./utils/errorHandler');
19
- const { initInfrastructureQueues } = require('./utils/initInfrastructureQueues');
20
22
 
21
23
  // Export BaseClient as default (constructor), with additional named exports
22
- // NOTE: When destructuring, use: const { initInfrastructureQueues } = require('@onlineapps/mq-client-core');
24
+ // NOTE: When destructuring, use: const { BaseClient } = require('@onlineapps/mq-client-core');
23
25
  // When using default, use: const BaseClient = require('@onlineapps/mq-client-core');
24
26
  // BaseClient must be a constructor, so we export it directly and attach other exports as properties
25
27
  module.exports = BaseClient;
26
28
  module.exports.BaseClient = BaseClient;
27
29
  module.exports.RabbitMQClient = RabbitMQClient;
28
- module.exports.initInfrastructureQueues = initInfrastructureQueues;
29
30
  module.exports.errors = {
30
31
  ValidationError,
31
32
  ConnectionError,
@@ -1,143 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * initInfrastructureQueues.js
5
- *
6
- * Utility for infrastructure services to initialize infrastructure queues.
7
- * Uses queueConfig from @onlineapps/conn-infra-mq for configuration.
8
- *
9
- * NOTE: This is for infrastructure services (gateway, monitoring, etc.)
10
- * Business services should use @onlineapps/conn-infra-mq connector instead.
11
- */
12
-
13
- /**
14
- * Initialize all infrastructure queues
15
- * @param {Object} channel - RabbitMQ channel
16
- * @param {Object} options - Options
17
- * @param {Array<string>} [options.queues] - Specific queues to create (default: all infrastructure queues)
18
- * @param {Object} [options.logger] - Logger instance (default: console)
19
- * @returns {Promise<void>}
20
- */
21
- async function initInfrastructureQueues(channel, options = {}) {
22
- if (!channel) {
23
- throw new Error('initInfrastructureQueues requires a valid channel');
24
- }
25
-
26
- const logger = options.logger || console;
27
- const connection = options.connection || channel.connection;
28
-
29
- // Load queueConfig from mq-client-core (spodní vrstva)
30
- // NOTE: queueConfig is part of mq-client-core because it's used by both:
31
- // - Infrastructure services (via mq-client-core)
32
- // - Business services (via conn-infra-mq connector)
33
- const queueConfig = options.queueConfig || require('../config/queueConfig');
34
-
35
- const queuesToCreate = options.queues || [
36
- // Workflow infrastructure queues
37
- 'workflow.init',
38
- 'workflow.completed',
39
- 'workflow.failed',
40
- 'workflow.dlq',
41
- // Registry infrastructure queues
42
- 'registry.register',
43
- 'registry.heartbeats'
44
- ];
45
-
46
- const watchChannel = (ch) => {
47
- if (!ch) return ch;
48
- if (!ch.__queueInitLinked) {
49
- ch.__queueInitLinked = true;
50
- ch.once('close', () => {
51
- ch.__queueInitClosed = true;
52
- logger.warn('[QueueInit] Queue channel closed');
53
- });
54
- ch.on('error', (err) => {
55
- ch.__queueInitClosed = true;
56
- logger.warn(`[QueueInit] Queue channel error: ${err.message}`);
57
- });
58
- }
59
- return ch;
60
- };
61
-
62
- let workingChannel = watchChannel(channel);
63
-
64
- const getChannel = async (forceNew = false) => {
65
- if (!forceNew && workingChannel && !workingChannel.__queueInitClosed) {
66
- return workingChannel;
67
- }
68
- if (!connection) {
69
- throw new Error('Queue channel closed and no connection reference available to recreate it');
70
- }
71
- workingChannel = watchChannel(await connection.createChannel());
72
- return workingChannel;
73
- };
74
-
75
- logger.log(`[QueueInit] Initializing ${queuesToCreate.length} infrastructure queues...`);
76
-
77
- for (const queueName of queuesToCreate) {
78
- try {
79
- // Verify it's an infrastructure queue
80
- if (!queueConfig.isInfrastructureQueue(queueName)) {
81
- logger.warn(`[QueueInit] Skipping ${queueName} - not an infrastructure queue`);
82
- continue;
83
- }
84
-
85
- // Get unified configuration
86
- const config = queueConfig.getInfrastructureQueueConfig(queueName);
87
-
88
- // CRITICAL: Check if queue exists with different arguments (406 error)
89
- // If so, delete it and recreate with correct parameters
90
- const ensureQueue = async () => {
91
- const activeChannel = await getChannel();
92
- return activeChannel.assertQueue(queueName, {
93
- durable: config.durable !== false,
94
- arguments: { ...config.arguments }
95
- });
96
- };
97
-
98
- try {
99
- await ensureQueue();
100
- logger.log(`[QueueInit] ✓ Created/verified infrastructure queue: ${queueName}`);
101
- } catch (assertError) {
102
- if (assertError.code === 406) {
103
- logger.warn(
104
- `[QueueInit] ⚠ Queue ${queueName} exists with different arguments - deleting and recreating...`
105
- );
106
- try {
107
- const deleteChannel = await getChannel(true);
108
- await deleteChannel.deleteQueue(queueName);
109
- logger.log(`[QueueInit] ✓ Deleted queue ${queueName} with incorrect parameters`);
110
- } catch (deleteError) {
111
- logger.error(
112
- `[QueueInit] ✗ Failed to delete queue ${queueName}:`,
113
- deleteError.message
114
- );
115
- throw new Error(
116
- `Cannot delete queue ${queueName} with incorrect parameters: ${deleteError.message}`
117
- );
118
- }
119
-
120
- // Recreate with correct parameters (force fresh channel to avoid closed state)
121
- await getChannel(true);
122
- await ensureQueue();
123
- logger.log(
124
- `[QueueInit] ✓ Recreated infrastructure queue: ${queueName} with correct parameters`
125
- );
126
- } else {
127
- logger.error(`[QueueInit] ✗ Failed to create ${queueName}:`, assertError.message);
128
- throw assertError;
129
- }
130
- }
131
- } catch (error) {
132
- logger.error(`[QueueInit] ✗ Failed to initialize queue ${queueName}:`, error.message);
133
- throw error;
134
- }
135
- }
136
-
137
- logger.log(`[QueueInit] Infrastructure queues initialization complete`);
138
- }
139
-
140
- module.exports = {
141
- initInfrastructureQueues
142
- };
143
-