@alpamayo-solutions/colca-client 0.36.3 → 0.36.4
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 +5 -0
- package/dist/doorbell.d.ts +31 -3
- package/dist/doorbell.d.ts.map +1 -1
- package/dist/doorbell.js +53 -13
- package/dist/doorbell.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/stream.d.ts +19 -4
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +15 -4
- package/dist/stream.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,11 @@ for await (const record of panels.follow({ bell })) {
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
`follow()` also reads from its cursor when the bell stayed silent for
|
|
31
|
+
`idleDrainMs` (five minutes by default), so a ring that was lost does not stall
|
|
32
|
+
the consumer for good. That is a recovery read, not a polling cadence: keep it
|
|
33
|
+
long. `idleDrainMs: null` waits for a ring alone.
|
|
34
|
+
|
|
30
35
|
## A producer
|
|
31
36
|
|
|
32
37
|
```ts
|
package/dist/doorbell.d.ts
CHANGED
|
@@ -6,16 +6,44 @@
|
|
|
6
6
|
* takes `generation` before it drains and afterwards waits for a newer one, so
|
|
7
7
|
* a ring that arrives while it drains is never lost. Rings are coalesced: many
|
|
8
8
|
* rings during one drain cost one more drain.
|
|
9
|
+
*
|
|
10
|
+
* A ring can still go missing before it reaches the bell: a subscription the
|
|
11
|
+
* broker dropped, a `/watch` connection that died without an error, a wiring
|
|
12
|
+
* mistake in the caller. So a consumer bounds its wait (`timeoutMs`) and reads
|
|
13
|
+
* from its cursor again when the bound passes. One lost ring then costs a
|
|
14
|
+
* delay, not a consumer that stands still until it is restarted.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* How long a consumer waits on a silent bell before it reads from its cursor
|
|
18
|
+
* anyway: five minutes, the value the Python SDK uses. It is a recovery read
|
|
19
|
+
* for a ring that never arrived, not a polling cadence — the bell is what
|
|
20
|
+
* keeps a consumer current, and this must stay long enough to say so.
|
|
9
21
|
*/
|
|
22
|
+
export declare const IDLE_DRAIN_MS = 300000;
|
|
23
|
+
/** Why a wait on the bell ended. */
|
|
24
|
+
export type Wake = "rang" | "timeout" | "aborted";
|
|
25
|
+
export interface AfterOptions {
|
|
26
|
+
/** Ends the wait with `"aborted"`. */
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
/**
|
|
29
|
+
* Ends the wait with `"timeout"` when nothing rang for this long. Greater
|
|
30
|
+
* than zero; without it the wait has no bound.
|
|
31
|
+
*/
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
}
|
|
10
34
|
export declare class Doorbell {
|
|
11
35
|
#private;
|
|
12
36
|
/** Increases with every ring. */
|
|
13
37
|
get generation(): number;
|
|
14
38
|
ring(): void;
|
|
15
39
|
/**
|
|
16
|
-
* Resolves
|
|
17
|
-
*
|
|
40
|
+
* Resolves with why the wait ended: `"rang"` once the bell rang after
|
|
41
|
+
* `since` was taken — at once when it already has —, `"aborted"` when
|
|
42
|
+
* `signal` aborts, `"timeout"` when `timeoutMs` passed without a ring. The
|
|
43
|
+
* caller reads from its cursor again on `"rang"` and on `"timeout"` alike.
|
|
44
|
+
*
|
|
45
|
+
* The options may also be the signal alone.
|
|
18
46
|
*/
|
|
19
|
-
after(since: number,
|
|
47
|
+
after(since: number, options?: AbortSignal | AfterOptions): Promise<Wake>;
|
|
20
48
|
}
|
|
21
49
|
//# sourceMappingURL=doorbell.d.ts.map
|
package/dist/doorbell.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doorbell.d.ts","sourceRoot":"","sources":["../src/doorbell.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"doorbell.d.ts","sourceRoot":"","sources":["../src/doorbell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAAU,CAAC;AAErC,oCAAoC;AACpC,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,qBAAa,QAAQ;;IAInB,iCAAiC;IACjC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,IAAI,IAAI;IAOZ;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,WAAW,GAAG,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAoC9E"}
|
package/dist/doorbell.js
CHANGED
|
@@ -6,7 +6,22 @@
|
|
|
6
6
|
* takes `generation` before it drains and afterwards waits for a newer one, so
|
|
7
7
|
* a ring that arrives while it drains is never lost. Rings are coalesced: many
|
|
8
8
|
* rings during one drain cost one more drain.
|
|
9
|
+
*
|
|
10
|
+
* A ring can still go missing before it reaches the bell: a subscription the
|
|
11
|
+
* broker dropped, a `/watch` connection that died without an error, a wiring
|
|
12
|
+
* mistake in the caller. So a consumer bounds its wait (`timeoutMs`) and reads
|
|
13
|
+
* from its cursor again when the bound passes. One lost ring then costs a
|
|
14
|
+
* delay, not a consumer that stands still until it is restarted.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* How long a consumer waits on a silent bell before it reads from its cursor
|
|
18
|
+
* anyway: five minutes, the value the Python SDK uses. It is a recovery read
|
|
19
|
+
* for a ring that never arrived, not a polling cadence — the bell is what
|
|
20
|
+
* keeps a consumer current, and this must stay long enough to say so.
|
|
9
21
|
*/
|
|
22
|
+
export const IDLE_DRAIN_MS = 300_000;
|
|
23
|
+
/** The longest delay a timer takes; a longer one would fire at once. */
|
|
24
|
+
const MAX_TIMER_MS = 2 ** 31 - 1;
|
|
10
25
|
export class Doorbell {
|
|
11
26
|
#generation = 0;
|
|
12
27
|
#waiters = new Set();
|
|
@@ -22,21 +37,46 @@ export class Doorbell {
|
|
|
22
37
|
wake();
|
|
23
38
|
}
|
|
24
39
|
/**
|
|
25
|
-
* Resolves
|
|
26
|
-
*
|
|
40
|
+
* Resolves with why the wait ended: `"rang"` once the bell rang after
|
|
41
|
+
* `since` was taken — at once when it already has —, `"aborted"` when
|
|
42
|
+
* `signal` aborts, `"timeout"` when `timeoutMs` passed without a ring. The
|
|
43
|
+
* caller reads from its cursor again on `"rang"` and on `"timeout"` alike.
|
|
44
|
+
*
|
|
45
|
+
* The options may also be the signal alone.
|
|
27
46
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
this.#waiters.delete(done);
|
|
33
|
-
signal?.removeEventListener("abort", done);
|
|
34
|
-
resolve();
|
|
35
|
-
};
|
|
36
|
-
this.#waiters.add(done);
|
|
37
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
38
|
-
});
|
|
47
|
+
after(since, options = {}) {
|
|
48
|
+
const { signal, timeoutMs } = "aborted" in options ? { signal: options } : options;
|
|
49
|
+
if (timeoutMs !== undefined && !(timeoutMs > 0)) {
|
|
50
|
+
return Promise.reject(new RangeError(`timeoutMs must be greater than zero, got ${String(timeoutMs)}`));
|
|
39
51
|
}
|
|
52
|
+
if (this.#generation !== since)
|
|
53
|
+
return Promise.resolve("rang");
|
|
54
|
+
if (signal?.aborted)
|
|
55
|
+
return Promise.resolve("aborted");
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
let timer;
|
|
58
|
+
// Whatever ends the wait takes the other two with it, so a consumer that
|
|
59
|
+
// waits for days leaves no timer and no listener behind per wait.
|
|
60
|
+
const end = (why) => {
|
|
61
|
+
this.#waiters.delete(rang);
|
|
62
|
+
signal?.removeEventListener("abort", aborted);
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
resolve(why);
|
|
65
|
+
};
|
|
66
|
+
const rang = () => {
|
|
67
|
+
end("rang");
|
|
68
|
+
};
|
|
69
|
+
const aborted = () => {
|
|
70
|
+
end("aborted");
|
|
71
|
+
};
|
|
72
|
+
this.#waiters.add(rang);
|
|
73
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
74
|
+
if (timeoutMs !== undefined) {
|
|
75
|
+
timer = setTimeout(() => {
|
|
76
|
+
end("timeout");
|
|
77
|
+
}, Math.min(timeoutMs, MAX_TIMER_MS));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
40
80
|
}
|
|
41
81
|
}
|
|
42
82
|
//# sourceMappingURL=doorbell.js.map
|
package/dist/doorbell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doorbell.js","sourceRoot":"","sources":["../src/doorbell.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"doorbell.js","sourceRoot":"","sources":["../src/doorbell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAerC,wEAAwE;AACxE,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAEjC,MAAM,OAAO,QAAQ;IACnB,WAAW,GAAG,CAAC,CAAC;IAChB,QAAQ,GAAG,IAAI,GAAG,EAAc,CAAC;IAEjC,iCAAiC;IACjC,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,MAAM,IAAI,IAAI,OAAO;YAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,KAAa,EAAE,UAAsC,EAAE;QAC3D,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAiB,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACjG,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;YAChD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,4CAA4C,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACzG,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,KAAK,KAAK;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/D,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEvD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,IAAI,KAAgD,CAAC;YACrD,yEAAyE;YACzE,kEAAkE;YAClE,MAAM,GAAG,GAAG,CAAC,GAAS,EAAQ,EAAE;gBAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9C,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,CAAC;YACf,CAAC,CAAC;YACF,MAAM,IAAI,GAAG,GAAS,EAAE;gBACtB,GAAG,CAAC,MAAM,CAAC,CAAC;YACd,CAAC,CAAC;YACF,MAAM,OAAO,GAAG,GAAS,EAAE;gBACzB,GAAG,CAAC,SAAS,CAAC,CAAC;YACjB,CAAC,CAAC;YACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE;oBACH,GAAG,CAAC,SAAS,CAAC,CAAC;gBACjB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAClC,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
* ```ts
|
|
5
5
|
* const door = new Door({ baseUrl: "http://colca", service: "my-app" });
|
|
6
6
|
* const stream = new Stream(door, "annotations", door.cursorName("panels"));
|
|
7
|
-
*
|
|
7
|
+
* const bell = new Doorbell(); // rung whenever the stream may have grown
|
|
8
|
+
* for await (const record of stream.follow({ bell })) {
|
|
8
9
|
* console.log(record.topic, record.payload);
|
|
9
10
|
* }
|
|
10
11
|
* ```
|
|
11
12
|
*/
|
|
12
13
|
export { Door, DoorError } from "./door.js";
|
|
13
14
|
export type { Attribution, DoorOptions, DoorRecord, FetchOptions, Gap, KvEntry, KvLevel, KvOptions, Page, PublishResult, SelfInfo, } from "./door.js";
|
|
14
|
-
export { Doorbell } from "./doorbell.js";
|
|
15
|
+
export { Doorbell, IDLE_DRAIN_MS } from "./doorbell.js";
|
|
16
|
+
export type { AfterOptions, Wake } from "./doorbell.js";
|
|
15
17
|
export { Stream } from "./stream.js";
|
|
16
18
|
export type { FollowOptions, StreamOptions } from "./stream.js";
|
|
17
19
|
export { DEFAULT_ROOT, TOPIC_VERSION, parseTopic, topic, topicMatches, topicPrefix } from "./topics.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,IAAI,EACJ,aAAa,EACb,QAAQ,GACT,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxG,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC5F,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAGtB,cAAc,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
* ```ts
|
|
5
5
|
* const door = new Door({ baseUrl: "http://colca", service: "my-app" });
|
|
6
6
|
* const stream = new Stream(door, "annotations", door.cursorName("panels"));
|
|
7
|
-
*
|
|
7
|
+
* const bell = new Doorbell(); // rung whenever the stream may have grown
|
|
8
|
+
* for await (const record of stream.follow({ bell })) {
|
|
8
9
|
* console.log(record.topic, record.payload);
|
|
9
10
|
* }
|
|
10
11
|
* ```
|
|
11
12
|
*/
|
|
12
13
|
export { Door, DoorError } from "./door.js";
|
|
13
|
-
export { Doorbell } from "./doorbell.js";
|
|
14
|
+
export { Doorbell, IDLE_DRAIN_MS } from "./doorbell.js";
|
|
14
15
|
export { Stream } from "./stream.js";
|
|
15
16
|
export { DEFAULT_ROOT, TOPIC_VERSION, parseTopic, topic, topicMatches, topicPrefix } from "./topics.js";
|
|
16
17
|
export { annotationIdMaterial, deriveAnnotationId, newUlid, ulidFromBytes } from "./ids.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAe5C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGxG,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG5F,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAStB,yEAAyE;AACzE,cAAc,0BAA0B,CAAC"}
|
package/dist/stream.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* must be able to run twice on the same record.
|
|
11
11
|
*/
|
|
12
12
|
import type { Door, DoorRecord, Gap, Page } from "./door.js";
|
|
13
|
-
import type
|
|
13
|
+
import { type Doorbell } from "./doorbell.js";
|
|
14
14
|
export interface StreamOptions {
|
|
15
15
|
/** Records per page, 1…1000. */
|
|
16
16
|
max?: number;
|
|
@@ -37,6 +37,14 @@ export interface FollowOptions {
|
|
|
37
37
|
*/
|
|
38
38
|
bell: Doorbell;
|
|
39
39
|
signal?: AbortSignal;
|
|
40
|
+
/**
|
|
41
|
+
* How long to wait on a silent bell before reading from the cursor anyway,
|
|
42
|
+
* `IDLE_DRAIN_MS` (five minutes) when omitted. It recovers from a ring that
|
|
43
|
+
* never arrived and is not a polling cadence: keep it long, and ring the
|
|
44
|
+
* bell for everything that can grow the stream. `null` waits for a ring
|
|
45
|
+
* alone — then a lost ring stalls the consumer until `signal` aborts.
|
|
46
|
+
*/
|
|
47
|
+
idleDrainMs?: number | null;
|
|
40
48
|
}
|
|
41
49
|
export declare class Stream {
|
|
42
50
|
#private;
|
|
@@ -60,9 +68,16 @@ export declare class Stream {
|
|
|
60
68
|
drain(signal?: AbortSignal): AsyncGenerator<DoorRecord>;
|
|
61
69
|
/**
|
|
62
70
|
* Drain now, then again after every ring of `bell`, until `signal` aborts.
|
|
63
|
-
*
|
|
64
|
-
*
|
|
71
|
+
* A ring during a drain leads to one more drain, and a consumer rings the
|
|
72
|
+
* bell on reconnect so what arrived meanwhile is read.
|
|
73
|
+
*
|
|
74
|
+
* The wait on the bell is bounded by `idleDrainMs`: when nothing rang for
|
|
75
|
+
* that long, the stream is read from its cursor once more. That read is the
|
|
76
|
+
* recovery for a ring that was lost on its way to the bell, which would
|
|
77
|
+
* otherwise leave the consumer waiting forever beside a growing stream. It
|
|
78
|
+
* is not how a consumer learns of new records, and an idle stream costs one
|
|
79
|
+
* empty page per bound.
|
|
65
80
|
*/
|
|
66
|
-
follow({ bell, signal }: FollowOptions): AsyncGenerator<DoorRecord>;
|
|
81
|
+
follow({ bell, signal, idleDrainMs }: FollowOptions): AsyncGenerator<DoorRecord>;
|
|
67
82
|
}
|
|
68
83
|
//# sourceMappingURL=stream.d.ts.map
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAgB,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAgB,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,qBAAa,MAAM;;IAEf,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAHP,IAAI,EAAE,IAAI,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACN,OAAO,GAAE,aAAkB;IAG9C,mEAAmE;IAC7D,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,4EAA4E;IACtE,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAItD,kEAAkE;IAC5D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B;;;OAGG;IACG,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAS/C,mGAAmG;IAC5F,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC;IAY9D;;;;;;;;;;;OAWG;IACI,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAA2B,EAAE,EAAE,aAAa,GAAG,cAAc,CAAC,UAAU,CAAC;CAoBxG"}
|
package/dist/stream.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* last one. A consumer that throws mid-page sees that page again, so handlers
|
|
10
10
|
* must be able to run twice on the same record.
|
|
11
11
|
*/
|
|
12
|
+
import { IDLE_DRAIN_MS } from "./doorbell.js";
|
|
12
13
|
export class Stream {
|
|
13
14
|
door;
|
|
14
15
|
name;
|
|
@@ -59,14 +60,24 @@ export class Stream {
|
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
61
62
|
* Drain now, then again after every ring of `bell`, until `signal` aborts.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
63
|
+
* A ring during a drain leads to one more drain, and a consumer rings the
|
|
64
|
+
* bell on reconnect so what arrived meanwhile is read.
|
|
65
|
+
*
|
|
66
|
+
* The wait on the bell is bounded by `idleDrainMs`: when nothing rang for
|
|
67
|
+
* that long, the stream is read from its cursor once more. That read is the
|
|
68
|
+
* recovery for a ring that was lost on its way to the bell, which would
|
|
69
|
+
* otherwise leave the consumer waiting forever beside a growing stream. It
|
|
70
|
+
* is not how a consumer learns of new records, and an idle stream costs one
|
|
71
|
+
* empty page per bound.
|
|
64
72
|
*/
|
|
65
|
-
async *follow({ bell, signal }) {
|
|
73
|
+
async *follow({ bell, signal, idleDrainMs = IDLE_DRAIN_MS }) {
|
|
74
|
+
if (idleDrainMs !== null && !(idleDrainMs > 0)) {
|
|
75
|
+
throw new RangeError(`idleDrainMs must be greater than zero, or null, got ${String(idleDrainMs)}`);
|
|
76
|
+
}
|
|
66
77
|
while (!signal?.aborted) {
|
|
67
78
|
const seen = bell.generation;
|
|
68
79
|
yield* this.drain(signal);
|
|
69
|
-
await bell.after(seen, signal);
|
|
80
|
+
await bell.after(seen, { signal, timeoutMs: idleDrainMs ?? undefined });
|
|
70
81
|
}
|
|
71
82
|
}
|
|
72
83
|
#fetchOptions(signal) {
|
package/dist/stream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAC;AAuC7D,MAAM,OAAO,MAAM;IAEE;IACR;IACA;IACQ;IAJnB,YACmB,IAAU,EAClB,IAAY,EACZ,MAAc,EACN,UAAyB,EAAE;QAH3B,SAAI,GAAJ,IAAI,CAAM;QAClB,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QACN,YAAO,GAAP,OAAO,CAAoB;IAC3C,CAAC;IAEJ,mEAAmE;IACnE,KAAK,CAAC,IAAI,CAAC,MAAoB;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,GAAG,CAAC,IAAyB;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9F,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,GAAY;QACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;YAC7D,GAAG,IAAI,CAAC,aAAa,EAAE;YACvB,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG;YAC5B,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,mGAAmG;IACnG,KAAK,CAAC,CAAC,KAAK,CAAC,MAAoB;QAC/B,SAAS,CAAC;YACR,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,GAAG;gBAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7C,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YAEpB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO;YACjC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,EAAiB;QACxE,IAAI,WAAW,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,UAAU,CAAC,uDAAuD,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;YAC7B,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC1B,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,IAAI,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,aAAa,CAAC,MAAoB;QAChC,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG;YACrB,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,MAAM;SACP,CAAC;IACJ,CAAC;CACF;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,IAAU;IAC3B,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;QAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;AAC7D,CAAC"}
|