@shutterstock/p-map-iterable 0.0.1 → 1.0.10
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 +85 -76
- package/dist/{blocking-queue.d.ts → src/blocking-queue.d.ts} +12 -8
- package/dist/src/blocking-queue.d.ts.map +1 -0
- package/dist/{blocking-queue.js → src/blocking-queue.js} +28 -19
- package/dist/src/blocking-queue.js.map +1 -0
- package/dist/src/blocking-queue.test.d.ts.map +1 -0
- package/dist/src/blocking-queue.test.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/iterable-mapper.d.ts +125 -0
- package/dist/src/iterable-mapper.d.ts.map +1 -0
- package/dist/{iterable-mapper.js → src/iterable-mapper.js} +44 -26
- package/dist/src/iterable-mapper.js.map +1 -0
- package/dist/src/iterable-mapper.test.d.ts.map +1 -0
- package/dist/{iterable-mapper.test.js → src/iterable-mapper.test.js} +133 -283
- package/dist/src/iterable-mapper.test.js.map +1 -0
- package/dist/src/iterable-queue-mapper-simple.d.ts +93 -0
- package/dist/src/iterable-queue-mapper-simple.d.ts.map +1 -0
- package/dist/{iterable-queue-mapper-simple.js → src/iterable-queue-mapper-simple.js} +47 -10
- package/dist/src/iterable-queue-mapper-simple.js.map +1 -0
- package/dist/src/iterable-queue-mapper-simple.test.d.ts.map +1 -0
- package/dist/{iterable-queue-mapper-simple.test.js → src/iterable-queue-mapper-simple.test.js} +2 -2
- package/dist/src/iterable-queue-mapper-simple.test.js.map +1 -0
- package/dist/src/iterable-queue-mapper.d.ts +97 -0
- package/dist/src/iterable-queue-mapper.d.ts.map +1 -0
- package/dist/src/iterable-queue-mapper.js +97 -0
- package/dist/src/iterable-queue-mapper.js.map +1 -0
- package/dist/src/iterable-queue-mapper.test.d.ts.map +1 -0
- package/dist/{iterable-queue-mapper.test.js → src/iterable-queue-mapper.test.js} +15 -30
- package/dist/src/iterable-queue-mapper.test.js.map +1 -0
- package/dist/{iterable-queue.d.ts → src/iterable-queue.d.ts} +10 -13
- package/dist/src/iterable-queue.d.ts.map +1 -0
- package/dist/{iterable-queue.js → src/iterable-queue.js} +8 -1
- package/dist/src/iterable-queue.js.map +1 -0
- package/dist/src/iterable-queue.test.d.ts.map +1 -0
- package/dist/{iterable-queue.test.js → src/iterable-queue.test.js} +26 -56
- package/dist/src/iterable-queue.test.js.map +1 -0
- package/dist/{queue.d.ts → src/queue.d.ts} +5 -0
- package/dist/src/queue.d.ts.map +1 -0
- package/dist/{queue.js → src/queue.js} +5 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/{queue.test.d.ts.map → src/queue.test.d.ts.map} +1 -1
- package/dist/src/queue.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +24 -7
- package/dist/blocking-queue.d.ts.map +0 -1
- package/dist/blocking-queue.js.map +0 -1
- package/dist/blocking-queue.test.d.ts.map +0 -1
- package/dist/blocking-queue.test.js.map +0 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/iterable-mapper.d.ts +0 -104
- package/dist/iterable-mapper.d.ts.map +0 -1
- package/dist/iterable-mapper.js.map +0 -1
- package/dist/iterable-mapper.test.d.ts.map +0 -1
- package/dist/iterable-mapper.test.js.map +0 -1
- package/dist/iterable-queue-mapper-simple.d.ts +0 -49
- package/dist/iterable-queue-mapper-simple.d.ts.map +0 -1
- package/dist/iterable-queue-mapper-simple.js.map +0 -1
- package/dist/iterable-queue-mapper-simple.test.d.ts.map +0 -1
- package/dist/iterable-queue-mapper-simple.test.js.map +0 -1
- package/dist/iterable-queue-mapper.d.ts +0 -73
- package/dist/iterable-queue-mapper.d.ts.map +0 -1
- package/dist/iterable-queue-mapper.js +0 -72
- package/dist/iterable-queue-mapper.js.map +0 -1
- package/dist/iterable-queue-mapper.test.d.ts.map +0 -1
- package/dist/iterable-queue-mapper.test.js.map +0 -1
- package/dist/iterable-queue.d.ts.map +0 -1
- package/dist/iterable-queue.js.map +0 -1
- package/dist/iterable-queue.test.d.ts.map +0 -1
- package/dist/iterable-queue.test.js.map +0 -1
- package/dist/queue.d.ts.map +0 -1
- package/dist/queue.js.map +0 -1
- package/dist/queue.test.js.map +0 -1
- /package/dist/{blocking-queue.test.d.ts → src/blocking-queue.test.d.ts} +0 -0
- /package/dist/{blocking-queue.test.js → src/blocking-queue.test.js} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{iterable-mapper.test.d.ts → src/iterable-mapper.test.d.ts} +0 -0
- /package/dist/{iterable-queue-mapper-simple.test.d.ts → src/iterable-queue-mapper-simple.test.d.ts} +0 -0
- /package/dist/{iterable-queue-mapper.test.d.ts → src/iterable-queue-mapper.test.d.ts} +0 -0
- /package/dist/{iterable-queue.test.d.ts → src/iterable-queue.test.d.ts} +0 -0
- /package/dist/{queue.test.d.ts → src/queue.test.d.ts} +0 -0
- /package/dist/{queue.test.js → src/queue.test.js} +0 -0
package/README.md
CHANGED
|
@@ -1,29 +1,88 @@
|
|
|
1
|
-
[](https://opensource.org/licenses/MIT)
|
|
1
|
+
[](https://opensource.org/licenses/MIT) [](https://tech.shutterstock.com/p-map-iterable/) [](https://github.com/shutterstock/p-map-iterable/actions/workflows/ci.yml) [](https://github.com/shutterstock/p-map-iterable/actions/workflows/publish.yml) [](https://github.com/shutterstock/p-map-iterable/actions/workflows/docs.yml)
|
|
2
2
|
|
|
3
3
|
# Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@shutterstock/p-map-iterable` provides several classes that allow processing results of `p-map`-style mapper functions by iterating the results as they are completed, with back pressure to limit the number of items that are processed ahead of the consumer.
|
|
6
6
|
|
|
7
|
-
A common use case for `
|
|
7
|
+
A common use case for `@shutterstock/p-map-iterable` is as a "prefetcher" that will fetch, for example, AWS S3 files in an AWS Lambda function. By prefetching large files the consumer is able to use 100% of the paid-for Lambda CPU time for the JS thread, rather than waiting idle while the next file is fetched. The backpressure (set by `maxUnread`) prevents the prefetcher from consuming unlimited memory or disk space by racing ahead of the consumer.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
These classes will typically be helpful in batch or queue consumers, not as much in request/response services.
|
|
10
|
+
|
|
11
|
+
# Example Usage Scenario
|
|
12
|
+
|
|
13
|
+
- AWS Lambda function for Kafka or Kinesis stream processing
|
|
14
|
+
- Each invocation has a batch of, say, 100 records
|
|
15
|
+
- Each record points to a file on S3 that needs to be parsed, processed, then written back to S3
|
|
16
|
+
- The average file size is 50 MB, so these will take a few seconds to fetch and write
|
|
17
|
+
- The Lambda function has 1,769 MB of RAM which gives it 1 vCPU, allowing the JS thread to run at roughly 100% speed of 1 core
|
|
18
|
+
- If the code never waits to fetch or write files then the Lambda function will be able to use 100% of the paid-for CPU time
|
|
19
|
+
- If there is no back pressure then reading 100 * 50 MB files would fill up the default Lambda temp disk space of 512 MB OR would consume 5 GB of memory, which would cause the Lambda function to fail
|
|
20
|
+
- We can use `IterableMapper` to fetch up to 5 of the next files while the current file is being processed, then pause until the current file is processed and the next file is consumed
|
|
21
|
+
- We can also use `IterableQueueMapper.enqueue()` to write the files back to S3 without waiting for them to finish, unless we get more than, say, 3-4 files being uploaded at once, at which point we can pause until the current file is uploaded before we allow queuing another file for upload
|
|
22
|
+
- In the rare case that 3-4 files are uploading, but not yet finished, we would block on `.enqueue()` and not consume much CPU while waiting for at least 1 upload to finish
|
|
23
|
+
|
|
24
|
+
# Getting Started
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
The package is available on npm as [@shutterstock/p-map-iterable](https://www.npmjs.com/package/@shutterstock/p-map-iterable)
|
|
10
29
|
|
|
11
30
|
`npm i @shutterstock/p-map-iterable`
|
|
12
31
|
|
|
32
|
+
## Importing
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { IterableMapper, IterableQueueMapper, IterableQueueMapperSimple } from '@shutterstock/p-map-iterable';
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Documentation
|
|
39
|
+
|
|
40
|
+
After installing the package, you might want to look at our [API Documentation](https://tech.shutterstock.com/p-map-iterable/) to learn about all the features available.
|
|
41
|
+
|
|
42
|
+
# `p-map-iterable` vs `p-map` vs `p-queue`
|
|
43
|
+
|
|
44
|
+
These diagrams illustrate the differences in operation betweeen `p-map`, `p-queue`, and `p-map-iterable`.
|
|
45
|
+
|
|
46
|
+
## `p-map-iterable`
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
## `p-map`
|
|
51
|
+
|
|
52
|
+

|
|
53
|
+
|
|
54
|
+
## `p-queue`
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
13
58
|
# Features
|
|
14
59
|
|
|
15
|
-
-
|
|
60
|
+
- [IterableMapper](https://tech.shutterstock.com/p-map-iterable/classes/IterableMapper.html)
|
|
16
61
|
- Interface and concept based on: [p-map](https://github.com/sindresorhus/p-map)
|
|
17
62
|
- Allows a sync or async iterable input
|
|
18
63
|
- User supplied sync or async mapper function
|
|
19
64
|
- Exposes an async iterable interface for consuming mapped items
|
|
20
65
|
- Allows a maximum queue depth of mapped items - if the consumer stops consuming, the queue will fill up, at which point the mapper will stop being invoked until an item is consumed from the queue
|
|
21
66
|
- This allows mapping with back pressure so that the mapper does not consume unlimited resources (e.g. memory, disk, network, event loop time) by racing ahead of the consumer
|
|
22
|
-
-
|
|
67
|
+
- [IterableQueueMapper](https://tech.shutterstock.com/p-map-iterable/classes/IterableQueueMapper.html)
|
|
23
68
|
- Wraps `IterableMapper`
|
|
69
|
+
- Adds items to the queue via the `enqueue` method
|
|
70
|
+
- [IterableQueueMapperSimple](https://tech.shutterstock.com/p-map-iterable/classes/IterableQueueMapperSimple.html)
|
|
71
|
+
- Wraps `IterableQueueMapper`
|
|
24
72
|
- Discards results as they become available
|
|
25
73
|
- Exposes any accumulated errors through the `errors` property instead of throwing an `AggregateError`
|
|
26
|
-
-
|
|
74
|
+
- Not actually `Iterable` - May rename this before 1.0.0
|
|
75
|
+
|
|
76
|
+
## Lower Level Utilities
|
|
77
|
+
- [IterableQueue](https://tech.shutterstock.com/p-map-iterable/classes/IterableQueue.html)
|
|
78
|
+
- Lower level utility class
|
|
79
|
+
- Wraps `BlockingQueue`
|
|
80
|
+
- Exposes an async iterable interface for consuming items in the queue
|
|
81
|
+
- [BlockingQueue](https://tech.shutterstock.com/p-map-iterable/classes/BlockingQueue.html)
|
|
82
|
+
- Lower level utility class
|
|
83
|
+
- `dequeue` blocks until an item is available or until all items have been removed, then returns `undefined`
|
|
84
|
+
- `enqueue` blocks if the queue is full
|
|
85
|
+
- `done` signals that no more items will be added to the queue
|
|
27
86
|
|
|
28
87
|
# `IterableMapper`
|
|
29
88
|
|
|
@@ -31,75 +90,25 @@ See [p-map](https://github.com/sindresorhus/p-map) docs for a good start in unde
|
|
|
31
90
|
|
|
32
91
|
The key difference between `IterableMapper` and `pMap` are that `IterableMapper` does not return when the entire mapping is done, rather it exposes an iterable that the caller loops through. This enables results to be processed while the mapping is still happening, while optionally allowing for back pressure to slow or stop the mapping if the caller is not consuming items fast enough. Common use cases include `prefetching` items from a remote service - the next set of requests are dispatched asyncronously while the current responses are processed and the prefetch requests will pause when the unread queue fills up.
|
|
33
92
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
this._current++;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const max = 100;
|
|
61
|
-
const iterator = new SleepIterator(max);
|
|
62
|
-
let total = 0;
|
|
63
|
-
let callCount = 0;
|
|
64
|
-
|
|
65
|
-
// Create an item prefetcher with IterableMapper
|
|
66
|
-
// Use `npm i it-batch`'s `batch` function to batch the source iterable
|
|
67
|
-
// into batches of a specific size, such as 50, if making batch requests
|
|
68
|
-
// to a remote service.
|
|
69
|
-
const prefetcher = new IterableMapper(
|
|
70
|
-
// Batch example:
|
|
71
|
-
// batch(iterator, 50),
|
|
72
|
-
iterator,
|
|
73
|
-
// Batch example:
|
|
74
|
-
// async (values: number[]): Promise<number> => {
|
|
75
|
-
async (value: number): Promise<number> => {
|
|
76
|
-
callCount++;
|
|
77
|
-
total += value;
|
|
78
|
-
|
|
79
|
-
// Simulate fetching an async item with varied delays
|
|
80
|
-
await sleep(10 * (callCount % 6));
|
|
81
|
-
|
|
82
|
-
return total;
|
|
83
|
-
},
|
|
84
|
-
{ concurrency: 2, maxUnread: 10 },
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
let lastTotal = 0;
|
|
88
|
-
let loopCount = 0;
|
|
89
|
-
|
|
90
|
-
// Loop through the prefetched items or batches
|
|
91
|
-
// Will pause and wait for prefetch to complete if none available
|
|
92
|
-
// Will immediately start processing if prefetched item or batch is already available
|
|
93
|
-
// If the `maxUnread` count was hit then no prefetches will be in progress until an item
|
|
94
|
-
// is returned from the iterable here. Once an item is returned a mapper
|
|
95
|
-
// will be started; this will repeat until `concurrency` mappers are running again.
|
|
96
|
-
for await (const item of prefetcher) {
|
|
97
|
-
loopCount++;
|
|
98
|
-
if (item > lastTotal) {
|
|
99
|
-
lastTotal = item;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
```
|
|
93
|
+
See [examples/iterable-mapper.ts](./examples/iterable-mapper.ts) for an example.
|
|
94
|
+
|
|
95
|
+
Run the example with `npm run example:iterable-mapper`
|
|
96
|
+
|
|
97
|
+
# `IterableQueueMapper`
|
|
98
|
+
|
|
99
|
+
`IterableQueueMapper` is similar to `IterableMapper` but instead of taking an iterable input it instead adds data via the `enqueue` method which will block if `maxUnread` will be reached by the current number of `mapper`'s running in parallel.
|
|
100
|
+
|
|
101
|
+
See [examples/iterable-queue-mapper.ts](./examples/iterable-queue-mapper.ts) for an example.
|
|
102
|
+
|
|
103
|
+
Run the example with `npm run example:iterable-queue-mapper`
|
|
104
|
+
|
|
105
|
+
# `IterableQueueMapperSimple`
|
|
106
|
+
|
|
107
|
+
`IterableQueueMapperSimple` is similar to `IterableQueueMapper` but instead exposing the results as an iterable it discards the results as soon as they are ready and exposes any errors through the `errors` property.
|
|
108
|
+
|
|
109
|
+
See [examples/iterable-queue-mapper-simple.ts](./examples/iterable-queue-mapper-simple.ts) for an example.
|
|
110
|
+
|
|
111
|
+
Run the example with `npm run example:iterable-queue-mapper-simple`
|
|
103
112
|
|
|
104
113
|
# Contributing - Setting up Build Environment
|
|
105
114
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface BlockingQueueOptions {
|
|
1
|
+
export interface BlockingQueueOptions {
|
|
2
2
|
/**
|
|
3
3
|
* Number of pending unread items.
|
|
4
4
|
*
|
|
@@ -8,6 +8,14 @@ interface BlockingQueueOptions {
|
|
|
8
8
|
*/
|
|
9
9
|
readonly maxUnread?: number;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* `enqueue` blocks when the queue is full, until an item is read with `dequeue`, or done
|
|
13
|
+
* `dequeue` blocks when the queue is empty, until an item is added with `enqueue`, or done
|
|
14
|
+
* `done` must be called when no more items will be added
|
|
15
|
+
* `dequeue` returns `undefined` there are no more items and processing is complete
|
|
16
|
+
*
|
|
17
|
+
* @category Low-Level
|
|
18
|
+
*/
|
|
11
19
|
export declare class BlockingQueue<Element> {
|
|
12
20
|
private _options;
|
|
13
21
|
private readonly _unreadQueue;
|
|
@@ -15,9 +23,11 @@ export declare class BlockingQueue<Element> {
|
|
|
15
23
|
private readonly _writersWaiting;
|
|
16
24
|
private _doneAdding;
|
|
17
25
|
/**
|
|
26
|
+
* Create a new `BlockingQueue`
|
|
18
27
|
*
|
|
28
|
+
* @param options BlockingQueue options
|
|
19
29
|
*/
|
|
20
|
-
constructor(
|
|
30
|
+
constructor(options?: BlockingQueueOptions);
|
|
21
31
|
get length(): number;
|
|
22
32
|
/**
|
|
23
33
|
* Indicate that no more items will be enqueued.
|
|
@@ -39,11 +49,6 @@ export declare class BlockingQueue<Element> {
|
|
|
39
49
|
dequeue(): Promise<Element | undefined>;
|
|
40
50
|
private releaseAllReaders;
|
|
41
51
|
private areWeDone;
|
|
42
|
-
/**
|
|
43
|
-
* Waits for an item to be ready in the queue
|
|
44
|
-
* @returns Item from the ready queue
|
|
45
|
-
*/
|
|
46
|
-
private readWhenReady;
|
|
47
52
|
/**
|
|
48
53
|
* Waits for an item to be ready in the queue
|
|
49
54
|
*/
|
|
@@ -53,5 +58,4 @@ export declare class BlockingQueue<Element> {
|
|
|
53
58
|
*/
|
|
54
59
|
private waitForRead;
|
|
55
60
|
}
|
|
56
|
-
export {};
|
|
57
61
|
//# sourceMappingURL=blocking-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -3,11 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BlockingQueue = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const queue_1 = require("./queue");
|
|
6
|
+
/**
|
|
7
|
+
* `enqueue` blocks when the queue is full, until an item is read with `dequeue`, or done
|
|
8
|
+
* `dequeue` blocks when the queue is empty, until an item is added with `enqueue`, or done
|
|
9
|
+
* `done` must be called when no more items will be added
|
|
10
|
+
* `dequeue` returns `undefined` there are no more items and processing is complete
|
|
11
|
+
*
|
|
12
|
+
* @category Low-Level
|
|
13
|
+
*/
|
|
6
14
|
class BlockingQueue {
|
|
7
15
|
/**
|
|
16
|
+
* Create a new `BlockingQueue`
|
|
8
17
|
*
|
|
18
|
+
* @param options BlockingQueue options
|
|
9
19
|
*/
|
|
10
|
-
constructor(
|
|
20
|
+
constructor(options = {}) {
|
|
11
21
|
// NOTE: unreadQueue has to be a proper FIFO queue with O(1) removal from the front
|
|
12
22
|
// as we may have O(m) unread items, where m may approach n, and Array.shift()
|
|
13
23
|
// would be O(m) (approaching O(n)) in that case as the array gets large.
|
|
@@ -25,6 +35,7 @@ class BlockingQueue {
|
|
|
25
35
|
// is ready.
|
|
26
36
|
this._writersWaiting = new queue_1.Queue();
|
|
27
37
|
this._doneAdding = false;
|
|
38
|
+
const { maxUnread = 8 } = options;
|
|
28
39
|
this._options = { maxUnread };
|
|
29
40
|
// Avoid undefined errors on options
|
|
30
41
|
if (this._options.maxUnread === undefined) {
|
|
@@ -142,24 +153,22 @@ class BlockingQueue {
|
|
|
142
153
|
}
|
|
143
154
|
return false;
|
|
144
155
|
}
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
readWhenReady() {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
});
|
|
162
|
-
}
|
|
156
|
+
// /**
|
|
157
|
+
// * Waits for an item to be ready in the queue
|
|
158
|
+
// * @returns Item from the ready queue
|
|
159
|
+
// */
|
|
160
|
+
// private async readWhenReady(): Promise<Element | undefined> {
|
|
161
|
+
// // If there are waiters, create a waiter promise and add to end of list
|
|
162
|
+
// // Note: the background reader removes the promise from the readers waiting queue
|
|
163
|
+
// const itemReady = new Promise((resolve) => {
|
|
164
|
+
// this._readersWaiting.enqueue(resolve);
|
|
165
|
+
// });
|
|
166
|
+
// // Wait for our item to be ready
|
|
167
|
+
// await itemReady;
|
|
168
|
+
// const item = this._unreadQueue.dequeue();
|
|
169
|
+
// // Pull the item from the front
|
|
170
|
+
// return item;
|
|
171
|
+
// }
|
|
163
172
|
/**
|
|
164
173
|
* Waits for an item to be ready in the queue
|
|
165
174
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocking-queue.js","sourceRoot":"","sources":["../../src/blocking-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocking-queue.test.d.ts","sourceRoot":"","sources":["../../src/blocking-queue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocking-queue.test.js","sourceRoot":"","sources":["../../src/blocking-queue.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Mapper, IterableMapper, IterableMapperOptions } from './iterable-mapper';
|
|
2
|
+
import { BlockingQueue, BlockingQueueOptions } from './blocking-queue';
|
|
3
|
+
import { IterableQueue, IterableQueueOptions } from './iterable-queue';
|
|
4
|
+
import { IterableQueueMapper, IterableQueueMapperOptions } from './iterable-queue-mapper';
|
|
5
|
+
import { IterableQueueMapperSimple } from './iterable-queue-mapper-simple';
|
|
6
|
+
import { Queue } from './queue';
|
|
7
|
+
export { Mapper, IterableMapper, IterableMapperOptions, IterableQueueMapper, IterableQueueMapperOptions, IterableQueueMapperSimple, BlockingQueue, BlockingQueueOptions, IterableQueue, IterableQueueOptions, Queue, };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EACL,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,0BAA0B,EAC1B,yBAAyB,EACzB,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,oBAAoB,EACpB,KAAK,GACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,uDAAkF;AAShF,+FATe,gCAAc,OASf;AARhB,qDAAuE;AAarE,8FAbO,8BAAa,OAaP;AAZf,qDAAuE;AAcrE,8FAdO,8BAAa,OAcP;AAbf,mEAA0F;AAQxF,oGARO,2CAAmB,OAQP;AAPrB,iFAA2E;AASzE,0GATO,wDAAyB,OASP;AAR3B,mCAAgC;AAa9B,sFAbO,aAAK,OAaP"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for IterableMapper
|
|
3
|
+
*/
|
|
4
|
+
export interface IterableMapperOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Number of concurrently pending promises returned by `mapper`.
|
|
7
|
+
*
|
|
8
|
+
* Must be an integer from 1 and up or `Infinity`, must be <= `maxUnread`.
|
|
9
|
+
*
|
|
10
|
+
* @default 4
|
|
11
|
+
*/
|
|
12
|
+
readonly concurrency?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Number of pending unread iterable items.
|
|
15
|
+
*
|
|
16
|
+
* Must be an integer from 1 and up or `Infinity`, must be >= `concurrency`.
|
|
17
|
+
*
|
|
18
|
+
* @default 8
|
|
19
|
+
*/
|
|
20
|
+
readonly maxUnread?: number;
|
|
21
|
+
/**
|
|
22
|
+
* When set to `false`, instead of stopping when a promise rejects, it will wait for all the promises to settle and then reject with an [aggregated error](https://github.com/sindresorhus/aggregate-error) containing all the errors from the rejected promises.
|
|
23
|
+
*
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
readonly stopOnMapperError?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Function which is called for every item in `input`. Expected to return a `Promise` or value.
|
|
30
|
+
*
|
|
31
|
+
* @template Element - Source element type
|
|
32
|
+
* @template NewElement - Element type returned by the mapper
|
|
33
|
+
* @param element - Iterated element
|
|
34
|
+
* @param index - Index of the element in the source array
|
|
35
|
+
*/
|
|
36
|
+
export type Mapper<Element = unknown, NewElement = unknown> = (element: Element, index: number) => NewElement | Promise<NewElement>;
|
|
37
|
+
/**
|
|
38
|
+
* Iterates over a source iterable with specified concurrency,
|
|
39
|
+
* calling the `mapper` on each iterated item, and storing the
|
|
40
|
+
* `mapper` result in a queue of specified max size, before
|
|
41
|
+
* being iterated / read by the caller.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
*
|
|
45
|
+
* This allows performing a concurrent mapping with
|
|
46
|
+
* back pressure (won't iterate all source items if the consumer is
|
|
47
|
+
* not reading).
|
|
48
|
+
*
|
|
49
|
+
* Typical use case is for a `prefetcher` that ensures that items
|
|
50
|
+
* are always ready for the consumer but that large numbers of items
|
|
51
|
+
* are not processed before the consumer is ready for them.
|
|
52
|
+
*
|
|
53
|
+
* @category Iterable Input
|
|
54
|
+
*/
|
|
55
|
+
export declare class IterableMapper<Element, NewElement> implements AsyncIterable<NewElement> {
|
|
56
|
+
private _mapper;
|
|
57
|
+
private _options;
|
|
58
|
+
private _unreadQueue;
|
|
59
|
+
private _iterator;
|
|
60
|
+
private readonly _errors;
|
|
61
|
+
private _asyncIterator;
|
|
62
|
+
private _isRejected;
|
|
63
|
+
private _isIterableDone;
|
|
64
|
+
private _activeRunners;
|
|
65
|
+
private _resolvingCount;
|
|
66
|
+
private _currentIndex;
|
|
67
|
+
private _initialRunnersCreated;
|
|
68
|
+
/**
|
|
69
|
+
* Create a new `IterableMapper`
|
|
70
|
+
*
|
|
71
|
+
* @param input Iterated over concurrently in the `mapper` function.
|
|
72
|
+
* @param mapper Function which is called for every item in `input`.
|
|
73
|
+
* Expected to return a `Promise` or value.
|
|
74
|
+
*
|
|
75
|
+
* The `mapper` *should* handle all errors and not allow an error to be thrown
|
|
76
|
+
* out of the `mapper` function as this enables the best handling of errors
|
|
77
|
+
* closest to the time that they occur.
|
|
78
|
+
*
|
|
79
|
+
* If the `mapper` function does allow an error to be thrown then the
|
|
80
|
+
* `stopOnMapperError` option controls the behavior:
|
|
81
|
+
* - `stopOnMapperError`: `true` - will throw the error
|
|
82
|
+
* out of `next` or the `AsyncIterator` returned from `[Symbol.asyncIterator]`
|
|
83
|
+
* and stop processing.
|
|
84
|
+
* - `stopOnMapperError`: `false` - will continue processing
|
|
85
|
+
* and accumulate the errors to be thrown from `next` or the `AsyncIterator`
|
|
86
|
+
* returned from `[Symbol.asyncIterator]` when all items have been processed.
|
|
87
|
+
* @param options IterableMapper options
|
|
88
|
+
*/
|
|
89
|
+
constructor(input: AsyncIterable<Element> | Iterable<Element>, mapper: Mapper<Element, NewElement>, options?: IterableMapperOptions);
|
|
90
|
+
[Symbol.asyncIterator](): AsyncIterator<NewElement>;
|
|
91
|
+
/**
|
|
92
|
+
* Used by the iterator returned from [Symbol.asyncIterator]
|
|
93
|
+
* Called every time an item is needed
|
|
94
|
+
*
|
|
95
|
+
* @returns Iterator result
|
|
96
|
+
*/
|
|
97
|
+
next(): Promise<IteratorResult<NewElement>>;
|
|
98
|
+
private bubbleUpErrors;
|
|
99
|
+
private startARunnerIfNeeded;
|
|
100
|
+
private startAnotherRunner;
|
|
101
|
+
private areWeDone;
|
|
102
|
+
/**
|
|
103
|
+
* Throw an exception if the wrapped NewElement is an Error
|
|
104
|
+
*
|
|
105
|
+
* @returns Element if no error
|
|
106
|
+
*/
|
|
107
|
+
private throwIfError;
|
|
108
|
+
/**
|
|
109
|
+
* Get the next item from the source iterable.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
*
|
|
113
|
+
* This is called up to `concurrency` times in parallel.
|
|
114
|
+
*
|
|
115
|
+
* If the read queue is not full, and there are source items to read,
|
|
116
|
+
* each instance of this will keep calling a new instance of itself
|
|
117
|
+
* that detaches and runs asynchronously (keeping the same number
|
|
118
|
+
* of instances running).
|
|
119
|
+
*
|
|
120
|
+
* If the read queue + runners = max read queue length then the runner
|
|
121
|
+
* will exit and will be restarted when an item is read from the queue.
|
|
122
|
+
*/
|
|
123
|
+
private sourceNext;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=iterable-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iterable-mapper.d.ts","sourceRoot":"","sources":["../../src/iterable-mapper.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,CAAC,OAAO,GAAG,OAAO,EAAE,UAAU,GAAG,OAAO,IAAI,CAC5D,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,KACV,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAUtC;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,cAAc,CAAC,OAAO,EAAE,UAAU,CAAE,YAAW,aAAa,CAAC,UAAU,CAAC;IACnF,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,QAAQ,CAAkC;IAElD,OAAO,CAAC,YAAY,CAA+C;IAEnE,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,sBAAsB,CAAS;IAEvC;;;;;;;;;;;;;;;;;;;;OAoBG;gBAED,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,EACjD,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,EACnC,OAAO,GAAE,qBAA0B;IAwF9B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC;IAI1D;;;;;OAKG;IACU,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAyBxD,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,oBAAoB;IAuB5B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,SAAS;IAiBjB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IASpB;;;;;;;;;;;;;;OAcG;YACW,UAAU;CAiHzB"}
|
|
@@ -7,33 +7,47 @@ const tslib_1 = require("tslib");
|
|
|
7
7
|
//
|
|
8
8
|
const aggregate_error_1 = tslib_1.__importDefault(require("aggregate-error"));
|
|
9
9
|
const iterable_queue_1 = require("./iterable-queue");
|
|
10
|
+
/**
|
|
11
|
+
* Iterates over a source iterable with specified concurrency,
|
|
12
|
+
* calling the `mapper` on each iterated item, and storing the
|
|
13
|
+
* `mapper` result in a queue of specified max size, before
|
|
14
|
+
* being iterated / read by the caller.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
*
|
|
18
|
+
* This allows performing a concurrent mapping with
|
|
19
|
+
* back pressure (won't iterate all source items if the consumer is
|
|
20
|
+
* not reading).
|
|
21
|
+
*
|
|
22
|
+
* Typical use case is for a `prefetcher` that ensures that items
|
|
23
|
+
* are always ready for the consumer but that large numbers of items
|
|
24
|
+
* are not processed before the consumer is ready for them.
|
|
25
|
+
*
|
|
26
|
+
* @category Iterable Input
|
|
27
|
+
*/
|
|
10
28
|
class IterableMapper {
|
|
11
29
|
/**
|
|
12
|
-
*
|
|
13
|
-
* calling the `mapper` on each iterated item, and storing the
|
|
14
|
-
* `mapper` result in a queue of specified max size, before
|
|
15
|
-
* being iterated / read by the caller.
|
|
30
|
+
* Create a new `IterableMapper`
|
|
16
31
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
32
|
+
* @param input Iterated over concurrently in the `mapper` function.
|
|
33
|
+
* @param mapper Function which is called for every item in `input`.
|
|
34
|
+
* Expected to return a `Promise` or value.
|
|
20
35
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
36
|
+
* The `mapper` *should* handle all errors and not allow an error to be thrown
|
|
37
|
+
* out of the `mapper` function as this enables the best handling of errors
|
|
38
|
+
* closest to the time that they occur.
|
|
24
39
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* values returned from `mapper` in `input` order.
|
|
40
|
+
* If the `mapper` function does allow an error to be thrown then the
|
|
41
|
+
* `stopOnMapperError` option controls the behavior:
|
|
42
|
+
* - `stopOnMapperError`: `true` - will throw the error
|
|
43
|
+
* out of `next` or the `AsyncIterator` returned from `[Symbol.asyncIterator]`
|
|
44
|
+
* and stop processing.
|
|
45
|
+
* - `stopOnMapperError`: `false` - will continue processing
|
|
46
|
+
* and accumulate the errors to be thrown from `next` or the `AsyncIterator`
|
|
47
|
+
* returned from `[Symbol.asyncIterator]` when all items have been processed.
|
|
48
|
+
* @param options IterableMapper options
|
|
35
49
|
*/
|
|
36
|
-
constructor(
|
|
50
|
+
constructor(input, mapper, options = {}) {
|
|
37
51
|
this._errors = [];
|
|
38
52
|
this._asyncIterator = false;
|
|
39
53
|
this._isRejected = false;
|
|
@@ -42,6 +56,7 @@ class IterableMapper {
|
|
|
42
56
|
this._resolvingCount = 0;
|
|
43
57
|
this._currentIndex = 0;
|
|
44
58
|
this._initialRunnersCreated = false;
|
|
59
|
+
const { concurrency = 4, stopOnMapperError = true, maxUnread = 8 } = options;
|
|
45
60
|
this._mapper = mapper;
|
|
46
61
|
this._options = { concurrency, stopOnMapperError, maxUnread };
|
|
47
62
|
if (typeof mapper !== 'function') {
|
|
@@ -71,13 +86,13 @@ class IterableMapper {
|
|
|
71
86
|
}
|
|
72
87
|
this._unreadQueue = new iterable_queue_1.IterableQueue({ maxUnread });
|
|
73
88
|
// Setup the source iterator
|
|
74
|
-
if (
|
|
89
|
+
if (input[Symbol.asyncIterator] !== undefined) {
|
|
75
90
|
// We've got an async iterable
|
|
76
|
-
this._iterator =
|
|
91
|
+
this._iterator = input[Symbol.asyncIterator]();
|
|
77
92
|
this._asyncIterator = true;
|
|
78
93
|
}
|
|
79
94
|
else {
|
|
80
|
-
this._iterator =
|
|
95
|
+
this._iterator = input[Symbol.iterator]();
|
|
81
96
|
}
|
|
82
97
|
// Create the initial concurrent runners in a detached (non-awaited)
|
|
83
98
|
// promise. We need this so we can await the next() calls
|
|
@@ -105,6 +120,7 @@ class IterableMapper {
|
|
|
105
120
|
/**
|
|
106
121
|
* Used by the iterator returned from [Symbol.asyncIterator]
|
|
107
122
|
* Called every time an item is needed
|
|
123
|
+
*
|
|
108
124
|
* @returns Iterator result
|
|
109
125
|
*/
|
|
110
126
|
next() {
|
|
@@ -192,7 +208,8 @@ class IterableMapper {
|
|
|
192
208
|
}
|
|
193
209
|
/**
|
|
194
210
|
* Throw an exception if the wrapped NewElement is an Error
|
|
195
|
-
*
|
|
211
|
+
*
|
|
212
|
+
* @returns Element if no error
|
|
196
213
|
*/
|
|
197
214
|
throwIfError(item) {
|
|
198
215
|
if (item.error !== undefined) {
|
|
@@ -206,6 +223,8 @@ class IterableMapper {
|
|
|
206
223
|
/**
|
|
207
224
|
* Get the next item from the source iterable.
|
|
208
225
|
*
|
|
226
|
+
* @remarks
|
|
227
|
+
*
|
|
209
228
|
* This is called up to `concurrency` times in parallel.
|
|
210
229
|
*
|
|
211
230
|
* If the read queue is not full, and there are source items to read,
|
|
@@ -215,7 +234,6 @@ class IterableMapper {
|
|
|
215
234
|
*
|
|
216
235
|
* If the read queue + runners = max read queue length then the runner
|
|
217
236
|
* will exit and will be restarted when an item is read from the queue.
|
|
218
|
-
* @returns
|
|
219
237
|
*/
|
|
220
238
|
sourceNext() {
|
|
221
239
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|