@rxdi/graphql-rabbitmq-subscriptions 0.7.191 → 0.7.193

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.
@@ -15,6 +15,7 @@ export declare class AmqpPubSub {
15
15
  private triggerTransform;
16
16
  private unsubscribeChannelMap;
17
17
  private logger;
18
+ private pendingSubscriptions;
18
19
  constructor(options?: PubSubRabbitMQBusOptions);
19
20
  publish(trigger: string, payload: any, config?: IQueueNameConfig): Promise<void>;
20
21
  subscribe<T>(trigger: string, onMessage: (m: T) => Promise<void>, options?: Partial<IQueueNameConfig>): Promise<number>;
@@ -19,6 +19,8 @@ class AmqpPubSub {
19
19
  this.subsRefsMap = {};
20
20
  this.currentSubscriptionId = 0;
21
21
  this.unsubscribeChannelMap = {};
22
+ // Track in-progress subscriptions to prevent race conditions
23
+ this.pendingSubscriptions = {};
22
24
  this.triggerTransform = options.triggerTransform || ((trigger) => trigger);
23
25
  const config = options.config || { host: '127.0.0.1', port: 5672 };
24
26
  const { logger } = options;
@@ -45,15 +47,34 @@ class AmqpPubSub {
45
47
  this.logger.trace("subscriber exist, adding triggerName '%s' to saved list.", triggerName);
46
48
  return id;
47
49
  }
50
+ // Check if there's already a pending subscription for this trigger
51
+ if (this.pendingSubscriptions[triggerName]) {
52
+ this.logger.trace("subscription in progress for '%s', waiting for it to complete", triggerName);
53
+ try {
54
+ const disposer = yield this.pendingSubscriptions[triggerName];
55
+ this.subsRefsMap[triggerName] = [...(this.subsRefsMap[triggerName] || []), id];
56
+ this.unsubscribeChannelMap[triggerName] = disposer;
57
+ return id;
58
+ }
59
+ catch (err) {
60
+ this.logger.error(err, "failed to receive message from queue '%s'", triggerName);
61
+ return id;
62
+ }
63
+ }
48
64
  this.logger.trace("trying to subscribe to queue '%s'", triggerName);
65
+ // Create the subscription promise and store it immediately
66
+ const subscriptionPromise = this.consumer.subscribe(triggerName, (msg) => this.onMessage(triggerName, msg), options);
67
+ this.pendingSubscriptions[triggerName] = subscriptionPromise;
49
68
  try {
50
- const disposer = yield this.consumer.subscribe(triggerName, (msg) => this.onMessage(triggerName, msg), options);
69
+ const disposer = yield subscriptionPromise;
51
70
  this.subsRefsMap[triggerName] = [...(this.subsRefsMap[triggerName] || []), id];
52
- this.unsubscribeChannelMap[id] = disposer;
71
+ this.unsubscribeChannelMap[triggerName] = disposer;
72
+ // Clean up pending subscription
73
+ delete this.pendingSubscriptions[triggerName];
53
74
  return id;
54
75
  }
55
76
  catch (err) {
56
- this.logger.error(err, "failed to recieve message from queue '%s'", triggerName);
77
+ this.logger.error(err, "failed to receive message from queue '%s'", triggerName);
57
78
  return id;
58
79
  }
59
80
  });
@@ -68,13 +89,15 @@ class AmqpPubSub {
68
89
  let newRefs;
69
90
  if (refs.length === 1) {
70
91
  newRefs = [];
71
- if (typeof this.unsubscribeChannelMap[subId] === 'function') {
72
- this.unsubscribeChannelMap[subId]()
92
+ if (typeof this.unsubscribeChannelMap[triggerName] === 'function') {
93
+ this.unsubscribeChannelMap[triggerName]()
73
94
  .then(() => {
74
95
  this.logger.trace("cancelled channel from subscribing to queue '%s'", triggerName);
96
+ delete this.unsubscribeChannelMap[triggerName];
75
97
  })
76
98
  .catch((err) => {
77
99
  this.logger.error(err, "channel cancellation failed from queue '%j'", triggerName);
100
+ delete this.unsubscribeChannelMap[triggerName];
78
101
  });
79
102
  }
80
103
  }
@@ -83,6 +106,9 @@ class AmqpPubSub {
83
106
  if (index !== -1) {
84
107
  newRefs = [...refs.slice(0, index), ...refs.slice(index + 1)];
85
108
  }
109
+ else {
110
+ newRefs = refs;
111
+ }
86
112
  this.logger.trace("removing triggerName from listening '%s' ", triggerName);
87
113
  }
88
114
  this.subsRefsMap[triggerName] = newRefs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdi/graphql-rabbitmq-subscriptions",
3
- "version": "0.7.191",
3
+ "version": "0.7.193",
4
4
  "description": "A graphql-subscriptions PubSub Engine using RabbitMQ",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "lint": "tslint ./src/**/*.ts"
25
25
  },
26
26
  "dependencies": {
27
- "@rxdi/rabbitmq-pubsub": "^0.7.190",
27
+ "@rxdi/rabbitmq-pubsub": "^0.7.192",
28
28
  "graphql-subscriptions": "^3.0.0"
29
29
  },
30
30
  "devDependencies": {