@zukhruf/async 0.3.19 → 0.3.20
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 +36 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/poll.d.ts +23 -0
- package/dist/poll.d.ts.map +1 -0
- package/dist/poll.js +15 -0
- package/dist/poll.js.map +1 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @zukhruf/async
|
|
2
2
|
|
|
3
|
-
Helpers for code that waits for promises: `untilAborted` cancels a wait,
|
|
3
|
+
Helpers for code that waits for promises: `untilAborted` cancels a wait, `Latch` holds callers until something happened, and `poll` calls an attempt again until it gives a value. `@zukhruf/mutex`, `@zukhruf/single-flight` and `@zukhruf/election` use them.
|
|
4
4
|
|
|
5
5
|
The words in these documents have one meaning each. See the glossary in [CONTEXT.md](./CONTEXT.md).
|
|
6
6
|
|
|
@@ -53,3 +53,38 @@ const value = await done.wait(); // 'report'
|
|
|
53
53
|
A latch never rejects. It keeps its value in a box, so it never adopts a promise, whatever its type. Thus a class can keep a latch in a field: the latch cannot fail before somebody awaits it. A latch whose type names a promise refuses one at compile time, because a wait would adopt the promise and could then reject. To share the outcome of work that can fail, give the latch a value that tells how the work ended, for example the `PromiseSettledResult` of `Promise.allSettled`. Each caller then throws the error for itself. See [ADR 0002](./docs/adr/0002-a-latch-carries-a-value-never-a-failure.md).
|
|
54
54
|
|
|
55
55
|
To stop a wait on a latch, cancel it: `untilAborted(latch.wait(), signal)`.
|
|
56
|
+
|
|
57
|
+
## Poll an attempt until it gives a value
|
|
58
|
+
|
|
59
|
+
An attempt tries to get a value now, and it does not wait. For example, it tries to take a lock that another process can hold. The attempt gives the value, or `undefined` when there is no value yet. `poll` calls the attempt. When the attempt gives `undefined`, `poll` waits `interval` milliseconds, and then it calls the attempt again. When the attempt gives a value, `poll` resolves with that value.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { poll } from '@zukhruf/async';
|
|
63
|
+
|
|
64
|
+
// queue.take() gives the next job, or undefined when the queue is empty.
|
|
65
|
+
const job = await poll(() => queue.take(), { interval: 100, signal });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Only `undefined` means "no value yet". `null`, `0` and `false` are values.
|
|
69
|
+
- An error from the attempt rejects `poll` with the same error. `poll` does not call the attempt again after an error. To try an operation again after an error, see `patiently` of `@zukhruf/fs`.
|
|
70
|
+
- When `signal` aborts during a wait, `poll` stops the timer of the wait and rejects with the reason of the signal. A cancel does not stop an attempt that runs.
|
|
71
|
+
|
|
72
|
+
### Stop at a deadline
|
|
73
|
+
|
|
74
|
+
A deadline is a time from `performance.now()`, not a duration. After the deadline, an attempt that gives `undefined` resolves `poll` with `undefined`. An attempt that gives a value still resolves `poll` with the value.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const deadline = performance.now() + 5_000;
|
|
78
|
+
const job = await poll(() => queue.take(), {
|
|
79
|
+
interval: 100,
|
|
80
|
+
signal: undefined,
|
|
81
|
+
deadline,
|
|
82
|
+
});
|
|
83
|
+
// job is undefined when the queue stayed empty for 5 seconds.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- The first attempt always occurs, also when the deadline is already in the past. Thus a deadline of `performance.now()` gives one attempt.
|
|
87
|
+
- One deadline can stop many polls. A campaign of `@zukhruf/election` uses one deadline for all its attempts.
|
|
88
|
+
- Without a deadline, the type of the result has no `undefined`.
|
|
89
|
+
|
|
90
|
+
See [ADR 0003](./docs/adr/0003-the-election-and-the-file-lock-stores-poll-through-one-function.md).
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAoB,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/poll.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PollOptions {
|
|
2
|
+
/** Milliseconds to wait after an attempt that gave nothing. */
|
|
3
|
+
interval: number;
|
|
4
|
+
/** Stops the wait between two attempts. The poll then rejects with `signal.reason`. */
|
|
5
|
+
signal: AbortSignal | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* A `performance.now()` time. After it, an attempt that gives nothing
|
|
8
|
+
* resolves the poll with `undefined`. The first attempt always occurs.
|
|
9
|
+
*/
|
|
10
|
+
deadline?: number | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Calls `attempt` until it gives a value other than `undefined`, and waits
|
|
14
|
+
* `interval` between two attempts. An error from `attempt` rejects the poll
|
|
15
|
+
* unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export declare function poll<T>(attempt: () => Promise<T | undefined>, options: PollOptions & {
|
|
18
|
+
deadline: number;
|
|
19
|
+
}): Promise<T | undefined>;
|
|
20
|
+
export declare function poll<T>(attempt: () => Promise<T | undefined>, options: PollOptions & {
|
|
21
|
+
deadline?: undefined;
|
|
22
|
+
}): Promise<T>;
|
|
23
|
+
//# sourceMappingURL=poll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,EACrC,OAAO,EAAE,WAAW,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAC1B,wBAAgB,IAAI,CAAC,CAAC,EACpB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,EACrC,OAAO,EAAE,WAAW,GAAG;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,GAC9C,OAAO,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/poll.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
2
|
+
import { untilAborted } from "./until-aborted.js";
|
|
3
|
+
export async function poll(attempt, { interval, signal, deadline }) {
|
|
4
|
+
for (;;) {
|
|
5
|
+
const value = await attempt();
|
|
6
|
+
if (value !== undefined)
|
|
7
|
+
return value;
|
|
8
|
+
if (deadline !== undefined && performance.now() >= deadline) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
// delay's signal frees the timer; untilAborted rejects with the reason.
|
|
12
|
+
await untilAborted(delay(interval, undefined, { signal }), signal);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=poll.js.map
|
package/dist/poll.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll.js","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA2BlD,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAqC,EACrC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAe;IAE3C,SAAS,CAAC;QACR,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,QAAQ,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC5D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,wEAAwE;QACxE,MAAM,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACrE,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/async",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Helpers for code that waits for promises: cancel a wait when an AbortSignal aborts,
|
|
3
|
+
"version": "0.3.20",
|
|
4
|
+
"description": "Helpers for code that waits for promises: cancel a wait when an AbortSignal aborts, hold callers on a one-shot latch that never rejects, and poll an attempt until it gives a value.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
"abortable",
|
|
19
19
|
"promise",
|
|
20
20
|
"async",
|
|
21
|
-
"latch"
|
|
21
|
+
"latch",
|
|
22
|
+
"poll",
|
|
23
|
+
"polling"
|
|
22
24
|
],
|
|
23
25
|
"type": "module",
|
|
24
26
|
"types": "./dist/index.d.ts",
|