@shutterstock/p-map-iterable 1.1.1 → 1.2.0-prerelease.1
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 +79 -17
- package/dist/src/blocking-queue.js +6 -20
- package/dist/src/blocking-queue.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +4 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/iterable-mapper.d.ts +18 -13
- package/dist/src/iterable-mapper.js +28 -45
- package/dist/src/iterable-mapper.js.map +1 -1
- package/dist/src/iterable-queue-mapper-simple.d.ts +28 -21
- package/dist/src/iterable-queue-mapper-simple.js +29 -23
- package/dist/src/iterable-queue-mapper-simple.js.map +1 -1
- package/dist/src/iterable-queue-mapper.d.ts +18 -9
- package/dist/src/iterable-queue-mapper.js +17 -8
- package/dist/src/iterable-queue-mapper.js.map +1 -1
- package/dist/src/iterable-queue.js.map +1 -1
- package/dist/src/queue.js.map +1 -1
- package/package.json +25 -19
- package/dist/src/blocking-queue.d.ts.map +0 -1
- package/dist/src/blocking-queue.test.d.ts +0 -2
- package/dist/src/blocking-queue.test.d.ts.map +0 -1
- package/dist/src/blocking-queue.test.js +0 -174
- package/dist/src/blocking-queue.test.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/iterable-mapper.d.ts.map +0 -1
- package/dist/src/iterable-mapper.test.d.ts +0 -2
- package/dist/src/iterable-mapper.test.d.ts.map +0 -1
- package/dist/src/iterable-mapper.test.js +0 -898
- package/dist/src/iterable-mapper.test.js.map +0 -1
- package/dist/src/iterable-queue-mapper-simple.d.ts.map +0 -1
- package/dist/src/iterable-queue-mapper-simple.test.d.ts +0 -2
- package/dist/src/iterable-queue-mapper-simple.test.d.ts.map +0 -1
- package/dist/src/iterable-queue-mapper-simple.test.js +0 -102
- package/dist/src/iterable-queue-mapper-simple.test.js.map +0 -1
- package/dist/src/iterable-queue-mapper.d.ts.map +0 -1
- package/dist/src/iterable-queue-mapper.test.d.ts +0 -2
- package/dist/src/iterable-queue-mapper.test.d.ts.map +0 -1
- package/dist/src/iterable-queue-mapper.test.js +0 -119
- package/dist/src/iterable-queue-mapper.test.js.map +0 -1
- package/dist/src/iterable-queue.d.ts.map +0 -1
- package/dist/src/iterable-queue.test.d.ts +0 -2
- package/dist/src/iterable-queue.test.d.ts.map +0 -1
- package/dist/src/iterable-queue.test.js +0 -143
- package/dist/src/iterable-queue.test.js.map +0 -1
- package/dist/src/queue.d.ts.map +0 -1
- package/dist/src/queue.test.d.ts +0 -2
- package/dist/src/queue.test.d.ts.map +0 -1
- package/dist/src/queue.test.js +0 -75
- package/dist/src/queue.test.js.map +0 -1
|
@@ -6,22 +6,25 @@ type Errors<T> = {
|
|
|
6
6
|
} | Error;
|
|
7
7
|
}[];
|
|
8
8
|
/**
|
|
9
|
-
* Options for IterableQueueMapperSimple
|
|
9
|
+
* Options for `IterableQueueMapperSimple`, also exported as `WorkerQueueOptions`.
|
|
10
10
|
*/
|
|
11
11
|
export type IterableQueueMapperSimpleOptions = Pick<IterableMapperOptions, 'concurrency'>;
|
|
12
12
|
/**
|
|
13
13
|
* Accepts queue items via `enqueue` and calls the `mapper` on them
|
|
14
14
|
* with specified `concurrency`, discards the results, and accumulates
|
|
15
|
-
* exceptions in the `errors` property.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* exceptions in the `errors` property. Await `enqueue()` for producer
|
|
16
|
+
* backpressure while the worker callback runs asynchronously.
|
|
17
|
+
*
|
|
18
|
+
* Also exported as `WorkerQueue`, with the same constructor and instance types.
|
|
19
|
+
* Each input uses the same worker callback supplied at construction. Asynchronous
|
|
20
|
+
* work overlaps in the current JavaScript process, and results are consumed internally.
|
|
18
21
|
*
|
|
19
22
|
* @remarks
|
|
20
23
|
*
|
|
21
|
-
* ### Typical Use
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
24
|
+
* ### Typical Use Cases
|
|
25
|
+
* - Running background status checks or other queued work through a fixed callback
|
|
26
|
+
* - Sending items to an async I/O destination
|
|
27
|
+
* - Processing items whose return values can be discarded (if results are needed, use `IterableQueueMapper` / `MappingQueue`)
|
|
25
28
|
*
|
|
26
29
|
* ### Error Handling
|
|
27
30
|
* The mapper should ideally handle all errors internally to enable error handling
|
|
@@ -31,7 +34,7 @@ export type IterableQueueMapperSimpleOptions = Pick<IterableMapperOptions, 'conc
|
|
|
31
34
|
* - Errors can be checked/handled during processing via the `errors` property
|
|
32
35
|
*
|
|
33
36
|
* Key Differences from `IterableQueueMapper`:
|
|
34
|
-
* - `maxUnread`
|
|
37
|
+
* - The internal `maxUnread` limit equals `concurrency`; only `concurrency` is configurable
|
|
35
38
|
* - Results are automatically iterated and discarded (all work should happen in mapper)
|
|
36
39
|
* - Errors are collected rather than thrown (available via errors property)
|
|
37
40
|
*
|
|
@@ -39,7 +42,11 @@ export type IterableQueueMapperSimpleOptions = Pick<IterableMapperOptions, 'conc
|
|
|
39
42
|
* - Items are added to the queue via the `await enqueue()` method
|
|
40
43
|
* - Check `errors` property to see if any errors occurred, stop if desired
|
|
41
44
|
* - IMPORTANT: `await enqueue()` method will block until a slot is available, if queue is full
|
|
42
|
-
* -
|
|
45
|
+
* - After the last awaited enqueue, await `onIdle()` to close input permanently and finish accepted work
|
|
46
|
+
* - Subsequent enqueues reject, so `onIdle()` is a final shutdown operation
|
|
47
|
+
* - Worker failures are collected in `errors`; they do not reject `onIdle()`
|
|
48
|
+
* - Await each enqueue for producer backpressure; unawaited calls can accumulate pending inputs
|
|
49
|
+
* - Admission limits for event callbacks, cancellation, and per-item completion handles belong to the caller
|
|
43
50
|
*
|
|
44
51
|
* Note: the name is somewhat of a misnomer as this wraps `IterableQueueMapper`
|
|
45
52
|
* but is not itself an `Iterable`.
|
|
@@ -70,7 +77,7 @@ export declare class IterableQueueMapperSimple<Element> {
|
|
|
70
77
|
private discardResults;
|
|
71
78
|
private worker;
|
|
72
79
|
/**
|
|
73
|
-
* Accumulated errors from
|
|
80
|
+
* Accumulated errors from the worker callback.
|
|
74
81
|
*
|
|
75
82
|
* @remarks
|
|
76
83
|
*
|
|
@@ -83,24 +90,24 @@ export declare class IterableQueueMapperSimple<Element> {
|
|
|
83
90
|
*/
|
|
84
91
|
get errors(): Errors<Element>;
|
|
85
92
|
/**
|
|
86
|
-
* Accept
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* the caller from getting too far ahead.
|
|
93
|
+
* Accept an input for the worker callback, waiting until it can be accepted.
|
|
94
|
+
* Resolves on acceptance, rather than completion of this item's work.
|
|
95
|
+
* Await each enqueue for producer backpressure.
|
|
90
96
|
*
|
|
91
|
-
*
|
|
92
|
-
* @param item
|
|
97
|
+
* After the last enqueue, await `onIdle()` to close input and finish accepted work.
|
|
98
|
+
* @param item Input for the worker callback
|
|
93
99
|
*/
|
|
94
100
|
enqueue(item: Element): Promise<void>;
|
|
95
101
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
102
|
+
* Permanently close input and wait for all accepted work to finish.
|
|
103
|
+
* Call after the last awaited enqueue. Subsequent enqueues reject.
|
|
104
|
+
* Worker failures are available in `errors` instead of rejecting this wait.
|
|
98
105
|
*/
|
|
99
106
|
onIdle(): Promise<void>;
|
|
100
107
|
/**
|
|
101
|
-
* Indicates
|
|
108
|
+
* Indicates whether final shutdown has completed.
|
|
102
109
|
*
|
|
103
|
-
* @returns true
|
|
110
|
+
* @returns true after `onIdle()` has finished all accepted work and closed input
|
|
104
111
|
*/
|
|
105
112
|
get isIdle(): boolean;
|
|
106
113
|
}
|
|
@@ -6,16 +6,19 @@ const NoResult = Symbol('noresult');
|
|
|
6
6
|
/**
|
|
7
7
|
* Accepts queue items via `enqueue` and calls the `mapper` on them
|
|
8
8
|
* with specified `concurrency`, discards the results, and accumulates
|
|
9
|
-
* exceptions in the `errors` property.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* exceptions in the `errors` property. Await `enqueue()` for producer
|
|
10
|
+
* backpressure while the worker callback runs asynchronously.
|
|
11
|
+
*
|
|
12
|
+
* Also exported as `WorkerQueue`, with the same constructor and instance types.
|
|
13
|
+
* Each input uses the same worker callback supplied at construction. Asynchronous
|
|
14
|
+
* work overlaps in the current JavaScript process, and results are consumed internally.
|
|
12
15
|
*
|
|
13
16
|
* @remarks
|
|
14
17
|
*
|
|
15
|
-
* ### Typical Use
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
18
|
+
* ### Typical Use Cases
|
|
19
|
+
* - Running background status checks or other queued work through a fixed callback
|
|
20
|
+
* - Sending items to an async I/O destination
|
|
21
|
+
* - Processing items whose return values can be discarded (if results are needed, use `IterableQueueMapper` / `MappingQueue`)
|
|
19
22
|
*
|
|
20
23
|
* ### Error Handling
|
|
21
24
|
* The mapper should ideally handle all errors internally to enable error handling
|
|
@@ -25,7 +28,7 @@ const NoResult = Symbol('noresult');
|
|
|
25
28
|
* - Errors can be checked/handled during processing via the `errors` property
|
|
26
29
|
*
|
|
27
30
|
* Key Differences from `IterableQueueMapper`:
|
|
28
|
-
* - `maxUnread`
|
|
31
|
+
* - The internal `maxUnread` limit equals `concurrency`; only `concurrency` is configurable
|
|
29
32
|
* - Results are automatically iterated and discarded (all work should happen in mapper)
|
|
30
33
|
* - Errors are collected rather than thrown (available via errors property)
|
|
31
34
|
*
|
|
@@ -33,7 +36,11 @@ const NoResult = Symbol('noresult');
|
|
|
33
36
|
* - Items are added to the queue via the `await enqueue()` method
|
|
34
37
|
* - Check `errors` property to see if any errors occurred, stop if desired
|
|
35
38
|
* - IMPORTANT: `await enqueue()` method will block until a slot is available, if queue is full
|
|
36
|
-
* -
|
|
39
|
+
* - After the last awaited enqueue, await `onIdle()` to close input permanently and finish accepted work
|
|
40
|
+
* - Subsequent enqueues reject, so `onIdle()` is a final shutdown operation
|
|
41
|
+
* - Worker failures are collected in `errors`; they do not reject `onIdle()`
|
|
42
|
+
* - Await each enqueue for producer backpressure; unawaited calls can accumulate pending inputs
|
|
43
|
+
* - Admission limits for event callbacks, cancellation, and per-item completion handles belong to the caller
|
|
37
44
|
*
|
|
38
45
|
* Note: the name is somewhat of a misnomer as this wraps `IterableQueueMapper`
|
|
39
46
|
* but is not itself an `Iterable`.
|
|
@@ -66,7 +73,6 @@ class IterableQueueMapperSimple {
|
|
|
66
73
|
this._done = this.discardResults();
|
|
67
74
|
}
|
|
68
75
|
async discardResults() {
|
|
69
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
70
76
|
let item = await this._writer.next();
|
|
71
77
|
while (item.done !== true) {
|
|
72
78
|
// Just discard all the results
|
|
@@ -85,7 +91,7 @@ class IterableQueueMapperSimple {
|
|
|
85
91
|
return NoResult;
|
|
86
92
|
}
|
|
87
93
|
/**
|
|
88
|
-
* Accumulated errors from
|
|
94
|
+
* Accumulated errors from the worker callback.
|
|
89
95
|
*
|
|
90
96
|
* @remarks
|
|
91
97
|
*
|
|
@@ -100,34 +106,34 @@ class IterableQueueMapperSimple {
|
|
|
100
106
|
return this._errors;
|
|
101
107
|
}
|
|
102
108
|
/**
|
|
103
|
-
* Accept
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* the caller from getting too far ahead.
|
|
109
|
+
* Accept an input for the worker callback, waiting until it can be accepted.
|
|
110
|
+
* Resolves on acceptance, rather than completion of this item's work.
|
|
111
|
+
* Await each enqueue for producer backpressure.
|
|
107
112
|
*
|
|
108
|
-
*
|
|
109
|
-
* @param item
|
|
113
|
+
* After the last enqueue, await `onIdle()` to close input and finish accepted work.
|
|
114
|
+
* @param item Input for the worker callback
|
|
110
115
|
*/
|
|
111
116
|
async enqueue(item) {
|
|
112
|
-
// Return immediately or wait for
|
|
117
|
+
// Return immediately or wait for the underlying mapping queue to accept the input
|
|
113
118
|
await this._writer.enqueue(item);
|
|
114
119
|
}
|
|
115
120
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
121
|
+
* Permanently close input and wait for all accepted work to finish.
|
|
122
|
+
* Call after the last awaited enqueue. Subsequent enqueues reject.
|
|
123
|
+
* Worker failures are available in `errors` instead of rejecting this wait.
|
|
118
124
|
*/
|
|
119
125
|
async onIdle() {
|
|
120
126
|
if (this._isIdle)
|
|
121
127
|
return;
|
|
122
|
-
// Indicate that
|
|
128
|
+
// Indicate that no more inputs will be enqueued
|
|
123
129
|
this._writer.done();
|
|
124
130
|
await this._done;
|
|
125
131
|
this._isIdle = true;
|
|
126
132
|
}
|
|
127
133
|
/**
|
|
128
|
-
* Indicates
|
|
134
|
+
* Indicates whether final shutdown has completed.
|
|
129
135
|
*
|
|
130
|
-
* @returns true
|
|
136
|
+
* @returns true after `onIdle()` has finished all accepted work and closed input
|
|
131
137
|
*/
|
|
132
138
|
get isIdle() {
|
|
133
139
|
return this._isIdle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-queue-mapper-simple.js","sourceRoot":"","sources":["../../src/iterable-queue-mapper-simple.ts"],"names":[],"mappings":";;;AACA,mEAA8D;AAK9D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAOpC
|
|
1
|
+
{"version":3,"file":"iterable-queue-mapper-simple.js","sourceRoot":"","sources":["../../src/iterable-queue-mapper-simple.ts"],"names":[],"mappings":";;;AACA,mEAA8D;AAK9D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAOpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAa,yBAAyB;IAOpC;;;;;;;;;;OAUG;IACH,YAAY,MAA6B,EAAE,UAA4C,EAAE;QAhBxE,YAAO,GAAoB,EAAE,CAAC;QAGvC,YAAO,GAAG,KAAK,CAAC;QActB,MAAM,EAAE,WAAW,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;QAEpC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,IAAI,2CAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;QAE7F,6BAA6B;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IACrC,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,IAAI,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC1B,+BAA+B;YAC/B,oEAAoE;YACpE,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,IAAa,EAAE,KAAa;QAC/C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAChC,8DAA8D;QAChE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,IAAa;QAChC,kFAAkF;QAClF,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM;QACjB,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAEzB,gDAAgD;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEpB,MAAM,IAAI,CAAC,KAAK,CAAC;QAEjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AArGD,8DAqGC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IterableMapperOptions, Mapper } from './iterable-mapper';
|
|
2
2
|
/**
|
|
3
|
-
* Options for IterableQueueMapper
|
|
3
|
+
* Options for `IterableQueueMapper`, also exported as `MappingQueueOptions`.
|
|
4
4
|
*/
|
|
5
5
|
export type IterableQueueMapperOptions = IterableMapperOptions;
|
|
6
6
|
/**
|
|
@@ -9,12 +9,16 @@ export type IterableQueueMapperOptions = IterableMapperOptions;
|
|
|
9
9
|
* of `maxUnread` size, before being iterated / read by the caller.
|
|
10
10
|
* The `enqueue` method will block if the queue is full, until an item is read.
|
|
11
11
|
*
|
|
12
|
+
* Also exported as `MappingQueue`, with the same constructor and instance types.
|
|
13
|
+
* Each input uses the same callback supplied at construction; results are exposed
|
|
14
|
+
* through the async iterator as mapping completes.
|
|
15
|
+
*
|
|
12
16
|
* @remarks
|
|
13
17
|
*
|
|
14
|
-
* ### Typical Use
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
+
* ### Typical Use Cases
|
|
19
|
+
* - Enqueuing capability probes or metadata lookups as inputs become available
|
|
20
|
+
* - Sending items to an async I/O destination and consuming its acknowledgements
|
|
21
|
+
* - Consuming mapped results in a subsequent step (if results can be discarded, use `IterableQueueMapperSimple` / `WorkerQueue`)
|
|
18
22
|
* - Prevents the producer from racing ahead of the consumer if `maxUnread` is reached
|
|
19
23
|
*
|
|
20
24
|
* ### Error Handling
|
|
@@ -33,8 +37,10 @@ export type IterableQueueMapperOptions = IterableMapperOptions;
|
|
|
33
37
|
* ### Usage
|
|
34
38
|
* - Items are added to the queue via the `await enqueue()` method
|
|
35
39
|
* - IMPORTANT: `await enqueue()` method will block until a slot is available, if queue is full
|
|
36
|
-
* -
|
|
37
|
-
* -
|
|
40
|
+
* - Produce inputs and consume results concurrently so the result buffer can drain
|
|
41
|
+
* - Call `done()` after the last awaited enqueue, then finish consuming the iterator
|
|
42
|
+
* - `enqueue()` confirms acceptance of an input; `done()` closes input without waiting for work to finish
|
|
43
|
+
* - Await each enqueue for producer backpressure; unawaited calls can accumulate pending inputs
|
|
38
44
|
*
|
|
39
45
|
* @category Enqueue Input
|
|
40
46
|
*
|
|
@@ -62,7 +68,9 @@ export declare class IterableQueueMapper<Element, NewElement> implements AsyncIt
|
|
|
62
68
|
*/
|
|
63
69
|
next(): Promise<IteratorResult<NewElement>>;
|
|
64
70
|
/**
|
|
65
|
-
* Add an item to the queue,
|
|
71
|
+
* Add an item to the queue, waiting until it can be accepted.
|
|
72
|
+
* Resolves on acceptance, rather than completion of the mapper for this item.
|
|
73
|
+
* Await each enqueue while consuming results concurrently for producer backpressure.
|
|
66
74
|
*
|
|
67
75
|
* @param item Element to add
|
|
68
76
|
*/
|
|
@@ -70,7 +78,8 @@ export declare class IterableQueueMapper<Element, NewElement> implements AsyncIt
|
|
|
70
78
|
/**
|
|
71
79
|
* Indicate that no more items will be enqueued.
|
|
72
80
|
*
|
|
73
|
-
*
|
|
81
|
+
* Call after the last awaited enqueue. Finish consuming the async iterator
|
|
82
|
+
* to wait for mapped results; this method does not wait for processing to finish.
|
|
74
83
|
*/
|
|
75
84
|
done(): void;
|
|
76
85
|
}
|
|
@@ -12,12 +12,16 @@ const iterable_queue_1 = require("./iterable-queue");
|
|
|
12
12
|
* of `maxUnread` size, before being iterated / read by the caller.
|
|
13
13
|
* The `enqueue` method will block if the queue is full, until an item is read.
|
|
14
14
|
*
|
|
15
|
+
* Also exported as `MappingQueue`, with the same constructor and instance types.
|
|
16
|
+
* Each input uses the same callback supplied at construction; results are exposed
|
|
17
|
+
* through the async iterator as mapping completes.
|
|
18
|
+
*
|
|
15
19
|
* @remarks
|
|
16
20
|
*
|
|
17
|
-
* ### Typical Use
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
21
|
+
* ### Typical Use Cases
|
|
22
|
+
* - Enqueuing capability probes or metadata lookups as inputs become available
|
|
23
|
+
* - Sending items to an async I/O destination and consuming its acknowledgements
|
|
24
|
+
* - Consuming mapped results in a subsequent step (if results can be discarded, use `IterableQueueMapperSimple` / `WorkerQueue`)
|
|
21
25
|
* - Prevents the producer from racing ahead of the consumer if `maxUnread` is reached
|
|
22
26
|
*
|
|
23
27
|
* ### Error Handling
|
|
@@ -36,8 +40,10 @@ const iterable_queue_1 = require("./iterable-queue");
|
|
|
36
40
|
* ### Usage
|
|
37
41
|
* - Items are added to the queue via the `await enqueue()` method
|
|
38
42
|
* - IMPORTANT: `await enqueue()` method will block until a slot is available, if queue is full
|
|
39
|
-
* -
|
|
40
|
-
* -
|
|
43
|
+
* - Produce inputs and consume results concurrently so the result buffer can drain
|
|
44
|
+
* - Call `done()` after the last awaited enqueue, then finish consuming the iterator
|
|
45
|
+
* - `enqueue()` confirms acceptance of an input; `done()` closes input without waiting for work to finish
|
|
46
|
+
* - Await each enqueue for producer backpressure; unawaited calls can accumulate pending inputs
|
|
41
47
|
*
|
|
42
48
|
* @category Enqueue Input
|
|
43
49
|
*
|
|
@@ -72,7 +78,9 @@ class IterableQueueMapper {
|
|
|
72
78
|
return this._iterableMapper.next();
|
|
73
79
|
}
|
|
74
80
|
/**
|
|
75
|
-
* Add an item to the queue,
|
|
81
|
+
* Add an item to the queue, waiting until it can be accepted.
|
|
82
|
+
* Resolves on acceptance, rather than completion of the mapper for this item.
|
|
83
|
+
* Await each enqueue while consuming results concurrently for producer backpressure.
|
|
76
84
|
*
|
|
77
85
|
* @param item Element to add
|
|
78
86
|
*/
|
|
@@ -82,7 +90,8 @@ class IterableQueueMapper {
|
|
|
82
90
|
/**
|
|
83
91
|
* Indicate that no more items will be enqueued.
|
|
84
92
|
*
|
|
85
|
-
*
|
|
93
|
+
* Call after the last awaited enqueue. Finish consuming the async iterator
|
|
94
|
+
* to wait for mapped results; this method does not wait for processing to finish.
|
|
86
95
|
*/
|
|
87
96
|
done() {
|
|
88
97
|
this._sourceIterable.done();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-queue-mapper.js","sourceRoot":"","sources":["../../src/iterable-queue-mapper.ts"],"names":[],"mappings":";;;AAAA,EAAE;AACF,sGAAsG;AACtG,EAAE;AACF,uDAAkF;AAClF,qDAAiD;AAOjD
|
|
1
|
+
{"version":3,"file":"iterable-queue-mapper.js","sourceRoot":"","sources":["../../src/iterable-queue-mapper.ts"],"names":[],"mappings":";;;AAAA,EAAE;AACF,sGAAsG;AACtG,EAAE;AACF,uDAAkF;AAClF,qDAAiD;AAOjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAa,mBAAmB;IAK9B;;;;;;;;;OASG;IACH,YAAY,MAAmC,EAAE,UAAsC,EAAE;QACvF,IAAI,CAAC,eAAe,GAAG,IAAI,8BAAa,CAAC;YACvC,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;QACH,IAAI,CAAC,eAAe,GAAG,IAAI,gCAAc,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;IAEM,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI;QACf,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,OAAO,CAAC,IAAa;QAChC,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACI,IAAI;QACT,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;CACF;AAvDD,kDAuDC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterable-queue.js","sourceRoot":"","sources":["../../src/iterable-queue.ts"],"names":[],"mappings":";;;AAAA,qDAAuE;AAIvE;;;;GAIG;AACH,MAAa,aACX,SAAQ,8BAAsB;IAG9B;;;OAGG;IACH,YAAY,UAAgC,EAAE;QAC5C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAEM,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,IAAI;QACf,6BAA6B;QAC7B,MAAM,IAAI,GAAwB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAEvD,IAAI,IAAI,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"iterable-queue.js","sourceRoot":"","sources":["../../src/iterable-queue.ts"],"names":[],"mappings":";;;AAAA,qDAAuE;AAIvE;;;;GAIG;AACH,MAAa,aACX,SAAQ,8BAAsB;IAG9B;;;OAGG;IACH,YAAY,UAAgC,EAAE;QAC5C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAEM,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,IAAI;QACf,6BAA6B;QAC7B,MAAM,IAAI,GAAwB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAEvD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,yCAAyC;YACzC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACtC,CAAC;CACF;AAjCD,sCAiCC"}
|
package/dist/src/queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/queue.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,kGAAkG;AAClG,EAAE;;;AAEF;;;;GAIG;AACH,MAAa,KAAK;IAAlB;QACU,WAAM,GAA2B,EAAE,CAAC;QACpC,UAAK,GAAG,CAAC,CAAC;QACV,UAAK,GAAG,CAAC,CAAC;IAsBpB,CAAC;IApBC,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACjC,CAAC;IAED,0CAA0C;IACnC,OAAO,CAAC,OAAU;QACvB,IAAI,OAAO,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/queue.ts"],"names":[],"mappings":";AAAA,EAAE;AACF,kGAAkG;AAClG,EAAE;;;AAEF;;;;GAIG;AACH,MAAa,KAAK;IAAlB;QACU,WAAM,GAA2B,EAAE,CAAC;QACpC,UAAK,GAAG,CAAC,CAAC;QACV,UAAK,GAAG,CAAC,CAAC;IAsBpB,CAAC;IApBC,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACjC,CAAC;IAED,0CAA0C;IACnC,OAAO,CAAC,OAAU;QACvB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;IACtC,CAAC;IAED,yCAAyC;IAClC,OAAO;QACZ,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAEhD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAzBD,sBAyBC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shutterstock/p-map-iterable",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"
|
|
3
|
+
"version": "1.2.0-prerelease.1",
|
|
4
|
+
"packageManager": "pnpm@12.7.0",
|
|
5
|
+
"description": "Concurrent mapping and queued background work with backpressure, streaming results, and collected errors",
|
|
5
6
|
"main": "dist/src/index.js",
|
|
6
7
|
"types": "dist/src/index.d.ts",
|
|
7
8
|
"publishConfig": {
|
|
@@ -24,14 +25,15 @@
|
|
|
24
25
|
"AsyncIterator"
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
|
-
"build": "tsc --build tsconfig.json && echo 'examples/\n*.tsbuildinfo' > dist/.npmignore",
|
|
28
|
+
"build": "tsc --build tsconfig.json && echo 'examples/\n*.tsbuildinfo\n*.test.*\n*.d.ts.map' > dist/.npmignore",
|
|
28
29
|
"build:docs": "typedoc src/index.ts",
|
|
29
30
|
"example:iterable-mapper": "ts-node -r tsconfig-paths/register examples/iterable-mapper.ts",
|
|
30
31
|
"example:iterable-queue-mapper": "ts-node -r tsconfig-paths/register examples/iterable-queue-mapper.ts",
|
|
31
32
|
"example:iterable-queue-mapper-simple": "ts-node -r tsconfig-paths/register examples/iterable-queue-mapper-simple.ts",
|
|
33
|
+
"example:semantic-aliases": "ts-node -r tsconfig-paths/register examples/semantic-aliases.ts",
|
|
32
34
|
"test": "jest",
|
|
33
|
-
"lint": "eslint
|
|
34
|
-
"lint-and-fix": "eslint
|
|
35
|
+
"lint": "eslint .",
|
|
36
|
+
"lint-and-fix": "eslint . --fix"
|
|
35
37
|
},
|
|
36
38
|
"files": [
|
|
37
39
|
"dist/",
|
|
@@ -44,24 +46,28 @@
|
|
|
44
46
|
},
|
|
45
47
|
"license": "MIT",
|
|
46
48
|
"dependencies": {
|
|
47
|
-
"aggregate-error": "^3.
|
|
49
|
+
"aggregate-error": "^3.1.0"
|
|
48
50
|
},
|
|
49
51
|
"peerDependencies": {
|
|
50
|
-
"aggregate-error": "^3.
|
|
52
|
+
"aggregate-error": "^3.1.0"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"eslint": "^
|
|
57
|
-
"eslint
|
|
58
|
-
"eslint
|
|
59
|
-
"
|
|
60
|
-
"prettier": "^
|
|
61
|
-
"
|
|
62
|
-
"
|
|
55
|
+
"@eslint/js": "^10.0.1",
|
|
56
|
+
"@types/jest": "30.0.0",
|
|
57
|
+
"@types/node": "^26.6.3",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^8.70.1",
|
|
59
|
+
"@typescript-eslint/parser": "^8.70.1",
|
|
60
|
+
"eslint": "^10.11.0",
|
|
61
|
+
"eslint-config-prettier": "^10.1.8",
|
|
62
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
63
|
+
"globals": "^17.12.0",
|
|
64
|
+
"jest": "30.5.2",
|
|
65
|
+
"lcov-parse": "1.0.0",
|
|
66
|
+
"prettier": "^3.9.9",
|
|
67
|
+
"ts-jest": "29.4.14",
|
|
68
|
+
"ts-node": "10.9.2",
|
|
63
69
|
"tsconfig-paths": "4.2.0",
|
|
64
|
-
"typedoc": "^0.
|
|
65
|
-
"typescript": "
|
|
70
|
+
"typedoc": "^0.28.20",
|
|
71
|
+
"typescript": "6.0.3"
|
|
66
72
|
}
|
|
67
73
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocking-queue.d.ts","sourceRoot":"","sources":["../../src/blocking-queue.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAOD;;;;;;;GAOG;AACH,qBAAa,aAAa,CAAC,OAAO;IAChC,OAAO,CAAC,QAAQ,CAAiC;IAKjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+B;IAO5D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;IAO1E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0C;IAE1E,OAAO,CAAC,WAAW,CAAS;IAE5B;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;IAuB9C,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;;;OAIG;IACI,IAAI,IAAI,IAAI;IAcnB;;;;OAIG;IACU,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BlD;;;;OAIG;IACU,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAoCpD,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,SAAS;IAqCjB;;OAEG;YACW,YAAY;IAW1B;;OAEG;YACW,WAAW;CAU1B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blocking-queue.test.d.ts","sourceRoot":"","sources":["../../src/blocking-queue.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/// <reference types="jest" />
|
|
4
|
-
const blocking_queue_1 = require("./blocking-queue");
|
|
5
|
-
describe('BlockingQueue', () => {
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
// nothing
|
|
8
|
-
});
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
jest.clearAllMocks();
|
|
11
|
-
});
|
|
12
|
-
describe('maxUnread: 0', () => {
|
|
13
|
-
it('single item enqueue/dequeue works', async () => {
|
|
14
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 0 });
|
|
15
|
-
setTimeout(() => {
|
|
16
|
-
void queue.enqueue(1);
|
|
17
|
-
}, 1000);
|
|
18
|
-
const item = await queue.dequeue();
|
|
19
|
-
queue.done();
|
|
20
|
-
expect(item).toBe(1);
|
|
21
|
-
});
|
|
22
|
-
it('dequeue after done does not hang', async () => {
|
|
23
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 0 });
|
|
24
|
-
setTimeout(() => {
|
|
25
|
-
void queue.enqueue(1);
|
|
26
|
-
}, 1000);
|
|
27
|
-
const item = await queue.dequeue();
|
|
28
|
-
queue.done();
|
|
29
|
-
await queue.dequeue();
|
|
30
|
-
expect(item).toBe(1);
|
|
31
|
-
});
|
|
32
|
-
it('enqueue after done throws', async () => {
|
|
33
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 0 });
|
|
34
|
-
setTimeout(() => {
|
|
35
|
-
void queue.enqueue(1);
|
|
36
|
-
}, 1000);
|
|
37
|
-
const item = await queue.dequeue();
|
|
38
|
-
queue.done();
|
|
39
|
-
await expect(async () => queue.enqueue(2)).rejects.toThrowError('`enqueue` called after `done` called');
|
|
40
|
-
expect(item).toBe(1);
|
|
41
|
-
});
|
|
42
|
-
it('balanced enqueue/dequeue works', async () => {
|
|
43
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 0 });
|
|
44
|
-
const writers = [];
|
|
45
|
-
writers.push(queue.enqueue(1));
|
|
46
|
-
writers.push(queue.enqueue(2));
|
|
47
|
-
const readers = [];
|
|
48
|
-
readers.push(queue.dequeue());
|
|
49
|
-
readers.push(queue.dequeue());
|
|
50
|
-
await Promise.all(writers);
|
|
51
|
-
queue.done();
|
|
52
|
-
await Promise.all(readers);
|
|
53
|
-
expect(await readers[0]).toBe(1);
|
|
54
|
-
expect(await readers[1]).toBe(2);
|
|
55
|
-
});
|
|
56
|
-
it('full queue blocks enqueue until dequeue', async () => {
|
|
57
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
58
|
-
// Add first item
|
|
59
|
-
void queue.enqueue(1);
|
|
60
|
-
// Do not wait for second item to add (it will wait until an enqueue completes)
|
|
61
|
-
setTimeout(() => {
|
|
62
|
-
void queue.enqueue(2);
|
|
63
|
-
}, 2000);
|
|
64
|
-
const startTime = Date.now();
|
|
65
|
-
expect(await queue.dequeue()).toBe(1);
|
|
66
|
-
expect(Date.now() - startTime).toBeLessThan(2000);
|
|
67
|
-
expect(await queue.dequeue()).toBe(2);
|
|
68
|
-
expect(Math.ceil(Date.now() - startTime)).toBeGreaterThanOrEqual(2000);
|
|
69
|
-
queue.done();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
describe('maxUnread: 1', () => {
|
|
73
|
-
it('single item enqueue/dequeue works', async () => {
|
|
74
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
75
|
-
await queue.enqueue(1);
|
|
76
|
-
const item = await queue.dequeue();
|
|
77
|
-
queue.done();
|
|
78
|
-
expect(item).toBe(1);
|
|
79
|
-
});
|
|
80
|
-
it('dequeue after done does not hang', async () => {
|
|
81
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
82
|
-
await queue.enqueue(1);
|
|
83
|
-
const item = await queue.dequeue();
|
|
84
|
-
queue.done();
|
|
85
|
-
await queue.dequeue();
|
|
86
|
-
expect(item).toBe(1);
|
|
87
|
-
});
|
|
88
|
-
it('dequeue after done and empty does not hang', async () => {
|
|
89
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
90
|
-
await queue.enqueue(1);
|
|
91
|
-
const item = await queue.dequeue();
|
|
92
|
-
queue.done();
|
|
93
|
-
await queue.dequeue();
|
|
94
|
-
expect(item).toBe(1);
|
|
95
|
-
await queue.dequeue();
|
|
96
|
-
});
|
|
97
|
-
it('enqueue after done throws', async () => {
|
|
98
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
99
|
-
await queue.enqueue(1);
|
|
100
|
-
const item = await queue.dequeue();
|
|
101
|
-
queue.done();
|
|
102
|
-
await expect(async () => queue.enqueue(2)).rejects.toThrowError('`enqueue` called after `done` called');
|
|
103
|
-
expect(item).toBe(1);
|
|
104
|
-
});
|
|
105
|
-
it('balanced enqueue/dequeue works', async () => {
|
|
106
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
107
|
-
const writers = [];
|
|
108
|
-
writers.push(queue.enqueue(1));
|
|
109
|
-
writers.push(queue.enqueue(2));
|
|
110
|
-
const readers = [];
|
|
111
|
-
readers.push(queue.dequeue());
|
|
112
|
-
readers.push(queue.dequeue());
|
|
113
|
-
await Promise.all(writers);
|
|
114
|
-
queue.done();
|
|
115
|
-
await Promise.all(readers);
|
|
116
|
-
expect(await readers[0]).toBe(1);
|
|
117
|
-
expect(await readers[1]).toBe(2);
|
|
118
|
-
});
|
|
119
|
-
it('more dequeue than enqueue works', async () => {
|
|
120
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
121
|
-
const writers = [];
|
|
122
|
-
writers.push(queue.enqueue(1));
|
|
123
|
-
writers.push(queue.enqueue(2));
|
|
124
|
-
const readers = [];
|
|
125
|
-
readers.push(queue.dequeue());
|
|
126
|
-
readers.push(queue.dequeue());
|
|
127
|
-
readers.push(queue.dequeue());
|
|
128
|
-
readers.push(queue.dequeue());
|
|
129
|
-
await Promise.all(writers);
|
|
130
|
-
queue.done();
|
|
131
|
-
await Promise.all(readers);
|
|
132
|
-
expect(await readers[0]).toBe(1);
|
|
133
|
-
expect(await readers[1]).toBe(2);
|
|
134
|
-
expect(await readers[2]).toBeUndefined();
|
|
135
|
-
expect(await readers[3]).toBeUndefined();
|
|
136
|
-
});
|
|
137
|
-
it('full queue blocks enqueue until dequeue', async () => {
|
|
138
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 1 });
|
|
139
|
-
// Wait for first item to add
|
|
140
|
-
await queue.enqueue(1);
|
|
141
|
-
// Do not wait for second item to add (it will wait until an enqueue completes)
|
|
142
|
-
setTimeout(() => {
|
|
143
|
-
void queue.enqueue(2);
|
|
144
|
-
}, 2000);
|
|
145
|
-
expect(await queue.dequeue()).toBe(1);
|
|
146
|
-
const startTime = Date.now();
|
|
147
|
-
expect(await queue.dequeue()).toBe(2);
|
|
148
|
-
const duration = Math.ceil(Date.now() - startTime);
|
|
149
|
-
expect(duration).toBeGreaterThanOrEqual(2000);
|
|
150
|
-
queue.done();
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
describe('maxUnread: 2', () => {
|
|
154
|
-
it('no reads until done works', async () => {
|
|
155
|
-
const queue = new blocking_queue_1.BlockingQueue({ maxUnread: 2 });
|
|
156
|
-
const writers = [];
|
|
157
|
-
writers.push(queue.enqueue(1));
|
|
158
|
-
writers.push(queue.enqueue(2));
|
|
159
|
-
await Promise.all(writers);
|
|
160
|
-
queue.done();
|
|
161
|
-
const readers = [];
|
|
162
|
-
readers.push(queue.dequeue());
|
|
163
|
-
readers.push(queue.dequeue());
|
|
164
|
-
readers.push(queue.dequeue());
|
|
165
|
-
readers.push(queue.dequeue());
|
|
166
|
-
await Promise.all(readers);
|
|
167
|
-
expect(await readers[0]).toBe(1);
|
|
168
|
-
expect(await readers[1]).toBe(2);
|
|
169
|
-
expect(await readers[2]).toBeUndefined();
|
|
170
|
-
expect(await readers[3]).toBeUndefined();
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
//# sourceMappingURL=blocking-queue.test.js.map
|