stream-demux 9.0.1 → 10.0.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/README.md +2 -5
- package/demuxed-consumable-stream.js +1 -1
- package/index.js +104 -67
- package/package.json +1 -1
- package/test/test.js +128 -0
- package/stream-consumer.js +0 -172
package/README.md
CHANGED
|
@@ -98,8 +98,5 @@ function wait(duration) {
|
|
|
98
98
|
|
|
99
99
|
## Goal
|
|
100
100
|
|
|
101
|
-
The goal of this module is to
|
|
102
|
-
|
|
103
|
-
Each stream returned by this module is responsible for picking up its own data from a shared source stream - This means that the stream-demux module doesn't hold any references to streams which it produces via its `stream()` method; this reduces the likelihood of programming mistakes which would lead to memory leaks because streams don't need to be destroyed or cleaned up explicitly.
|
|
104
|
-
|
|
105
|
-
The downside to making each stream responsible for consuming its own data is that having a lot of concurrent streams can have a negative impact on performance (especially if there are a lot of idle streams). A goal of stream-demux is to keep that overhead to a minimum.
|
|
101
|
+
The goal of this module is to facilitate functional programming patterns which decrease the probability of memory leaks and race conditions.
|
|
102
|
+
It serves as an alternative to callback-based event handling.
|
|
@@ -3,8 +3,8 @@ const ConsumableStream = require('consumable-stream');
|
|
|
3
3
|
class DemuxedConsumableStream extends ConsumableStream {
|
|
4
4
|
constructor(streamDemux, name) {
|
|
5
5
|
super();
|
|
6
|
-
this.name = name;
|
|
7
6
|
this._streamDemux = streamDemux;
|
|
7
|
+
this.name = name;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
createConsumer(timeout) {
|
package/index.js
CHANGED
|
@@ -1,135 +1,168 @@
|
|
|
1
1
|
const WritableConsumableStream = require('writable-consumable-stream');
|
|
2
2
|
const DemuxedConsumableStream = require('./demuxed-consumable-stream');
|
|
3
|
-
const StreamConsumer = require('./stream-consumer');
|
|
4
3
|
|
|
5
4
|
class StreamDemux {
|
|
6
5
|
constructor() {
|
|
7
|
-
this.
|
|
6
|
+
this.streams = {};
|
|
7
|
+
this._nextConsumerId = 1;
|
|
8
|
+
this.generateConsumerId = () => {
|
|
9
|
+
return this._nextConsumerId++;
|
|
10
|
+
};
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
write(streamName, value) {
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
value,
|
|
15
|
-
done: false
|
|
16
|
-
}
|
|
17
|
-
});
|
|
14
|
+
if (this.streams[streamName]) {
|
|
15
|
+
this.streams[streamName].write(value);
|
|
16
|
+
}
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
close(streamName, value) {
|
|
21
|
-
this.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
value,
|
|
25
|
-
done: true
|
|
26
|
-
}
|
|
27
|
-
});
|
|
20
|
+
if (this.streams[streamName]) {
|
|
21
|
+
this.streams[streamName].close(value);
|
|
22
|
+
}
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
closeAll(value) {
|
|
31
|
-
this.
|
|
26
|
+
for (let stream of Object.values(this.streams)) {
|
|
27
|
+
stream.close(value);
|
|
28
|
+
}
|
|
32
29
|
}
|
|
33
30
|
|
|
34
31
|
writeToConsumer(consumerId, value) {
|
|
35
|
-
this.
|
|
36
|
-
consumerId
|
|
37
|
-
|
|
38
|
-
value,
|
|
39
|
-
done: false
|
|
32
|
+
for (let stream of Object.values(this.streams)) {
|
|
33
|
+
if (stream.hasConsumer(consumerId)) {
|
|
34
|
+
return stream.writeToConsumer(consumerId, value);
|
|
40
35
|
}
|
|
41
|
-
}
|
|
36
|
+
}
|
|
42
37
|
}
|
|
43
38
|
|
|
44
39
|
closeConsumer(consumerId, value) {
|
|
45
|
-
this.
|
|
46
|
-
consumerId
|
|
47
|
-
|
|
48
|
-
value,
|
|
49
|
-
done: true
|
|
40
|
+
for (let stream of Object.values(this.streams)) {
|
|
41
|
+
if (stream.hasConsumer(consumerId)) {
|
|
42
|
+
return stream.closeConsumer(consumerId, value);
|
|
50
43
|
}
|
|
51
|
-
}
|
|
44
|
+
}
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
getConsumerStats(consumerId) {
|
|
55
|
-
|
|
48
|
+
for (let [streamName, stream] of Object.entries(this.streams)) {
|
|
49
|
+
if (stream.hasConsumer(consumerId)) {
|
|
50
|
+
return {
|
|
51
|
+
...stream.getConsumerStats(consumerId),
|
|
52
|
+
stream: streamName
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
getConsumerStatsList(streamName) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
if (this.streams[streamName]) {
|
|
61
|
+
return this.streams[streamName]
|
|
62
|
+
.getConsumerStatsList()
|
|
63
|
+
.map(
|
|
64
|
+
(stats) => {
|
|
65
|
+
return {
|
|
66
|
+
...stats,
|
|
67
|
+
stream: streamName
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return [];
|
|
63
73
|
}
|
|
64
74
|
|
|
65
75
|
getConsumerStatsListAll() {
|
|
66
|
-
|
|
76
|
+
let allStatsList = [];
|
|
77
|
+
for (let streamName of Object.keys(this.streams)) {
|
|
78
|
+
let statsList = this.getConsumerStatsList(streamName);
|
|
79
|
+
for (let stats of statsList) {
|
|
80
|
+
allStatsList.push(stats);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return allStatsList;
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
kill(streamName, value) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
for (let i = 0; i < len; i++) {
|
|
73
|
-
this.killConsumer(consumerList[i].id, value);
|
|
87
|
+
if (this.streams[streamName]) {
|
|
88
|
+
this.streams[streamName].kill(value);
|
|
74
89
|
}
|
|
75
90
|
}
|
|
76
91
|
|
|
77
92
|
killAll(value) {
|
|
78
|
-
this.
|
|
93
|
+
for (let stream of Object.values(this.streams)) {
|
|
94
|
+
stream.kill(value);
|
|
95
|
+
}
|
|
79
96
|
}
|
|
80
97
|
|
|
81
98
|
killConsumer(consumerId, value) {
|
|
82
|
-
this.
|
|
99
|
+
for (let stream of Object.values(this.streams)) {
|
|
100
|
+
if (stream.hasConsumer(consumerId)) {
|
|
101
|
+
return stream.killConsumer(consumerId, value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
getBackpressure(streamName) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
let maxBackpressure = 0;
|
|
90
|
-
for (let i = 0; i < len; i++) {
|
|
91
|
-
let consumer = consumerList[i];
|
|
92
|
-
if (consumer.backpressure > maxBackpressure) {
|
|
93
|
-
maxBackpressure = consumer.backpressure;
|
|
94
|
-
}
|
|
107
|
+
if (this.streams[streamName]) {
|
|
108
|
+
return this.streams[streamName].getBackpressure();
|
|
95
109
|
}
|
|
96
|
-
return
|
|
110
|
+
return 0;
|
|
97
111
|
}
|
|
98
112
|
|
|
99
113
|
getBackpressureAll() {
|
|
100
|
-
return this.
|
|
114
|
+
return Object.values(this.streams).reduce(
|
|
115
|
+
(max, stream) => Math.max(max, stream.getBackpressure()),
|
|
116
|
+
0
|
|
117
|
+
);
|
|
101
118
|
}
|
|
102
119
|
|
|
103
120
|
getConsumerBackpressure(consumerId) {
|
|
104
|
-
|
|
121
|
+
for (let stream of Object.values(this.streams)) {
|
|
122
|
+
if (stream.hasConsumer(consumerId)) {
|
|
123
|
+
return stream.getConsumerBackpressure(consumerId);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return 0;
|
|
105
127
|
}
|
|
106
128
|
|
|
107
129
|
hasConsumer(streamName, consumerId) {
|
|
108
|
-
|
|
109
|
-
|
|
130
|
+
if (this.streams[streamName]) {
|
|
131
|
+
return this.streams[streamName].hasConsumer(consumerId);
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
hasConsumerAll(consumerId) {
|
|
113
|
-
return this.
|
|
137
|
+
return Object.values(this.streams).some(stream => stream.hasConsumer(consumerId));
|
|
114
138
|
}
|
|
115
139
|
|
|
116
140
|
getConsumerCount(streamName) {
|
|
117
|
-
|
|
141
|
+
if (this.streams[streamName]) {
|
|
142
|
+
return this.streams[streamName].getConsumerCount();
|
|
143
|
+
}
|
|
144
|
+
return 0;
|
|
118
145
|
}
|
|
119
146
|
|
|
120
147
|
getConsumerCountAll() {
|
|
121
|
-
return this.
|
|
148
|
+
return Object.values(this.streams).reduce(
|
|
149
|
+
(sum, stream) => sum + stream.getConsumerCount(),
|
|
150
|
+
0
|
|
151
|
+
);
|
|
122
152
|
}
|
|
123
153
|
|
|
124
|
-
createConsumer(streamName, timeout
|
|
125
|
-
|
|
126
|
-
this.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
createConsumer(streamName, timeout) {
|
|
155
|
+
if (!this.streams[streamName]) {
|
|
156
|
+
this.streams[streamName] = new WritableConsumableStream({
|
|
157
|
+
generateConsumerId: this.generateConsumerId,
|
|
158
|
+
removeConsumerCallback: () => {
|
|
159
|
+
if (!this.getConsumerCount(streamName)) {
|
|
160
|
+
delete this.streams[streamName];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return this.streams[streamName].createConsumer(timeout);
|
|
133
166
|
}
|
|
134
167
|
|
|
135
168
|
// Unlike individual consumers, consumable streams support being iterated
|
|
@@ -137,6 +170,10 @@ class StreamDemux {
|
|
|
137
170
|
stream(streamName) {
|
|
138
171
|
return new DemuxedConsumableStream(this, streamName);
|
|
139
172
|
}
|
|
173
|
+
|
|
174
|
+
unstream(streamName) {
|
|
175
|
+
delete this.streams[streamName];
|
|
176
|
+
}
|
|
140
177
|
}
|
|
141
178
|
|
|
142
179
|
module.exports = StreamDemux;
|
package/package.json
CHANGED
package/test/test.js
CHANGED
|
@@ -231,6 +231,102 @@ describe('StreamDemux', () => {
|
|
|
231
231
|
assert.equal(receivedPacketsB.length, 10);
|
|
232
232
|
});
|
|
233
233
|
|
|
234
|
+
it('should support writing multiple times within the same call stack and across multiple streams', async () => {
|
|
235
|
+
(async () => {
|
|
236
|
+
for (let i = 0; i < 10; i++) {
|
|
237
|
+
await wait(20);
|
|
238
|
+
for (let j = 0; j < 10; j++) {
|
|
239
|
+
demux.write('hello', 'world' + i + '-' + j);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
demux.close('hello');
|
|
243
|
+
})();
|
|
244
|
+
|
|
245
|
+
(async () => {
|
|
246
|
+
for (let i = 0; i < 10; i++) {
|
|
247
|
+
await wait(10);
|
|
248
|
+
for (let j = 0; j < 5; j++) {
|
|
249
|
+
demux.write('other', 'message' + i + '-' + j);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
demux.close('other');
|
|
253
|
+
})();
|
|
254
|
+
|
|
255
|
+
let substream = demux.stream('hello');
|
|
256
|
+
let otherSubstream = demux.stream('other');
|
|
257
|
+
|
|
258
|
+
let otherReceivedPackets = [];
|
|
259
|
+
(async () => {
|
|
260
|
+
for await (let otherPacket of otherSubstream) {
|
|
261
|
+
await wait(10);
|
|
262
|
+
otherReceivedPackets.push(otherPacket);
|
|
263
|
+
}
|
|
264
|
+
})();
|
|
265
|
+
|
|
266
|
+
(async () => {
|
|
267
|
+
for await (let otherPacket of otherSubstream) {
|
|
268
|
+
await wait(20);
|
|
269
|
+
otherReceivedPackets.push(otherPacket);
|
|
270
|
+
}
|
|
271
|
+
})();
|
|
272
|
+
|
|
273
|
+
let receivedPackets = [];
|
|
274
|
+
for await (let packet of substream) {
|
|
275
|
+
await wait(20);
|
|
276
|
+
receivedPackets.push(packet);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
assert.equal(receivedPackets.length, 100);
|
|
280
|
+
assert.equal(otherReceivedPackets.length, 100);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should support writing an arbitrarily large number of times within the same call stack', async () => {
|
|
284
|
+
(async () => {
|
|
285
|
+
await wait(50);
|
|
286
|
+
for (let i = 0; i < 100; i++) {
|
|
287
|
+
demux.write('hello', 'world' + i);
|
|
288
|
+
}
|
|
289
|
+
demux.close('hello');
|
|
290
|
+
})();
|
|
291
|
+
|
|
292
|
+
let substream = demux.stream('hello');
|
|
293
|
+
|
|
294
|
+
let receivedPackets = [];
|
|
295
|
+
for await (let packet of substream) {
|
|
296
|
+
receivedPackets.push(packet);
|
|
297
|
+
await wait(10);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
assert.equal(receivedPackets.length, 100);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should support writing an arbitrarily large number of times within the same call stack with multiple concurrent consumers', async () => {
|
|
304
|
+
(async () => {
|
|
305
|
+
await wait(50);
|
|
306
|
+
for (let i = 0; i < 50; i++) {
|
|
307
|
+
demux.write('other', 'message' + i);
|
|
308
|
+
}
|
|
309
|
+
demux.close('other');
|
|
310
|
+
})();
|
|
311
|
+
|
|
312
|
+
let otherSubstream = demux.stream('other');
|
|
313
|
+
|
|
314
|
+
let receivedPackets = [];
|
|
315
|
+
(async () => {
|
|
316
|
+
for await (let otherPacket of otherSubstream) {
|
|
317
|
+
await wait(10);
|
|
318
|
+
receivedPackets.push(otherPacket);
|
|
319
|
+
}
|
|
320
|
+
})();
|
|
321
|
+
|
|
322
|
+
for await (let otherPacket of otherSubstream) {
|
|
323
|
+
await wait(20);
|
|
324
|
+
receivedPackets.push(otherPacket);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
assert.equal(receivedPackets.length, 100);
|
|
328
|
+
});
|
|
329
|
+
|
|
234
330
|
it('should support the stream.once() method', async () => {
|
|
235
331
|
(async () => {
|
|
236
332
|
for (let i = 0; i < 10; i++) {
|
|
@@ -248,6 +344,8 @@ describe('StreamDemux', () => {
|
|
|
248
344
|
packet = await substream.once();
|
|
249
345
|
assert.equal(packet, 'world1');
|
|
250
346
|
|
|
347
|
+
await wait(1);
|
|
348
|
+
|
|
251
349
|
packet = await substream.once();
|
|
252
350
|
assert.equal(packet, 'world2');
|
|
253
351
|
});
|
|
@@ -319,6 +417,36 @@ describe('StreamDemux', () => {
|
|
|
319
417
|
assert.equal(packet, null);
|
|
320
418
|
});
|
|
321
419
|
|
|
420
|
+
it('should prevent stream timeout from being reset when writing to other streams when iterating over consumer with timeout', async () => {
|
|
421
|
+
(async () => {
|
|
422
|
+
for (let i = 0; i < 10; i++) {
|
|
423
|
+
await wait(200);
|
|
424
|
+
demux.write('foo', 123);
|
|
425
|
+
await wait(200);
|
|
426
|
+
demux.write('hello', 'test' + i);
|
|
427
|
+
}
|
|
428
|
+
demux.kill('hello');
|
|
429
|
+
})();
|
|
430
|
+
|
|
431
|
+
let consumer = demux.stream('hello').createConsumer(300);
|
|
432
|
+
let error;
|
|
433
|
+
|
|
434
|
+
let packet;
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
while (true) {
|
|
438
|
+
packet = await consumer.next();
|
|
439
|
+
if (packet.done) break;
|
|
440
|
+
}
|
|
441
|
+
} catch (err) {
|
|
442
|
+
error = err;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
assert.notEqual(error, null);
|
|
446
|
+
assert.equal(error.name, 'TimeoutError');
|
|
447
|
+
assert.equal(packet, null);
|
|
448
|
+
});
|
|
449
|
+
|
|
322
450
|
it('should prevent stream.once() timeout from being reset when killing other streams', async () => {
|
|
323
451
|
(async () => {
|
|
324
452
|
for (let i = 0; i < 15; i++) {
|
package/stream-consumer.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
class StreamConsumer {
|
|
2
|
-
constructor(mainStream, id, startNode, streamName, timeout, usabilityMode) {
|
|
3
|
-
this.id = id;
|
|
4
|
-
this._backpressure = 0;
|
|
5
|
-
this.currentNode = startNode;
|
|
6
|
-
this.timeout = timeout;
|
|
7
|
-
this.isAlive = true;
|
|
8
|
-
this._mainStream = mainStream;
|
|
9
|
-
this._mainStream.setConsumer(this.id, this);
|
|
10
|
-
this.streamName = streamName;
|
|
11
|
-
this.usabilityMode = !!usabilityMode;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
getStats() {
|
|
15
|
-
let stats = {
|
|
16
|
-
id: this.id,
|
|
17
|
-
backpressure: this._backpressure,
|
|
18
|
-
stream: this.streamName
|
|
19
|
-
};
|
|
20
|
-
if (this.timeout != null) {
|
|
21
|
-
stats.timeout = this.timeout;
|
|
22
|
-
}
|
|
23
|
-
return stats;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
_resetBackpressure() {
|
|
27
|
-
this._backpressure = 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
applyBackpressure(packet) {
|
|
31
|
-
this._backpressure++;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
releaseBackpressure(packet) {
|
|
35
|
-
this._backpressure--;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
getBackpressure() {
|
|
39
|
-
return this._backpressure;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
clearActiveTimeout() {
|
|
43
|
-
clearTimeout(this._timeoutId);
|
|
44
|
-
delete this._timeoutId;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
write(packet) {
|
|
48
|
-
if (packet.done || packet.value.stream === this.streamName) {
|
|
49
|
-
if (this._timeoutId !== undefined) {
|
|
50
|
-
this.clearActiveTimeout(packet);
|
|
51
|
-
}
|
|
52
|
-
this.applyBackpressure(packet);
|
|
53
|
-
}
|
|
54
|
-
if (this._resolve) {
|
|
55
|
-
this._resolve();
|
|
56
|
-
delete this._resolve;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
kill(value) {
|
|
61
|
-
this._killPacket = {value, done: true};
|
|
62
|
-
if (this._timeoutId !== undefined) {
|
|
63
|
-
this.clearActiveTimeout(this._killPacket);
|
|
64
|
-
}
|
|
65
|
-
this._destroy();
|
|
66
|
-
|
|
67
|
-
if (this._resolve) {
|
|
68
|
-
this._resolve();
|
|
69
|
-
delete this._resolve;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
_destroy() {
|
|
74
|
-
this.isAlive = false;
|
|
75
|
-
this._resetBackpressure();
|
|
76
|
-
this._mainStream.removeConsumer(this.id);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async _waitForNextItem(timeout) {
|
|
80
|
-
return new Promise((resolve, reject) => {
|
|
81
|
-
this._resolve = resolve;
|
|
82
|
-
let timeoutId;
|
|
83
|
-
if (timeout != null) {
|
|
84
|
-
// Create the error object in the outer scope in order
|
|
85
|
-
// to get the full stack trace.
|
|
86
|
-
let error = new Error('Stream consumer iteration timed out');
|
|
87
|
-
(async () => {
|
|
88
|
-
let delay = wait(timeout);
|
|
89
|
-
timeoutId = delay.timeoutId;
|
|
90
|
-
await delay.promise;
|
|
91
|
-
error.name = 'TimeoutError';
|
|
92
|
-
delete this._resolve;
|
|
93
|
-
reject(error);
|
|
94
|
-
})();
|
|
95
|
-
}
|
|
96
|
-
this._timeoutId = timeoutId;
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async next() {
|
|
101
|
-
this._mainStream.setConsumer(this.id, this);
|
|
102
|
-
|
|
103
|
-
while (true) {
|
|
104
|
-
if (!this.currentNode.next) {
|
|
105
|
-
try {
|
|
106
|
-
await this._waitForNextItem(this.timeout);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
this._destroy();
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (this._killPacket) {
|
|
113
|
-
this._destroy();
|
|
114
|
-
let killPacket = this._killPacket;
|
|
115
|
-
delete this._killPacket;
|
|
116
|
-
|
|
117
|
-
return killPacket;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Skip over nodes which belong to different streams.
|
|
121
|
-
while (
|
|
122
|
-
this.currentNode.next?.data?.value &&
|
|
123
|
-
this.currentNode.next.data.value.stream !== this.streamName &&
|
|
124
|
-
this.currentNode.next.consumerId !== this.id &&
|
|
125
|
-
!this.currentNode.next.data.done
|
|
126
|
-
) {
|
|
127
|
-
this.currentNode = this.currentNode.next;
|
|
128
|
-
this.usabilityMode && await wait(0);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (!this.currentNode.next) {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
this.currentNode = this.currentNode.next;
|
|
136
|
-
|
|
137
|
-
this.releaseBackpressure(this.currentNode.data);
|
|
138
|
-
|
|
139
|
-
if (this.currentNode.data?.value?.data?.done) {
|
|
140
|
-
this._destroy();
|
|
141
|
-
return this.currentNode.data.value.data;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (this.currentNode.data.done) {
|
|
145
|
-
this._destroy();
|
|
146
|
-
return this.currentNode.data;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return this.currentNode.data.value.data;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return() {
|
|
154
|
-
delete this.currentNode;
|
|
155
|
-
this._destroy();
|
|
156
|
-
return {};
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
[Symbol.asyncIterator]() {
|
|
160
|
-
return this;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function wait(timeout) {
|
|
165
|
-
let timeoutId;
|
|
166
|
-
let promise = new Promise((resolve) => {
|
|
167
|
-
timeoutId = setTimeout(resolve, timeout);
|
|
168
|
-
});
|
|
169
|
-
return {timeoutId, promise};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
module.exports = StreamConsumer;
|