@tonalisk-labs/kit 1.0.0 → 1.0.6
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 +7 -80
- package/dist/testing/src/config-coverage.d.ts.map +1 -1
- package/dist/testing/src/config-coverage.js +3 -2
- package/dist/testing/src/config-coverage.js.map +1 -1
- package/dist/testing/src/fixtures.d.ts +9 -3
- package/dist/testing/src/fixtures.d.ts.map +1 -1
- package/dist/testing/src/fixtures.js +98 -42
- package/dist/testing/src/fixtures.js.map +1 -1
- package/dist/testing/src/floors/node.js +11 -3
- package/dist/testing/src/floors/node.js.map +1 -1
- package/dist/testing/src/stack/browsers.d.ts +13 -3
- package/dist/testing/src/stack/browsers.d.ts.map +1 -1
- package/dist/testing/src/stack/browsers.js +117 -14
- package/dist/testing/src/stack/browsers.js.map +1 -1
- package/dist/testing/src/stack/containers.d.ts +6 -2
- package/dist/testing/src/stack/containers.d.ts.map +1 -1
- package/dist/testing/src/stack/containers.js +8 -1
- package/dist/testing/src/stack/containers.js.map +1 -1
- package/dist/testing/src/stack/control.d.ts +18 -3
- package/dist/testing/src/stack/control.d.ts.map +1 -1
- package/dist/testing/src/stack/control.js +50 -10
- package/dist/testing/src/stack/control.js.map +1 -1
- package/dist/testing/src/stack/gate-member.d.ts +10 -0
- package/dist/testing/src/stack/gate-member.d.ts.map +1 -1
- package/dist/testing/src/stack/gate-member.js +68 -7
- package/dist/testing/src/stack/gate-member.js.map +1 -1
- package/dist/testing/src/stack/gate-server.d.ts +37 -4
- package/dist/testing/src/stack/gate-server.d.ts.map +1 -1
- package/dist/testing/src/stack/gate-server.js +124 -12
- package/dist/testing/src/stack/gate-server.js.map +1 -1
- package/dist/testing/src/stack/hold.d.ts +24 -3
- package/dist/testing/src/stack/hold.d.ts.map +1 -1
- package/dist/testing/src/stack/hold.js +136 -11
- package/dist/testing/src/stack/hold.js.map +1 -1
- package/dist/testing/src/stack/host.d.ts.map +1 -1
- package/dist/testing/src/stack/host.js +26 -6
- package/dist/testing/src/stack/host.js.map +1 -1
- package/dist/testing/src/stack/lock.d.ts +15 -4
- package/dist/testing/src/stack/lock.d.ts.map +1 -1
- package/dist/testing/src/stack/lock.js +47 -18
- package/dist/testing/src/stack/lock.js.map +1 -1
- package/dist/testing/src/stack/preview-child.js +14 -3
- package/dist/testing/src/stack/preview-child.js.map +1 -1
- package/dist/testing/src/stack/runtime-apple.d.ts.map +1 -1
- package/dist/testing/src/stack/runtime-apple.js +16 -0
- package/dist/testing/src/stack/runtime-apple.js.map +1 -1
- package/dist/testing/src/stack/runtime-docker.d.ts +2 -1
- package/dist/testing/src/stack/runtime-docker.d.ts.map +1 -1
- package/dist/testing/src/stack/runtime-docker.js +29 -3
- package/dist/testing/src/stack/runtime-docker.js.map +1 -1
- package/dist/testing/src/stack/runtime.d.ts +10 -0
- package/dist/testing/src/stack/runtime.d.ts.map +1 -1
- package/dist/testing/src/stack/runtime.js +1 -0
- package/dist/testing/src/stack/runtime.js.map +1 -1
- package/dist/testing/src/stack/socks.d.ts +25 -0
- package/dist/testing/src/stack/socks.d.ts.map +1 -0
- package/dist/testing/src/stack/socks.js +195 -0
- package/dist/testing/src/stack/socks.js.map +1 -0
- package/dist/testing/src/stack/stall.d.ts +36 -0
- package/dist/testing/src/stack/stall.d.ts.map +1 -0
- package/dist/testing/src/stack/stall.js +93 -0
- package/dist/testing/src/stack/stall.js.map +1 -0
- package/package.json +4 -4
- package/testing/src/config-coverage.ts +3 -2
- package/testing/src/fixtures.ts +277 -197
- package/testing/src/floors/node.ts +19 -3
- package/testing/src/stack/browsers.ts +129 -15
- package/testing/src/stack/containers.ts +14 -2
- package/testing/src/stack/control.ts +62 -11
- package/testing/src/stack/gate-member.ts +90 -8
- package/testing/src/stack/gate-server.ts +166 -21
- package/testing/src/stack/hold.ts +163 -11
- package/testing/src/stack/host.ts +32 -9
- package/testing/src/stack/lock.ts +61 -21
- package/testing/src/stack/preview-child.ts +21 -4
- package/testing/src/stack/runtime-apple.ts +20 -1
- package/testing/src/stack/runtime-docker.ts +47 -3
- package/testing/src/stack/runtime.ts +11 -0
- package/testing/src/stack/socks.ts +233 -0
- package/testing/src/stack/stall.ts +145 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// The bound on every hold's wait: a CPU turn, a stack lock, a seat. Waits fail once nothing they
|
|
2
|
+
// wait among has changed hands for a while and every holder is past its test's deadline, naming
|
|
3
|
+
// who holds what and by when: a queue that moves, or a long test inside its own timeout, never
|
|
4
|
+
// trips it, and a holder that outlives its test is a leak.
|
|
5
|
+
|
|
6
|
+
/** How long a hold's wait may see nothing change hands; and for a holder that names no deadline,
|
|
7
|
+
* as a hold outside a test, how long it may keep it still. */
|
|
8
|
+
const STALL_MS = 600_000;
|
|
9
|
+
|
|
10
|
+
/** The clock a stall is read on, and its alarm, which `after`'s answer cancels; a test's is its
|
|
11
|
+
* own. */
|
|
12
|
+
export interface Clock {
|
|
13
|
+
readonly now: () => number;
|
|
14
|
+
readonly after: (ms: number, ring: () => void) => () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Wall-clock time, as a holder's deadline is: its test's start, plus the hold waits it isn't
|
|
18
|
+
* charged, plus its timeout (control.ts). */
|
|
19
|
+
const WALL: Clock = {
|
|
20
|
+
now: () => Date.now(),
|
|
21
|
+
after: (ms, ring) => {
|
|
22
|
+
// An alarm never holds its process open: a wait still pending keeps it open itself.
|
|
23
|
+
const timer = setTimeout(ring, ms).unref();
|
|
24
|
+
return () => {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** How waits are bounded: the stillness they fail after, on its clock. */
|
|
31
|
+
export interface Stillness {
|
|
32
|
+
readonly stall: number;
|
|
33
|
+
readonly clock: Clock;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const STILLNESS: Stillness = { stall: STALL_MS, clock: WALL };
|
|
37
|
+
|
|
38
|
+
/** What a stalled wait says: what stood still, and who held and waited for it. */
|
|
39
|
+
export interface Still {
|
|
40
|
+
readonly what: string;
|
|
41
|
+
readonly named: () => string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** One resource's watch over its waits: its moves, and its waits, bounded by them. */
|
|
45
|
+
export interface Watch {
|
|
46
|
+
/** A grant or a give: the resource changed hands. */
|
|
47
|
+
readonly moved: () => void;
|
|
48
|
+
/** Counts a wait from now, which `fail` ends should the resource stand still; the answer is
|
|
49
|
+
* called once the wait ends, granted or not. */
|
|
50
|
+
readonly waiting: (fail: (error: Error) => void) => () => void;
|
|
51
|
+
/** Counts a holder, by its test's deadline, until it lets go; its test may move the deadline. */
|
|
52
|
+
readonly holding: (deadline: number | undefined) => Held;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A holder the watch counts: its deadline moved, or let go. */
|
|
56
|
+
export interface Held {
|
|
57
|
+
readonly renew: (deadline: number | undefined) => void;
|
|
58
|
+
readonly release: () => void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface Alarm {
|
|
62
|
+
at: number;
|
|
63
|
+
cancel: (() => void) | undefined;
|
|
64
|
+
readonly failing: Set<(error: Error) => void>;
|
|
65
|
+
readonly holders: Set<{ deadline: number | undefined }>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** When the resource's waits may fail: once still for the stall, and past every holder's deadline,
|
|
69
|
+
* a holder that names none keeping it still for the stall alone. */
|
|
70
|
+
const dueOf = ({ stall }: Stillness, alarm: Alarm): number =>
|
|
71
|
+
Math.max(
|
|
72
|
+
alarm.at + stall,
|
|
73
|
+
...[...alarm.holders].map(({ deadline }) => deadline ?? alarm.at + stall),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
/** Rings the stall: re-armed for the rest while the resource moved, or a holder is inside its
|
|
77
|
+
* deadline, else every pending wait fails, as all wait on the same stillness. */
|
|
78
|
+
const ringOf = (stillness: Stillness, still: Still, alarm: Alarm) => (): void => {
|
|
79
|
+
const { stall, clock } = stillness;
|
|
80
|
+
alarm.cancel = undefined;
|
|
81
|
+
if (alarm.failing.size === 0) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const left = dueOf(stillness, alarm) - clock.now();
|
|
85
|
+
if (left > 0) {
|
|
86
|
+
alarm.cancel = clock.after(left, ringOf(stillness, still, alarm));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const seconds = String(Math.round(stall / 1000));
|
|
90
|
+
const past = `${still.what} changed hands in ${seconds} s, every holder past its deadline`;
|
|
91
|
+
const error = new Error(`${past}: ${still.named()}`);
|
|
92
|
+
for (const fail of alarm.failing) {
|
|
93
|
+
fail(error);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/** A resource's watch: one alarm while any wait is pending, measuring from the later of its last
|
|
98
|
+
* move and when its waits began. A wait costs a set entry, so thousands queue as cheaply as one. */
|
|
99
|
+
export const watchOf = (stillness: Stillness, still: Still): Watch => {
|
|
100
|
+
const { stall, clock } = stillness;
|
|
101
|
+
const alarm: Alarm = {
|
|
102
|
+
at: clock.now(),
|
|
103
|
+
cancel: undefined,
|
|
104
|
+
failing: new Set(),
|
|
105
|
+
holders: new Set(),
|
|
106
|
+
};
|
|
107
|
+
const ring = ringOf(stillness, still, alarm);
|
|
108
|
+
return {
|
|
109
|
+
moved: () => {
|
|
110
|
+
alarm.at = clock.now();
|
|
111
|
+
},
|
|
112
|
+
holding: (deadline) => {
|
|
113
|
+
const holder = { deadline };
|
|
114
|
+
alarm.holders.add(holder);
|
|
115
|
+
return {
|
|
116
|
+
renew: (moved) => {
|
|
117
|
+
holder.deadline = moved;
|
|
118
|
+
// An earlier deadline brings the stall's check forward; a later one the check re-arms for.
|
|
119
|
+
if (alarm.cancel !== undefined) {
|
|
120
|
+
alarm.cancel();
|
|
121
|
+
alarm.cancel = undefined;
|
|
122
|
+
ring();
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
release: () => {
|
|
126
|
+
alarm.holders.delete(holder);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
waiting: (fail) => {
|
|
131
|
+
if (alarm.failing.size === 0) {
|
|
132
|
+
alarm.at = clock.now();
|
|
133
|
+
}
|
|
134
|
+
alarm.failing.add(fail);
|
|
135
|
+
alarm.cancel ??= clock.after(stall, ring);
|
|
136
|
+
return () => {
|
|
137
|
+
alarm.failing.delete(fail);
|
|
138
|
+
if (alarm.failing.size === 0 && alarm.cancel !== undefined) {
|
|
139
|
+
alarm.cancel();
|
|
140
|
+
alarm.cancel = undefined;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
};
|