@onlineapps/mq-client-core 1.0.74 → 1.0.76

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.74",
3
+ "version": "1.0.76",
4
4
  "description": "Core MQ client library for RabbitMQ - shared by infrastructure services and connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -766,60 +766,7 @@ class RabbitMQClient extends EventEmitter {
766
766
  this._attachConsumerChannelHandlers(this._consumerChannel);
767
767
 
768
768
  // Re-register all active consumers
769
- let reRegistered = 0;
770
- let failed = 0;
771
-
772
- if (this._activeConsumers.size > 0) {
773
- console.log(`[RabbitMQClient] [mq-client-core] Re-registering ${this._activeConsumers.size} consumers...`);
774
- for (const [queue, consumerInfo] of this._activeConsumers.entries()) {
775
- try {
776
- // Re-assert queue with correct options before consuming (may have been deleted)
777
- if (consumerInfo.options.queueOptions) {
778
- try {
779
- await this._ensureQueueChannel();
780
- if (!this._queueChannel || this._queueChannel.closed) {
781
- throw new Error('Queue channel is not available (connection may be closed)');
782
- }
783
- this._trackChannelOperation(this._queueChannel, `assertQueue ${queue} (re-register)`);
784
- await this._queueChannel.assertQueue(queue, consumerInfo.options.queueOptions);
785
- } catch (assertErr) {
786
- if (assertErr.code === 404) {
787
- console.warn(`[RabbitMQClient] [mq-client-core] Queue ${queue} does not exist, skipping consumer re-registration`);
788
- this._activeConsumers.delete(queue);
789
- failed++;
790
- this.emit('consumer:re-registration:failed', { queue, error: 'Queue does not exist', code: 404 });
791
- continue;
792
- }
793
- // 406 error means queue exists with different args - skip this consumer
794
- if (assertErr.code === 406) {
795
- console.warn(`[RabbitMQClient] [mq-client-core] Queue ${queue} exists with different args, skipping consumer re-registration`);
796
- this._activeConsumers.delete(queue);
797
- failed++;
798
- this.emit('consumer:re-registration:failed', { queue, error: 'Queue exists with different arguments', code: 406 });
799
- continue;
800
- }
801
- throw assertErr;
802
- }
803
- }
804
-
805
- const consumeResult = await this._consumerChannel.consume(
806
- queue,
807
- consumerInfo.handler,
808
- { noAck: consumerInfo.options.noAck }
809
- );
810
- consumerInfo.consumerTag = consumeResult.consumerTag;
811
- reRegistered++;
812
- console.log(`[RabbitMQClient] [mq-client-core] ✓ Re-registered consumer for queue: ${queue} (consumerTag: ${consumeResult.consumerTag})`);
813
- } catch (err) {
814
- failed++;
815
- console.error(`[RabbitMQClient] [mq-client-core] Failed to re-register consumer for queue ${queue}:`, err.message);
816
- // Remove failed consumer from tracking
817
- this._activeConsumers.delete(queue);
818
- // Emit event for re-registration failure
819
- this.emit('consumer:re-registration:failed', { queue, error: err.message, code: err.code });
820
- }
821
- }
822
- }
769
+ const { reRegistered, failed } = await this._reRegisterConsumers();
823
770
 
824
771
  console.log(`[RabbitMQClient] [mq-client-core] ✓ Consumer channel recreated (re-registered: ${reRegistered}, failed: ${failed})`);
825
772
  return { reRegistered, failed };
@@ -829,6 +776,73 @@ class RabbitMQClient extends EventEmitter {
829
776
  }
830
777
  }
831
778
 
779
+ /**
780
+ * Internal helper to re-register all active consumers on the current consumer channel
781
+ * @private
782
+ * @returns {Promise<{reRegistered: number, failed: number}>}
783
+ */
784
+ async _reRegisterConsumers() {
785
+ let reRegistered = 0;
786
+ let failed = 0;
787
+
788
+ if (!this._consumerChannel || this._consumerChannel.closed) {
789
+ return { reRegistered: 0, failed: this._activeConsumers.size };
790
+ }
791
+
792
+ if (this._activeConsumers.size > 0) {
793
+ console.log(`[RabbitMQClient] [mq-client-core] Re-registering ${this._activeConsumers.size} consumers...`);
794
+ for (const [queue, consumerInfo] of this._activeConsumers.entries()) {
795
+ try {
796
+ // Re-assert queue with correct options before consuming (may have been deleted)
797
+ if (consumerInfo.options.queueOptions) {
798
+ try {
799
+ await this._ensureQueueChannel();
800
+ if (!this._queueChannel || this._queueChannel.closed) {
801
+ throw new Error('Queue channel is not available (connection may be closed)');
802
+ }
803
+ this._trackChannelOperation(this._queueChannel, `assertQueue ${queue} (re-register)`);
804
+ await this._queueChannel.assertQueue(queue, consumerInfo.options.queueOptions);
805
+ } catch (assertErr) {
806
+ if (assertErr.code === 404) {
807
+ console.warn(`[RabbitMQClient] [mq-client-core] Queue ${queue} does not exist, skipping consumer re-registration`);
808
+ this._activeConsumers.delete(queue);
809
+ failed++;
810
+ this.emit('consumer:re-registration:failed', { queue, error: 'Queue does not exist', code: 404 });
811
+ continue;
812
+ }
813
+ // 406 error means queue exists with different args - skip this consumer
814
+ if (assertErr.code === 406) {
815
+ console.warn(`[RabbitMQClient] [mq-client-core] Queue ${queue} exists with different args, skipping consumer re-registration`);
816
+ this._activeConsumers.delete(queue);
817
+ failed++;
818
+ this.emit('consumer:re-registration:failed', { queue, error: 'Queue exists with different arguments', code: 406 });
819
+ continue;
820
+ }
821
+ throw assertErr;
822
+ }
823
+ }
824
+
825
+ const consumeResult = await this._consumerChannel.consume(
826
+ queue,
827
+ consumerInfo.handler,
828
+ { noAck: consumerInfo.options.noAck }
829
+ );
830
+ consumerInfo.consumerTag = consumeResult.consumerTag;
831
+ reRegistered++;
832
+ console.log(`[RabbitMQClient] [mq-client-core] ✓ Re-registered consumer for queue: ${queue} (consumerTag: ${consumeResult.consumerTag})`);
833
+ } catch (err) {
834
+ failed++;
835
+ console.error(`[RabbitMQClient] [mq-client-core] Failed to re-register consumer for queue ${queue}:`, err.message);
836
+ // Remove failed consumer from tracking
837
+ this._activeConsumers.delete(queue);
838
+ // Emit event for re-registration failure
839
+ this.emit('consumer:re-registration:failed', { queue, error: err.message, code: err.code });
840
+ }
841
+ }
842
+ }
843
+ return { reRegistered, failed };
844
+ }
845
+
832
846
  /**
833
847
  * Disconnects: closes channel and connection.
834
848
  * @returns {Promise<void>}
@@ -1782,33 +1796,21 @@ class RabbitMQClient extends EventEmitter {
1782
1796
 
1783
1797
  // Recreate publisher channel
1784
1798
  try {
1785
- this._channel = await this._connection.createConfirmChannel();
1786
- this._channel._createdAt = new Date().toISOString();
1787
- this._channel._closeReason = null;
1788
- this._channel._lastOperation = 'Recreated via _reconnectWithBackoff()';
1789
- this._channel._type = 'publisher';
1790
- this._attachPublisherChannelHandlers(this._channel);
1799
+ await this._ensurePublisherChannel();
1791
1800
  channelState.publisher = true;
1792
1801
  console.log('[RabbitMQClient] ✓ Publisher channel recreated');
1793
1802
  } catch (err) {
1794
1803
  console.error('[RabbitMQClient] Failed to recreate publisher channel:', err.message);
1795
- this._channel = null;
1796
1804
  // Continue - partial success is better than total failure
1797
1805
  }
1798
1806
 
1799
1807
  // Recreate queue channel
1800
1808
  try {
1801
- this._queueChannel = await this._connection.createChannel();
1802
- this._queueChannel._createdAt = new Date().toISOString();
1803
- this._queueChannel._closeReason = null;
1804
- this._queueChannel._lastOperation = 'Recreated via _reconnectWithBackoff()';
1805
- this._queueChannel._type = 'queue';
1806
- this._attachQueueChannelHandlers(this._queueChannel);
1809
+ await this._ensureQueueChannel();
1807
1810
  channelState.queue = true;
1808
1811
  console.log('[RabbitMQClient] ✓ Queue channel recreated');
1809
1812
  } catch (err) {
1810
1813
  console.error('[RabbitMQClient] Failed to recreate queue channel:', err.message);
1811
- this._queueChannel = null;
1812
1814
  // Continue - partial success is better than total failure
1813
1815
  }
1814
1816
 
@@ -1821,8 +1823,8 @@ class RabbitMQClient extends EventEmitter {
1821
1823
  this._consumerChannel._type = 'consumer';
1822
1824
  this._attachConsumerChannelHandlers(this._consumerChannel);
1823
1825
 
1824
- // Re-register all consumers
1825
- consumerReRegResult = await this._ensureConsumerChannel();
1826
+ // Re-register all consumers - use internal helper to avoid the "channel already open" check
1827
+ consumerReRegResult = await this._reRegisterConsumers();
1826
1828
  channelState.consumer = true;
1827
1829
  console.log('[RabbitMQClient] ✓ Consumer channel recreated');
1828
1830
  } catch (err) {