@nebulae/event-store-tpi-rx6 1.1.5 → 1.2.0
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/lib/broker/PubSubBroker.js +82 -46
- package/package.json +1 -1
|
@@ -21,30 +21,50 @@ class PubSubBroker {
|
|
|
21
21
|
)
|
|
22
22
|
this.senderId = uuidv4();
|
|
23
23
|
this.pubsubClient = new PubSub({});
|
|
24
|
+
this.subscriptionLock = false;
|
|
25
|
+
this.startLock = false;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Starts Broker connections
|
|
28
30
|
* Returns an Obserable that resolves to each connection result
|
|
31
|
+
* Uses a semaphore to prevent concurrent access - returns of(null) if busy
|
|
29
32
|
*/
|
|
30
|
-
start$() {
|
|
31
|
-
return new Rx.Observable(async (observer) => {
|
|
33
|
+
start$() {
|
|
34
|
+
return new Rx.Observable(async (observer) => {
|
|
35
|
+
// Check semaphore - return null if already busy
|
|
36
|
+
if (this.startLock) {
|
|
37
|
+
observer.next(null);
|
|
38
|
+
observer.complete();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Acquire lock
|
|
43
|
+
this.startLock = true;
|
|
44
|
+
|
|
32
45
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
try {
|
|
47
|
+
const [topic] = await this.pubsubClient.createTopic(this.eventsTopic);
|
|
48
|
+
console.log(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker created topic: Topic=${this.eventsTopic}`);
|
|
49
|
+
this.topic = topic;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
if (error.code === 6) {
|
|
52
|
+
this.topic = this.pubsubClient.topic(this.eventsTopic);
|
|
53
|
+
console.log(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker topic already exists, getting existing topic: Topic=${this.eventsTopic}`);
|
|
54
|
+
} else {
|
|
55
|
+
observer.error(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker failed to create or get topic: Topic=${this.eventsTopic}, Error=${error.message}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (this.topic) {
|
|
60
|
+
this.startMessageListener(this.topic);
|
|
61
|
+
observer.next(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker listening: Topic=${this.eventsTopic}, subscriptionName=${this.eventsTopicSubscription}`);
|
|
62
|
+
}
|
|
63
|
+
observer.complete();
|
|
64
|
+
} finally {
|
|
65
|
+
// Release lock
|
|
66
|
+
this.startLock = false;
|
|
44
67
|
}
|
|
45
|
-
this.startMessageListener(this.topic);
|
|
46
|
-
observer.next(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker listening: Topic=${this.eventsTopic}, subscriptionName=${this.eventsTopicSubscription}`);
|
|
47
|
-
observer.complete();
|
|
48
68
|
});
|
|
49
69
|
}
|
|
50
70
|
|
|
@@ -53,7 +73,9 @@ class PubSubBroker {
|
|
|
53
73
|
*/
|
|
54
74
|
stop$() {
|
|
55
75
|
return Rx.Observable.create(observer => {
|
|
56
|
-
Rx.defer(() => this.getSubscription$()).
|
|
76
|
+
Rx.defer(() => this.getSubscription$()).pipe(
|
|
77
|
+
filter(sub => sub != null)
|
|
78
|
+
).subscribe(
|
|
57
79
|
(subscription) => {
|
|
58
80
|
subscription.removeListener(`message`, this.onMessage);
|
|
59
81
|
observer.next(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker removed listener: Topic=${this.eventsTopic}, subscriptionName=${subscription}`);
|
|
@@ -93,28 +115,41 @@ class PubSubBroker {
|
|
|
93
115
|
getEventListener$(aggregateType, ignoreSelfEvents = true) {
|
|
94
116
|
return this.orderedIncomingEvents$.pipe(
|
|
95
117
|
filter(msg => msg)
|
|
96
|
-
,filter(msg => !ignoreSelfEvents || msg.attributes.senderId !== this.senderId)
|
|
97
|
-
,map(msg => msg.data)
|
|
98
|
-
,filter(evt => evt.at === aggregateType || aggregateType == "*")
|
|
99
|
-
|
|
118
|
+
, filter(msg => !ignoreSelfEvents || msg.attributes.senderId !== this.senderId)
|
|
119
|
+
, map(msg => msg.data)
|
|
120
|
+
, filter(evt => evt.at === aggregateType || aggregateType == "*")
|
|
121
|
+
)
|
|
100
122
|
}
|
|
101
123
|
|
|
102
124
|
|
|
103
125
|
/**
|
|
104
126
|
* Returns an Observable that resolves to the subscription
|
|
127
|
+
* Uses a semaphore to prevent concurrent access - returns null if busy
|
|
105
128
|
*/
|
|
106
129
|
async getSubscription$(topic) {
|
|
130
|
+
// Check semaphore - return null if already busy
|
|
131
|
+
if (this.subscriptionLock) {
|
|
132
|
+
//console.log(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker getSubscription$ is busy, returning null`);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Acquire lock
|
|
137
|
+
this.subscriptionLock = true;
|
|
138
|
+
|
|
107
139
|
try {
|
|
108
140
|
const [subscription] = await (topic || this.topic).createSubscription(this.eventsTopicSubscription);
|
|
109
141
|
console.log(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker created subscription: Topic=${this.eventsTopic}, subscriptionName=${this.eventsTopicSubscription}`);
|
|
110
|
-
return subscription;
|
|
142
|
+
return subscription;
|
|
111
143
|
} catch (error) {
|
|
112
|
-
if(error.code === 6) {
|
|
144
|
+
if (error.code === 6) {
|
|
113
145
|
console.log(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker subscription already exists, getting existing subscription: Topic=${this.eventsTopic}, subscriptionName=${this.eventsTopicSubscription}`);
|
|
114
146
|
return (topic || this.topic).subscription(this.eventsTopicSubscription);
|
|
115
147
|
} else {
|
|
116
148
|
throw new Error(`@nebulae/event-store-tpi-rx6: Event Store PubSub Broker failed to create or get subscription: Topic=${this.eventsTopic}, subscriptionName=${this.eventsTopicSubscription}, Error=${error.message}`);
|
|
117
149
|
}
|
|
150
|
+
} finally {
|
|
151
|
+
// Release lock
|
|
152
|
+
this.subscriptionLock = false;
|
|
118
153
|
}
|
|
119
154
|
}
|
|
120
155
|
|
|
@@ -122,30 +157,31 @@ class PubSubBroker {
|
|
|
122
157
|
* Starts to listen messages
|
|
123
158
|
*/
|
|
124
159
|
startMessageListener(topic) {
|
|
125
|
-
this.messageListenerSubscription = Rx.defer(() => this.getSubscription$(topic))
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
};
|
|
137
|
-
pubSubSubscription.on(`message`, this.onMessage);
|
|
138
|
-
pubSubSubscription.on('error', error => {
|
|
139
|
-
console.error('@nebulae/event-store-tpi-rx6.PubSubBroker: Received error:', error);
|
|
160
|
+
this.messageListenerSubscription = Rx.defer(() => this.getSubscription$(topic)).pipe(
|
|
161
|
+
filter(sub => sub != null)
|
|
162
|
+
).subscribe(
|
|
163
|
+
(pubSubSubscription) => {
|
|
164
|
+
this.onMessage = message => {
|
|
165
|
+
message.ack();
|
|
166
|
+
this.incomingEvents$.next({
|
|
167
|
+
data: JSON.parse(message.data),
|
|
168
|
+
id: message.id,
|
|
169
|
+
attributes: message.attributes,
|
|
170
|
+
correlationId: message.attributes.correlationId
|
|
140
171
|
});
|
|
141
|
-
}
|
|
142
|
-
(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
172
|
+
};
|
|
173
|
+
pubSubSubscription.on(`message`, this.onMessage);
|
|
174
|
+
pubSubSubscription.on('error', error => {
|
|
175
|
+
console.error('@nebulae/event-store-tpi-rx6.PubSubBroker: Received error:', error);
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
(err) => {
|
|
179
|
+
console.error('Failed to obtain EventStore subscription', err);
|
|
180
|
+
},
|
|
181
|
+
() => {
|
|
182
|
+
console.log('GatewayEvents listener has completed!');
|
|
183
|
+
}
|
|
184
|
+
);
|
|
149
185
|
}
|
|
150
186
|
|
|
151
187
|
}
|
package/package.json
CHANGED