@adviser/cement 0.4.58 → 0.4.60
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/cjs/base-sys-abstraction.d.ts +1 -1
- package/cjs/base-sys-abstraction.d.ts.map +1 -1
- package/cjs/future.cjs +2 -0
- package/cjs/future.cjs.map +1 -1
- package/cjs/future.d.ts +1 -0
- package/cjs/future.d.ts.map +1 -1
- package/cjs/future.test.cjs +5 -0
- package/cjs/future.test.cjs.map +1 -1
- package/cjs/on-func.test.cjs +1 -1
- package/cjs/on-func.test.cjs.map +1 -1
- package/cjs/poller.cjs +107 -18
- package/cjs/poller.cjs.map +1 -1
- package/cjs/poller.d.ts +27 -5
- package/cjs/poller.d.ts.map +1 -1
- package/cjs/poller.test.cjs +46 -2
- package/cjs/poller.test.cjs.map +1 -1
- package/cjs/timeouted.cjs +119 -0
- package/cjs/timeouted.cjs.map +1 -0
- package/cjs/timeouted.d.ts +45 -0
- package/cjs/timeouted.d.ts.map +1 -0
- package/cjs/timeouted.test.cjs +581 -0
- package/cjs/timeouted.test.cjs.map +1 -0
- package/cjs/timeouted.test.d.ts +2 -0
- package/cjs/timeouted.test.d.ts.map +1 -0
- package/cjs/utils/promise-sleep.cjs +27 -26
- package/cjs/utils/promise-sleep.cjs.map +1 -1
- package/cjs/utils/promise-sleep.d.ts +28 -2
- package/cjs/utils/promise-sleep.d.ts.map +1 -1
- package/cjs/utils/promise-sleep.test.cjs +13 -13
- package/cjs/utils/promise-sleep.test.cjs.map +1 -1
- package/cjs/version.cjs +1 -1
- package/deno.json +1 -1
- package/esm/base-sys-abstraction.d.ts +1 -1
- package/esm/base-sys-abstraction.d.ts.map +1 -1
- package/esm/future.d.ts +1 -0
- package/esm/future.d.ts.map +1 -1
- package/esm/future.js +2 -0
- package/esm/future.js.map +1 -1
- package/esm/future.test.js +5 -0
- package/esm/future.test.js.map +1 -1
- package/esm/on-func.test.js +1 -1
- package/esm/on-func.test.js.map +1 -1
- package/esm/poller.d.ts +27 -5
- package/esm/poller.d.ts.map +1 -1
- package/esm/poller.js +107 -18
- package/esm/poller.js.map +1 -1
- package/esm/poller.test.js +46 -2
- package/esm/poller.test.js.map +1 -1
- package/esm/timeouted.d.ts +45 -0
- package/esm/timeouted.d.ts.map +1 -0
- package/esm/timeouted.js +110 -0
- package/esm/timeouted.js.map +1 -0
- package/esm/timeouted.test.d.ts +2 -0
- package/esm/timeouted.test.d.ts.map +1 -0
- package/esm/timeouted.test.js +579 -0
- package/esm/timeouted.test.js.map +1 -0
- package/esm/utils/promise-sleep.d.ts +28 -2
- package/esm/utils/promise-sleep.d.ts.map +1 -1
- package/esm/utils/promise-sleep.js +27 -26
- package/esm/utils/promise-sleep.js.map +1 -1
- package/esm/utils/promise-sleep.test.js +13 -13
- package/esm/utils/promise-sleep.test.js.map +1 -1
- package/esm/version.js +1 -1
- package/package.json +8 -8
- package/src/base-sys-abstraction.ts +1 -1
- package/src/future.ts +5 -0
- package/src/poller.ts +159 -23
- package/src/timeouted.ts +186 -0
- package/src/utils/promise-sleep.ts +61 -31
- package/ts/cjs/base-sys-abstraction.d.ts +1 -1
- package/ts/cjs/base-sys-abstraction.d.ts.map +1 -1
- package/ts/cjs/future.d.ts +1 -0
- package/ts/cjs/future.d.ts.map +1 -1
- package/ts/cjs/future.js +2 -0
- package/ts/cjs/future.js.map +1 -1
- package/ts/cjs/future.test.js +5 -0
- package/ts/cjs/future.test.js.map +1 -1
- package/ts/cjs/on-func.test.js +1 -1
- package/ts/cjs/on-func.test.js.map +1 -1
- package/ts/cjs/poller.d.ts +27 -5
- package/ts/cjs/poller.d.ts.map +1 -1
- package/ts/cjs/poller.js +107 -18
- package/ts/cjs/poller.js.map +1 -1
- package/ts/cjs/poller.test.js +46 -2
- package/ts/cjs/poller.test.js.map +1 -1
- package/ts/cjs/timeouted.d.ts +45 -0
- package/ts/cjs/timeouted.d.ts.map +1 -0
- package/ts/cjs/timeouted.js +119 -0
- package/ts/cjs/timeouted.js.map +1 -0
- package/ts/cjs/timeouted.test.d.ts +2 -0
- package/ts/cjs/timeouted.test.d.ts.map +1 -0
- package/ts/cjs/timeouted.test.js +581 -0
- package/ts/cjs/timeouted.test.js.map +1 -0
- package/ts/cjs/utils/promise-sleep.d.ts +28 -2
- package/ts/cjs/utils/promise-sleep.d.ts.map +1 -1
- package/ts/cjs/utils/promise-sleep.js +27 -26
- package/ts/cjs/utils/promise-sleep.js.map +1 -1
- package/ts/cjs/utils/promise-sleep.test.js +13 -13
- package/ts/cjs/utils/promise-sleep.test.js.map +1 -1
- package/ts/cjs/version.js +1 -1
- package/ts/esm/base-sys-abstraction.d.ts +1 -1
- package/ts/esm/base-sys-abstraction.d.ts.map +1 -1
- package/ts/esm/future.d.ts +1 -0
- package/ts/esm/future.d.ts.map +1 -1
- package/ts/esm/future.js +2 -0
- package/ts/esm/future.js.map +1 -1
- package/ts/esm/future.test.js +5 -0
- package/ts/esm/future.test.js.map +1 -1
- package/ts/esm/on-func.test.js +1 -1
- package/ts/esm/on-func.test.js.map +1 -1
- package/ts/esm/poller.d.ts +27 -5
- package/ts/esm/poller.d.ts.map +1 -1
- package/ts/esm/poller.js +107 -18
- package/ts/esm/poller.js.map +1 -1
- package/ts/esm/poller.test.js +46 -2
- package/ts/esm/poller.test.js.map +1 -1
- package/ts/esm/timeouted.d.ts +45 -0
- package/ts/esm/timeouted.d.ts.map +1 -0
- package/ts/esm/timeouted.js +110 -0
- package/ts/esm/timeouted.js.map +1 -0
- package/ts/esm/timeouted.test.d.ts +2 -0
- package/ts/esm/timeouted.test.d.ts.map +1 -0
- package/ts/esm/timeouted.test.js +579 -0
- package/ts/esm/timeouted.test.js.map +1 -0
- package/ts/esm/utils/promise-sleep.d.ts +28 -2
- package/ts/esm/utils/promise-sleep.d.ts.map +1 -1
- package/ts/esm/utils/promise-sleep.js +27 -26
- package/ts/esm/utils/promise-sleep.js.map +1 -1
- package/ts/esm/utils/promise-sleep.test.js +13 -13
- package/ts/esm/utils/promise-sleep.test.js.map +1 -1
- package/ts/esm/version.js +1 -1
|
@@ -1,3 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface SleepBase {
|
|
2
|
+
readonly state: "sleeped" | "error" | "aborted";
|
|
3
|
+
readonly isOk: boolean;
|
|
4
|
+
readonly isErr: boolean;
|
|
5
|
+
readonly isAborted: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface SleepOk extends SleepBase {
|
|
8
|
+
readonly state: "sleeped";
|
|
9
|
+
readonly isOk: true;
|
|
10
|
+
readonly isErr: false;
|
|
11
|
+
readonly isAborted: false;
|
|
12
|
+
}
|
|
13
|
+
export interface SleepErr extends SleepBase {
|
|
14
|
+
readonly state: "error";
|
|
15
|
+
readonly error: Error;
|
|
16
|
+
readonly isOk: false;
|
|
17
|
+
readonly isErr: true;
|
|
18
|
+
readonly isAborted: false;
|
|
19
|
+
}
|
|
20
|
+
export interface SleepAbort extends SleepBase {
|
|
21
|
+
readonly state: "aborted";
|
|
22
|
+
readonly reason: Error;
|
|
23
|
+
readonly isOk: false;
|
|
24
|
+
readonly isErr: false;
|
|
25
|
+
readonly isAborted: true;
|
|
26
|
+
}
|
|
27
|
+
export type SleepResult = SleepOk | SleepErr | SleepAbort;
|
|
28
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<SleepResult>;
|
|
3
29
|
//# sourceMappingURL=promise-sleep.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-sleep.d.ts","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"promise-sleep.d.ts","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;CAC3B;AAED,MAAM,WAAW,QAAS,SAAQ,SAAS;IACzC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;CAC3B;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAU1D,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CA8BlF"}
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export function sleep(ms, signal) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
import { Future } from "../future.js";
|
|
2
|
+
export async function sleep(ms, signal) {
|
|
3
|
+
if (ms < 0) {
|
|
4
|
+
return { state: "sleeped", isOk: true, isErr: false, isAborted: false };
|
|
5
|
+
}
|
|
6
|
+
if (signal?.aborted) {
|
|
7
|
+
const err = new Error("sleep aborted");
|
|
8
|
+
return { state: "aborted", reason: err, isOk: false, isErr: false, isAborted: true };
|
|
9
|
+
}
|
|
10
|
+
const sleepFuture = new Future();
|
|
11
|
+
const id = setTimeout(() => {
|
|
12
|
+
sleepFuture.resolve({ state: "sleeped", isOk: true, isErr: false, isAborted: false });
|
|
13
|
+
}, ms);
|
|
14
|
+
const abortFuture = new Future();
|
|
15
|
+
function onAbort() {
|
|
16
|
+
abortFuture.resolve({
|
|
17
|
+
state: "aborted",
|
|
18
|
+
reason: new Error("sleep aborted"),
|
|
19
|
+
isOk: false,
|
|
20
|
+
isErr: false,
|
|
21
|
+
isAborted: true,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
25
|
+
return Promise.race([abortFuture.asPromise(), sleepFuture.asPromise()]).finally(() => {
|
|
26
|
+
clearTimeout(id);
|
|
27
|
+
signal?.removeEventListener("abort", onAbort);
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
//# sourceMappingURL=promise-sleep.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-sleep.js","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"promise-sleep.js","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AA0CtC,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,EAAU,EAAE,MAAoB,EAAwB;IAClF,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAEvC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACvF,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,MAAM,EAAW,CAAC;IAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;QAE1B,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAAA,CACvF,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,WAAW,GAAG,IAAI,MAAM,EAAc,CAAC;IAC7C,SAAS,OAAO,GAAS;QACvB,WAAW,CAAC,OAAO,CAAC;YAClB,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,IAAI,KAAK,CAAC,eAAe,CAAC;YAClC,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;IAAA,CACJ;IACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACpF,YAAY,CAAC,EAAE,CAAC,CAAC;QACjB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAAA,CAC/C,CAAC,CAAC;AAAA,CACJ"}
|
|
@@ -5,58 +5,58 @@ it("sleeps for the specified duration", async () => {
|
|
|
5
5
|
const duration = performance.now() - start;
|
|
6
6
|
expect(duration).toBeGreaterThanOrEqual(95);
|
|
7
7
|
expect(duration).toBeLessThan(150);
|
|
8
|
-
expect(result.isOk
|
|
9
|
-
expect(result.unwrap()).toBeUndefined();
|
|
8
|
+
expect(result.isOk).toBe(true);
|
|
10
9
|
});
|
|
11
10
|
it("returns immediately for zero milliseconds", async () => {
|
|
12
11
|
const start = performance.now();
|
|
13
12
|
const result = await sleep(0);
|
|
14
13
|
const duration = performance.now() - start;
|
|
15
14
|
expect(duration).toBeLessThan(10);
|
|
16
|
-
expect(result.isOk
|
|
15
|
+
expect(result.isOk).toBe(true);
|
|
17
16
|
});
|
|
18
17
|
it("returns immediately for negative milliseconds", async () => {
|
|
19
18
|
const start = performance.now();
|
|
20
19
|
const result = await sleep(-100);
|
|
21
20
|
const duration = performance.now() - start;
|
|
22
21
|
expect(duration).toBeLessThan(10);
|
|
23
|
-
expect(result.isOk
|
|
22
|
+
expect(result.isOk).toBe(true);
|
|
24
23
|
});
|
|
25
24
|
it("returns error when aborted before sleep starts", async () => {
|
|
26
25
|
const controller = new AbortController();
|
|
27
26
|
controller.abort();
|
|
28
|
-
const result = await sleep(100, controller.signal);
|
|
29
|
-
expect(result.isOk
|
|
30
|
-
expect(result.
|
|
27
|
+
const result = (await sleep(100, controller.signal));
|
|
28
|
+
expect(result.isOk).toBe(false);
|
|
29
|
+
expect(result.isAborted).toBe(true);
|
|
30
|
+
expect(result.reason.message).toBe("sleep aborted");
|
|
31
31
|
});
|
|
32
32
|
it("returns error when aborted during sleep", async () => {
|
|
33
33
|
const controller = new AbortController();
|
|
34
34
|
const start = performance.now();
|
|
35
35
|
const sleepPromise = sleep(200, controller.signal);
|
|
36
36
|
setTimeout(() => controller.abort(), 50);
|
|
37
|
-
const result = await sleepPromise;
|
|
37
|
+
const result = (await sleepPromise);
|
|
38
38
|
const duration = performance.now() - start;
|
|
39
39
|
expect(duration).toBeGreaterThanOrEqual(45);
|
|
40
40
|
expect(duration).toBeLessThan(150);
|
|
41
|
-
expect(result.isOk
|
|
42
|
-
expect(result.
|
|
41
|
+
expect(result.isOk).toBe(false);
|
|
42
|
+
expect(result.reason.message).toBe("sleep aborted");
|
|
43
43
|
});
|
|
44
44
|
it("completes successfully if not aborted", async () => {
|
|
45
45
|
const controller = new AbortController();
|
|
46
46
|
const result = await sleep(50, controller.signal);
|
|
47
|
-
expect(result.isOk
|
|
47
|
+
expect(result.isOk).toBe(true);
|
|
48
48
|
});
|
|
49
49
|
it("cleans up timeout and event listener on abort", async () => {
|
|
50
50
|
const controller = new AbortController();
|
|
51
51
|
const sleepPromise = sleep(100, controller.signal);
|
|
52
52
|
controller.abort();
|
|
53
53
|
const result = await sleepPromise;
|
|
54
|
-
expect(result.isOk
|
|
54
|
+
expect(result.isOk).toBe(false);
|
|
55
55
|
});
|
|
56
56
|
it("cleans up timeout and event listener on success", async () => {
|
|
57
57
|
const controller = new AbortController();
|
|
58
58
|
const result = await sleep(50, controller.signal);
|
|
59
|
-
expect(result.isOk
|
|
59
|
+
expect(result.isOk).toBe(true);
|
|
60
60
|
controller.abort();
|
|
61
61
|
});
|
|
62
62
|
//# sourceMappingURL=promise-sleep.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-sleep.test.js","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"promise-sleep.test.js","sourceRoot":"","sources":["../../../../src/utils/promise-sleep.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAc,MAAM,oBAAoB,CAAC;AAEvD,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAChC,CAAC,CAAC;AAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAChC,CAAC,CAAC;AAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAChC,CAAC,CAAC;AAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,UAAU,CAAC,KAAK,EAAE,CAAC;IAEnB,MAAM,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,CAAe,CAAC;IAEnE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAAA,CACrD,CAAC,CAAC;AAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE,CAAC;IACxD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAGnD,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAEzC,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAe,CAAC;IAClD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAAA,CACrD,CAAC,CAAC;AAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE,CAAC;IACtD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAElD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAChC,CAAC,CAAC;AAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAGnD,UAAU,CAAC,KAAK,EAAE,CAAC;IAEnB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;IAGlC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAAA,CAGjC,CAAC,CAAC;AAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE,CAAC;IAChE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAElD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAG/B,UAAU,CAAC,KAAK,EAAE,CAAC;AAAA,CACpB,CAAC,CAAC"}
|
package/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.4.
|
|
1
|
+
export const VERSION = "0.4.60";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adviser/cement",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.60",
|
|
4
4
|
"description": "better try/catch/finally handling",
|
|
5
5
|
"main": "./cjs/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -84,20 +84,20 @@
|
|
|
84
84
|
"yaml": "^2.7.1"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"@cloudflare/vitest-pool-workers": "^0.
|
|
88
|
-
"@eslint/js": "^9.
|
|
87
|
+
"@cloudflare/vitest-pool-workers": "^0.10.3",
|
|
88
|
+
"@eslint/js": "^9.39.1",
|
|
89
89
|
"@types/deno": "^2.3.0",
|
|
90
90
|
"@types/fs-extra": "^11.0.4",
|
|
91
91
|
"@types/node": "^24.4.0",
|
|
92
92
|
"@types/semver": "^7.7.1",
|
|
93
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
94
|
-
"@typescript-eslint/parser": "^8.
|
|
95
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
|
94
|
+
"@typescript-eslint/parser": "^8.46.3",
|
|
95
|
+
"@typescript/native-preview": "7.0.0-dev.20251102.1",
|
|
96
96
|
"@vitest/browser": "^3.2.4",
|
|
97
97
|
"@vitest/runner": "^3.2.4",
|
|
98
98
|
"cmd-ts": "^0.14.1",
|
|
99
99
|
"deno": "^2.5.1",
|
|
100
|
-
"eslint": "^9.
|
|
100
|
+
"eslint": "^9.39.1",
|
|
101
101
|
"jscodeshift": "^17.3.0",
|
|
102
102
|
"playwright": "^1.54.1",
|
|
103
103
|
"prettier": "^3.6.2",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"tsup": "^8.3.0",
|
|
106
106
|
"tsx": "^4.19.1",
|
|
107
107
|
"typescript": "^5.9.2",
|
|
108
|
-
"typescript-eslint": "^8.
|
|
108
|
+
"typescript-eslint": "^8.46.3",
|
|
109
109
|
"vite": "^7.0.4",
|
|
110
110
|
"vite-tsconfig-paths": "^5.0.1",
|
|
111
111
|
"vitest": "^3.2.4",
|
package/src/future.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Lazy } from "./resolve-once.js";
|
|
2
|
+
|
|
1
3
|
export class Future<T, CTX = void> {
|
|
2
4
|
// readonly id = Math.random();
|
|
3
5
|
readonly #promise: Promise<T>;
|
|
@@ -17,6 +19,9 @@ export class Future<T, CTX = void> {
|
|
|
17
19
|
});
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
// the id is not cryptographically secure, but good enough for transaction id
|
|
23
|
+
readonly id: () => string = Lazy(() => Math.random().toString(36).substring(2) + Date.now().toString(36));
|
|
24
|
+
|
|
20
25
|
asPromise(): Promise<T> {
|
|
21
26
|
return this.#promise;
|
|
22
27
|
}
|
package/src/poller.ts
CHANGED
|
@@ -1,64 +1,172 @@
|
|
|
1
|
+
import { Future } from "./future.js";
|
|
1
2
|
import { sleep } from "./utils/promise-sleep.js";
|
|
2
3
|
import { Writable } from "ts-essentials";
|
|
3
4
|
|
|
4
|
-
export interface
|
|
5
|
+
export interface PollerStats {
|
|
6
|
+
readonly attempts: number;
|
|
7
|
+
readonly lastIntervalMs: number;
|
|
8
|
+
readonly totalElapsedMs: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface PollWithStats {
|
|
12
|
+
readonly stats: PollerStats;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface PurPollWaitingActionResult {
|
|
5
16
|
readonly state: "waiting";
|
|
6
17
|
}
|
|
7
18
|
|
|
8
|
-
export
|
|
19
|
+
export type PollWaitingActionResult = PurPollWaitingActionResult & PollWithStats;
|
|
20
|
+
|
|
21
|
+
export interface PurPollSuccessActionResult<T> {
|
|
9
22
|
readonly state: "success";
|
|
10
23
|
readonly result: T;
|
|
11
24
|
}
|
|
12
25
|
|
|
13
|
-
export
|
|
26
|
+
export type PollSuccessActionResult<T> = PurPollSuccessActionResult<T> & PollWithStats;
|
|
27
|
+
|
|
28
|
+
export interface PurPollErrorActionResult {
|
|
14
29
|
readonly state: "error";
|
|
15
30
|
readonly error: Error;
|
|
16
31
|
}
|
|
17
32
|
|
|
18
|
-
export type
|
|
33
|
+
export type PollErrorActionResult = PurPollErrorActionResult & PollWithStats;
|
|
34
|
+
|
|
35
|
+
export interface PurPollTimeoutActionResult {
|
|
36
|
+
readonly state: "timeout";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type PollTimeoutActionResult = PurPollTimeoutActionResult & PollWithStats;
|
|
40
|
+
|
|
41
|
+
export interface PurPollAbortActionResult {
|
|
42
|
+
readonly state: "aborted";
|
|
43
|
+
readonly reason: unknown;
|
|
44
|
+
}
|
|
45
|
+
export type PollAbortActionResult = PurPollAbortActionResult & PollWithStats;
|
|
46
|
+
|
|
47
|
+
export type PollActionResult<T> =
|
|
48
|
+
| PurPollWaitingActionResult
|
|
49
|
+
| PurPollSuccessActionResult<T>
|
|
50
|
+
| PurPollErrorActionResult
|
|
51
|
+
| PurPollTimeoutActionResult
|
|
52
|
+
| PurPollAbortActionResult;
|
|
19
53
|
|
|
20
54
|
export const FOREVER = 2147483647; // Maximum setTimeout delay
|
|
21
55
|
export interface PollerOptions {
|
|
22
56
|
readonly intervalMs: number;
|
|
57
|
+
readonly actionTimeoutMs: number; // not -1 it means if a timeout occures the action is retried in the next interval
|
|
23
58
|
readonly timeoutMs: number;
|
|
24
59
|
readonly exponentialBackoff: boolean;
|
|
25
60
|
readonly abortSignal?: AbortSignal;
|
|
26
61
|
}
|
|
27
62
|
|
|
28
|
-
export type PollerResult<T> = PollSuccessActionResult<T> | PollErrorActionResult;
|
|
63
|
+
export type PollerResult<T> = PollSuccessActionResult<T> | PollErrorActionResult | PollTimeoutActionResult | PollAbortActionResult;
|
|
64
|
+
|
|
65
|
+
function doneStats(stats: Writable<PollerStats> & { startTime: number }): PollerStats {
|
|
66
|
+
stats.totalElapsedMs = Date.now() - stats.startTime;
|
|
67
|
+
return {
|
|
68
|
+
attempts: stats.attempts,
|
|
69
|
+
lastIntervalMs: stats.lastIntervalMs,
|
|
70
|
+
totalElapsedMs: stats.totalElapsedMs,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
29
73
|
|
|
30
74
|
async function interPoller<T>(
|
|
31
75
|
fn: (abortSignal?: AbortSignal) => Promise<PollActionResult<T>>,
|
|
32
|
-
options: Writable<PollerOptions
|
|
76
|
+
options: Writable<Omit<PollerOptions, "abortSignal">>,
|
|
77
|
+
stats: Writable<PollerStats> & { readonly startTime: number },
|
|
78
|
+
abortController: AbortController,
|
|
33
79
|
): Promise<PollerResult<T>> {
|
|
34
80
|
do {
|
|
35
|
-
let result: PollActionResult<T>;
|
|
81
|
+
// let result: PollActionResult<T>;
|
|
36
82
|
try {
|
|
37
|
-
|
|
83
|
+
stats.attempts += 1;
|
|
84
|
+
|
|
85
|
+
const abortCheck = new Future<PurPollAbortActionResult>();
|
|
86
|
+
function onAbort(): void {
|
|
87
|
+
abortCheck.resolve({
|
|
88
|
+
state: "aborted",
|
|
89
|
+
reason: abortController.signal.reason,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const fnAbortController = new AbortController();
|
|
93
|
+
fnAbortController.signal.addEventListener("abort", onAbort, { once: true });
|
|
94
|
+
|
|
95
|
+
const races = [
|
|
96
|
+
fn(fnAbortController.signal).finally(() => {
|
|
97
|
+
// abort all other waits
|
|
98
|
+
fnAbortController.abort();
|
|
99
|
+
}),
|
|
100
|
+
abortCheck.asPromise().finally(() => {
|
|
101
|
+
// abort all other waits
|
|
102
|
+
fnAbortController.abort();
|
|
103
|
+
}),
|
|
104
|
+
];
|
|
105
|
+
if (options.actionTimeoutMs > 0) {
|
|
106
|
+
races.push(
|
|
107
|
+
sleep(options.actionTimeoutMs, fnAbortController.signal).then((res): PollActionResult<T> => {
|
|
108
|
+
// abort all other waits
|
|
109
|
+
fnAbortController.abort(new Error("poller action timeout"));
|
|
110
|
+
switch (res.state) {
|
|
111
|
+
case "sleeped":
|
|
112
|
+
// timeout occurred but we retry
|
|
113
|
+
return { state: "waiting" as const };
|
|
114
|
+
case "error":
|
|
115
|
+
return { state: "error" as const, error: res.error };
|
|
116
|
+
case "aborted":
|
|
117
|
+
return { state: "aborted" as const, reason: res.reason };
|
|
118
|
+
}
|
|
119
|
+
throw new Error("Unreachable code in poller action timeout");
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const result = await Promise.race<PollActionResult<T>>(races).finally(() => {
|
|
124
|
+
fnAbortController.signal.removeEventListener("abort", onAbort);
|
|
125
|
+
});
|
|
38
126
|
switch (result.state) {
|
|
39
127
|
case "waiting":
|
|
40
128
|
{
|
|
41
129
|
if (options.exponentialBackoff) {
|
|
42
130
|
options.intervalMs = Math.min(options.intervalMs * 2, FOREVER);
|
|
43
131
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
132
|
+
stats.lastIntervalMs = options.intervalMs;
|
|
133
|
+
const res = await sleep(options.intervalMs, abortController.signal);
|
|
134
|
+
switch (true) {
|
|
135
|
+
case res.isAborted:
|
|
136
|
+
return {
|
|
137
|
+
state: "aborted" as const,
|
|
138
|
+
reason: res.reason,
|
|
139
|
+
stats: doneStats(stats),
|
|
140
|
+
};
|
|
141
|
+
case res.isOk:
|
|
142
|
+
break;
|
|
143
|
+
case res.isErr:
|
|
144
|
+
return {
|
|
145
|
+
state: "error",
|
|
146
|
+
error: res.error,
|
|
147
|
+
stats: doneStats(stats),
|
|
148
|
+
};
|
|
149
|
+
default:
|
|
150
|
+
throw new Error("poller interrupted during sleep");
|
|
50
151
|
}
|
|
51
152
|
}
|
|
52
153
|
break;
|
|
154
|
+
case "aborted":
|
|
155
|
+
return {
|
|
156
|
+
state: "aborted" as const,
|
|
157
|
+
reason: result.reason,
|
|
158
|
+
stats: doneStats(stats),
|
|
159
|
+
};
|
|
53
160
|
case "success":
|
|
54
|
-
return result;
|
|
161
|
+
return { ...result, stats: doneStats(stats) };
|
|
55
162
|
case "error":
|
|
56
|
-
return result;
|
|
163
|
+
return { ...result, stats: doneStats(stats) };
|
|
57
164
|
}
|
|
58
165
|
} catch (err) {
|
|
59
166
|
return {
|
|
60
167
|
state: "error",
|
|
61
168
|
error: err as Error,
|
|
169
|
+
stats: doneStats(stats),
|
|
62
170
|
};
|
|
63
171
|
}
|
|
64
172
|
// eslint-disable-next-line no-constant-condition
|
|
@@ -71,15 +179,43 @@ export async function poller<T>(
|
|
|
71
179
|
): Promise<PollerResult<T>> {
|
|
72
180
|
const options = {
|
|
73
181
|
intervalMs: 1000,
|
|
74
|
-
timeoutMs: 30000,
|
|
182
|
+
timeoutMs: 30000, // -1 means forever
|
|
183
|
+
actionTimeoutMs: -1, // forever
|
|
75
184
|
...ioptions,
|
|
76
185
|
exponentialBackoff:
|
|
77
186
|
typeof ioptions.exponentialBackoff === "boolean" ? ioptions.exponentialBackoff : ioptions.timeoutMs === FOREVER,
|
|
78
187
|
};
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
188
|
+
const stats = {
|
|
189
|
+
attempts: 0,
|
|
190
|
+
startTime: Date.now(),
|
|
191
|
+
lastIntervalMs: 0,
|
|
192
|
+
totalElapsedMs: 0,
|
|
193
|
+
};
|
|
194
|
+
const abortController = new AbortController();
|
|
195
|
+
const toRemoveEventListeners: (() => void)[] = [];
|
|
196
|
+
if (options.abortSignal) {
|
|
197
|
+
if (options.abortSignal.aborted) {
|
|
198
|
+
abortController.abort(options.abortSignal.reason);
|
|
199
|
+
} else {
|
|
200
|
+
function dispatchAbort(): void {
|
|
201
|
+
abortController.abort(options.abortSignal?.reason);
|
|
202
|
+
}
|
|
203
|
+
toRemoveEventListeners.push(() => {
|
|
204
|
+
options.abortSignal?.removeEventListener("abort", dispatchAbort);
|
|
205
|
+
});
|
|
206
|
+
options.abortSignal.addEventListener("abort", dispatchAbort, { once: true });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const races = [interPoller(fn, options, stats, abortController)];
|
|
210
|
+
if (options.timeoutMs > 0) {
|
|
211
|
+
races.push(
|
|
212
|
+
sleep(options.timeoutMs, abortController.signal)
|
|
213
|
+
.then(() => ({ state: "timeout" as const, stats: doneStats(stats) }))
|
|
214
|
+
.catch((e: Error) => ({ state: "error" as const, error: e, stats: doneStats(stats) })),
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
return Promise.race(races).finally(() => {
|
|
218
|
+
toRemoveEventListeners.forEach((fn) => fn());
|
|
219
|
+
toRemoveEventListeners.length = 0;
|
|
220
|
+
});
|
|
85
221
|
}
|