@rxdi/graphql-rabbitmq-subscriptions 0.7.193 → 0.7.194

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.
@@ -14,8 +14,8 @@ export declare class AmqpPubSub {
14
14
  private currentSubscriptionId;
15
15
  private triggerTransform;
16
16
  private unsubscribeChannelMap;
17
- private logger;
18
17
  private pendingSubscriptions;
18
+ private logger;
19
19
  constructor(options?: PubSubRabbitMQBusOptions);
20
20
  publish(trigger: string, payload: any, config?: IQueueNameConfig): Promise<void>;
21
21
  subscribe<T>(trigger: string, onMessage: (m: T) => Promise<void>, options?: Partial<IQueueNameConfig>): Promise<number>;
@@ -15,19 +15,18 @@ const rabbitmq_pubsub_1 = require("@rxdi/rabbitmq-pubsub");
15
15
  const child_logger_1 = require("./child-logger");
16
16
  class AmqpPubSub {
17
17
  constructor(options = {}) {
18
- this.subscriptionMap = {};
19
- this.subsRefsMap = {};
18
+ this.subscriptionMap = new Map();
19
+ this.subsRefsMap = new Map();
20
20
  this.currentSubscriptionId = 0;
21
- this.unsubscribeChannelMap = {};
21
+ this.unsubscribeChannelMap = new Map();
22
22
  // Track in-progress subscriptions to prevent race conditions
23
- this.pendingSubscriptions = {};
23
+ this.pendingSubscriptions = new Map();
24
24
  this.triggerTransform = options.triggerTransform || ((trigger) => trigger);
25
25
  const config = options.config || { host: '127.0.0.1', port: 5672 };
26
- const { logger } = options;
27
- this.logger = (0, child_logger_1.createChildLogger)(logger, 'AmqpPubSub');
28
- const factory = new rabbitmq_pubsub_1.RabbitMqSingletonConnectionFactory(logger, config);
29
- this.consumer = new rabbitmq_pubsub_1.RabbitMqSubscriber(logger, factory);
30
- this.producer = new rabbitmq_pubsub_1.RabbitMqPublisher(logger, factory);
26
+ this.logger = (0, child_logger_1.createChildLogger)(options.logger, 'AmqpPubSub');
27
+ const factory = new rabbitmq_pubsub_1.RabbitMqSingletonConnectionFactory(options.logger, config);
28
+ this.consumer = new rabbitmq_pubsub_1.RabbitMqSubscriber(options.logger, factory);
29
+ this.producer = new rabbitmq_pubsub_1.RabbitMqPublisher(options.logger, factory);
31
30
  }
32
31
  publish(trigger, payload, config) {
33
32
  return __awaiter(this, void 0, void 0, function* () {
@@ -39,21 +38,22 @@ class AmqpPubSub {
39
38
  return __awaiter(this, void 0, void 0, function* () {
40
39
  const triggerName = this.triggerTransform(trigger, options);
41
40
  const id = this.currentSubscriptionId++;
42
- this.subscriptionMap[id] = [triggerName, onMessage];
43
- let refs = this.subsRefsMap[triggerName];
44
- if (refs && refs.length > 0) {
45
- const newRefs = [...refs, id];
46
- this.subsRefsMap[triggerName] = newRefs;
47
- this.logger.trace("subscriber exist, adding triggerName '%s' to saved list.", triggerName);
41
+ this.subscriptionMap.set(id, [triggerName, onMessage]);
42
+ const refs = this.subsRefsMap.get(triggerName);
43
+ if (refs === null || refs === void 0 ? void 0 : refs.length) {
44
+ this.subsRefsMap.set(triggerName, [...refs, id]);
45
+ this.logger.trace("subscriber exists, adding triggerName '%s' to saved list.", triggerName);
48
46
  return id;
49
47
  }
50
- // Check if there's already a pending subscription for this trigger
51
- if (this.pendingSubscriptions[triggerName]) {
48
+ // Subscription already in progress
49
+ const pending = this.pendingSubscriptions.get(triggerName);
50
+ if (pending) {
52
51
  this.logger.trace("subscription in progress for '%s', waiting for it to complete", triggerName);
53
52
  try {
54
- const disposer = yield this.pendingSubscriptions[triggerName];
55
- this.subsRefsMap[triggerName] = [...(this.subsRefsMap[triggerName] || []), id];
56
- this.unsubscribeChannelMap[triggerName] = disposer;
53
+ const disposer = yield pending;
54
+ const nextRefs = [...(this.subsRefsMap.get(triggerName) || []), id];
55
+ this.subsRefsMap.set(triggerName, nextRefs);
56
+ this.unsubscribeChannelMap.set(triggerName, disposer);
57
57
  return id;
58
58
  }
59
59
  catch (err) {
@@ -62,72 +62,69 @@ class AmqpPubSub {
62
62
  }
63
63
  }
64
64
  this.logger.trace("trying to subscribe to queue '%s'", triggerName);
65
- // Create the subscription promise and store it immediately
66
65
  const subscriptionPromise = this.consumer.subscribe(triggerName, (msg) => this.onMessage(triggerName, msg), options);
67
- this.pendingSubscriptions[triggerName] = subscriptionPromise;
66
+ this.pendingSubscriptions.set(triggerName, subscriptionPromise);
68
67
  try {
69
68
  const disposer = yield subscriptionPromise;
70
- this.subsRefsMap[triggerName] = [...(this.subsRefsMap[triggerName] || []), id];
71
- this.unsubscribeChannelMap[triggerName] = disposer;
72
- // Clean up pending subscription
73
- delete this.pendingSubscriptions[triggerName];
69
+ this.subsRefsMap.set(triggerName, [...(this.subsRefsMap.get(triggerName) || []), id]);
70
+ this.unsubscribeChannelMap.set(triggerName, disposer);
71
+ this.pendingSubscriptions.delete(triggerName);
74
72
  return id;
75
73
  }
76
74
  catch (err) {
77
75
  this.logger.error(err, "failed to receive message from queue '%s'", triggerName);
76
+ this.pendingSubscriptions.delete(triggerName);
78
77
  return id;
79
78
  }
80
79
  });
81
80
  }
82
81
  unsubscribe(subId) {
83
- const [triggerName = null] = this.subscriptionMap[subId] || [];
84
- const refs = this.subsRefsMap[triggerName];
85
- if (!refs) {
82
+ const entry = this.subscriptionMap.get(subId);
83
+ const triggerName = entry === null || entry === void 0 ? void 0 : entry[0];
84
+ if (!triggerName) {
86
85
  this.logger.error("There is no subscription of id '%s'", subId);
87
86
  throw new Error(`There is no subscription of id "${subId}"`);
88
87
  }
89
- let newRefs;
88
+ const refs = this.subsRefsMap.get(triggerName);
89
+ if (!refs)
90
+ return;
90
91
  if (refs.length === 1) {
91
- newRefs = [];
92
- if (typeof this.unsubscribeChannelMap[triggerName] === 'function') {
93
- this.unsubscribeChannelMap[triggerName]()
92
+ const disposer = this.unsubscribeChannelMap.get(triggerName);
93
+ if (typeof disposer === 'function') {
94
+ disposer()
94
95
  .then(() => {
95
96
  this.logger.trace("cancelled channel from subscribing to queue '%s'", triggerName);
96
- delete this.unsubscribeChannelMap[triggerName];
97
97
  })
98
98
  .catch((err) => {
99
- this.logger.error(err, "channel cancellation failed from queue '%j'", triggerName);
100
- delete this.unsubscribeChannelMap[triggerName];
99
+ this.logger.error(err, "channel cancellation failed from queue '%s'", triggerName);
100
+ })
101
+ .finally(() => {
102
+ this.unsubscribeChannelMap.delete(triggerName);
101
103
  });
102
104
  }
105
+ this.subsRefsMap.delete(triggerName);
103
106
  }
104
107
  else {
105
- const index = refs.indexOf(subId);
106
- if (index !== -1) {
107
- newRefs = [...refs.slice(0, index), ...refs.slice(index + 1)];
108
- }
109
- else {
110
- newRefs = refs;
111
- }
112
- this.logger.trace("removing triggerName from listening '%s' ", triggerName);
108
+ this.subsRefsMap.set(triggerName, refs.filter((id) => id !== subId));
109
+ this.logger.trace("removing triggerName from listening '%s'", triggerName);
113
110
  }
114
- this.subsRefsMap[triggerName] = newRefs;
115
- delete this.subscriptionMap[subId];
116
- this.logger.trace("list of subscriptions still available '(%j)'", this.subscriptionMap);
111
+ this.subscriptionMap.delete(subId);
112
+ this.logger.trace("list of subscriptions still available '(%j)'", Array.from(this.subscriptionMap.entries()));
117
113
  }
118
114
  asyncIterator(triggers, options) {
119
115
  return new pubsub_async_iterator_1.PubSubAsyncIterator(this, triggers, options);
120
116
  }
121
117
  onMessage(channel, message) {
122
118
  return __awaiter(this, void 0, void 0, function* () {
123
- const subscribers = this.subsRefsMap[channel];
124
- // Don't work for nothing..
125
- if (!subscribers || !subscribers.length) {
119
+ const subscribers = this.subsRefsMap.get(channel);
120
+ if (!(subscribers === null || subscribers === void 0 ? void 0 : subscribers.length))
126
121
  return;
127
- }
128
122
  this.logger.trace("sending message to subscriber callback function '(%j)'", message);
129
123
  for (const subId of subscribers) {
130
- const [triggerName, listener] = this.subscriptionMap[subId];
124
+ const entry = this.subscriptionMap.get(subId);
125
+ if (!entry)
126
+ continue;
127
+ const [, listener] = entry;
131
128
  yield listener(message);
132
129
  }
133
130
  });
package/dist/index.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export { AmqpPubSub } from './amqp-pubsub';
2
+ import { FilterFn, ResolverFn } from 'graphql-subscriptions';
3
+ export declare function withFilter<T>(this: T, asyncIteratorFn: ResolverFn<any, any, any>, filterFn: FilterFn<any, any, any>): import("graphql-subscriptions").IterableResolverFn<any, any, any>;
package/dist/index.js CHANGED
@@ -1,5 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AmqpPubSub = void 0;
4
+ exports.withFilter = withFilter;
4
5
  var amqp_pubsub_1 = require("./amqp-pubsub");
5
6
  Object.defineProperty(exports, "AmqpPubSub", { enumerable: true, get: function () { return amqp_pubsub_1.AmqpPubSub; } });
7
+ const graphql_subscriptions_1 = require("graphql-subscriptions");
8
+ function withFilter(asyncIteratorFn, filterFn) {
9
+ return (0, graphql_subscriptions_1.withFilter)(asyncIteratorFn, filterFn);
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdi/graphql-rabbitmq-subscriptions",
3
- "version": "0.7.193",
3
+ "version": "0.7.194",
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.192",
27
+ "@rxdi/rabbitmq-pubsub": "^0.7.193",
28
28
  "graphql-subscriptions": "^3.0.0"
29
29
  },
30
30
  "devDependencies": {