@kensio/yulin 1.21.14 → 1.21.15
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/dist/util/background/background-clock-waits.d.ts +10 -3
- package/dist/util/background/background-clock-waits.js +11 -4
- package/dist/util/background/background-pending-tasks.d.ts +15 -9
- package/dist/util/background/background-pending-tasks.js +18 -12
- package/dist/util/background/background.d.ts +11 -3
- package/dist/util/background/background.js +14 -4
- package/dist/util/background/non-deterministic-background.d.ts +4 -0
- package/dist/util/background/non-deterministic-background.js +5 -1
- package/dist/util/clock/sim-clock.d.ts +16 -0
- package/dist/util/clock/sim-clock.js +4 -0
- package/dist/util/clock/sim-controllable-clock.d.ts +11 -0
- package/dist/util/clock/sim-controllable-clock.js +13 -0
- package/docs/services/lambda/README.md +11 -0
- package/docs/time/README.md +7 -0
- package/package.json +1 -1
|
@@ -26,10 +26,17 @@ export declare class BackgroundClockWaits {
|
|
|
26
26
|
*/
|
|
27
27
|
around<T>(wait: BackgroundClockWait, work: () => Promise<T>): Promise<T>;
|
|
28
28
|
/**
|
|
29
|
-
* The work in a set that
|
|
30
|
-
*
|
|
29
|
+
* The work in a set that completion has anything to wait for.
|
|
30
|
+
*
|
|
31
|
+
* The work asking is always left out. Waiting for the invocation the asking
|
|
32
|
+
* code is part of would be waiting for itself.
|
|
33
|
+
*
|
|
34
|
+
* Work waiting on the clock is left out where simulated time stands still,
|
|
35
|
+
* since only a caller moving the clock brings the instant it waits for, and
|
|
36
|
+
* that caller is the one waiting here. A running clock reaches the instant on
|
|
37
|
+
* its own, and this waits for the work to get there.
|
|
31
38
|
*/
|
|
32
|
-
runnable(held: ReadonlyMap<Promise<unknown>, BackgroundClockWait
|
|
39
|
+
runnable(held: ReadonlyMap<Promise<unknown>, BackgroundClockWait>, clockIsRunning?: boolean): Promise<unknown>[];
|
|
33
40
|
/**
|
|
34
41
|
* Whether the code running now is already inside outstanding work, and so
|
|
35
42
|
* already counted.
|
|
@@ -23,14 +23,21 @@ export class BackgroundClockWaits {
|
|
|
23
23
|
return await this.storage.run(wait, work);
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* The work in a set that
|
|
27
|
-
*
|
|
26
|
+
* The work in a set that completion has anything to wait for.
|
|
27
|
+
*
|
|
28
|
+
* The work asking is always left out. Waiting for the invocation the asking
|
|
29
|
+
* code is part of would be waiting for itself.
|
|
30
|
+
*
|
|
31
|
+
* Work waiting on the clock is left out where simulated time stands still,
|
|
32
|
+
* since only a caller moving the clock brings the instant it waits for, and
|
|
33
|
+
* that caller is the one waiting here. A running clock reaches the instant on
|
|
34
|
+
* its own, and this waits for the work to get there.
|
|
28
35
|
*/
|
|
29
|
-
runnable(held) {
|
|
36
|
+
runnable(held, clockIsRunning = false) {
|
|
30
37
|
const own = this.storage.getStore();
|
|
31
38
|
return held
|
|
32
39
|
.entries()
|
|
33
|
-
.filter(([, wait]) => wait
|
|
40
|
+
.filter(([, wait]) => wait !== own && (clockIsRunning || wait.count === 0))
|
|
34
41
|
.map(([promise]) => promise)
|
|
35
42
|
.toArray();
|
|
36
43
|
}
|
|
@@ -35,21 +35,27 @@ export declare class BackgroundPendingTasks {
|
|
|
35
35
|
*/
|
|
36
36
|
get size(): number;
|
|
37
37
|
/**
|
|
38
|
-
* Wait until nothing is outstanding
|
|
38
|
+
* Wait until nothing is outstanding that can still get somewhere.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* here. The loop then looks again at what is
|
|
43
|
-
* carries on is waited for again.
|
|
40
|
+
* Where simulated time stands still, work that parks on the clock ends the
|
|
41
|
+
* wait rather than extending it. Only moving the clock releases it, and
|
|
42
|
+
* moving the clock is what waits here. The loop then looks again at what is
|
|
43
|
+
* left running, so work that carries on is waited for again.
|
|
44
|
+
*
|
|
45
|
+
* A running clock reaches those instants by itself, and the work parked on
|
|
46
|
+
* them is waited for like any other. What bounds the wait is the instant
|
|
47
|
+
* itself, which arrives in the real time between here and there.
|
|
44
48
|
*/
|
|
45
|
-
complete(): Promise<void>;
|
|
49
|
+
complete(clockIsRunning?: boolean): Promise<void>;
|
|
46
50
|
/**
|
|
47
|
-
* The work completion has anything to wait for
|
|
48
|
-
* neither waiting on the clock nor waiting for completion itself.
|
|
51
|
+
* The work completion has anything to wait for.
|
|
49
52
|
*
|
|
50
53
|
* Work that asks for the simulation to settle from inside itself is left
|
|
51
54
|
* out. A handler advancing the clock is the ordinary case, and waiting for
|
|
52
55
|
* the invocation it is part of would be waiting for itself.
|
|
56
|
+
*
|
|
57
|
+
* Work waiting on the clock joins it once simulated time is running, since
|
|
58
|
+
* a running clock is what brings the instant it waits for.
|
|
53
59
|
*/
|
|
54
|
-
running(): Promise<unknown>[];
|
|
60
|
+
running(clockIsRunning?: boolean): Promise<unknown>[];
|
|
55
61
|
}
|
|
@@ -52,15 +52,19 @@ export class BackgroundPendingTasks {
|
|
|
52
52
|
return this.#held.size;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
* Wait until nothing is outstanding
|
|
55
|
+
* Wait until nothing is outstanding that can still get somewhere.
|
|
56
56
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* here. The loop then looks again at what is
|
|
60
|
-
* carries on is waited for again.
|
|
57
|
+
* Where simulated time stands still, work that parks on the clock ends the
|
|
58
|
+
* wait rather than extending it. Only moving the clock releases it, and
|
|
59
|
+
* moving the clock is what waits here. The loop then looks again at what is
|
|
60
|
+
* left running, so work that carries on is waited for again.
|
|
61
|
+
*
|
|
62
|
+
* A running clock reaches those instants by itself, and the work parked on
|
|
63
|
+
* them is waited for like any other. What bounds the wait is the instant
|
|
64
|
+
* itself, which arrives in the real time between here and there.
|
|
61
65
|
*/
|
|
62
|
-
async complete() {
|
|
63
|
-
let running = this.running();
|
|
66
|
+
async complete(clockIsRunning = false) {
|
|
67
|
+
let running = this.running(clockIsRunning);
|
|
64
68
|
while (running.length > 0) {
|
|
65
69
|
// oxlint-disable-next-line no-await-in-loop
|
|
66
70
|
const settled = await Promise.race([
|
|
@@ -68,19 +72,21 @@ export class BackgroundPendingTasks {
|
|
|
68
72
|
this.#clockWaits.next,
|
|
69
73
|
]);
|
|
70
74
|
new BackgroundSettledTasks(settled).throwFirstFailure();
|
|
71
|
-
running = this.running();
|
|
75
|
+
running = this.running(clockIsRunning);
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
75
|
-
* The work completion has anything to wait for
|
|
76
|
-
* neither waiting on the clock nor waiting for completion itself.
|
|
79
|
+
* The work completion has anything to wait for.
|
|
77
80
|
*
|
|
78
81
|
* Work that asks for the simulation to settle from inside itself is left
|
|
79
82
|
* out. A handler advancing the clock is the ordinary case, and waiting for
|
|
80
83
|
* the invocation it is part of would be waiting for itself.
|
|
84
|
+
*
|
|
85
|
+
* Work waiting on the clock joins it once simulated time is running, since
|
|
86
|
+
* a running clock is what brings the instant it waits for.
|
|
81
87
|
*/
|
|
82
|
-
running() {
|
|
83
|
-
return this.#clockWaits.runnable(this.#held);
|
|
88
|
+
running(clockIsRunning = false) {
|
|
89
|
+
return this.#clockWaits.runnable(this.#held, clockIsRunning);
|
|
84
90
|
}
|
|
85
91
|
/**
|
|
86
92
|
* Keep work outstanding under its own record until it settles.
|
|
@@ -141,9 +141,11 @@ export declare class BackgroundTasks implements BackgroundScheduler, BackgroundC
|
|
|
141
141
|
* Wait until all tasks currently scheduled have finished.
|
|
142
142
|
* If tasks schedule more tasks, this will continue draining until idle.
|
|
143
143
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
144
|
+
* What happens to work waiting on the clock follows the clock. Where
|
|
145
|
+
* simulated time stands still the work stays where it is, scheduled for an
|
|
146
|
+
* instant only a caller can bring, and this returns without it. Where
|
|
147
|
+
* simulated time runs, the instant arrives by itself and this waits for the
|
|
148
|
+
* work to get through it.
|
|
147
149
|
*/
|
|
148
150
|
complete(): Promise<void>;
|
|
149
151
|
/**
|
|
@@ -154,5 +156,11 @@ export declare class BackgroundTasks implements BackgroundScheduler, BackgroundC
|
|
|
154
156
|
* See how many tasks are waiting for simulated time to reach them.
|
|
155
157
|
*/
|
|
156
158
|
get dueTaskCount(): number;
|
|
159
|
+
/**
|
|
160
|
+
* Whether simulated time reaches a scheduled instant on its own.
|
|
161
|
+
*
|
|
162
|
+
* A clock with nothing to say about it advances, as the host clock does.
|
|
163
|
+
*/
|
|
164
|
+
private get clockIsRunning();
|
|
157
165
|
}
|
|
158
166
|
export {};
|
|
@@ -79,12 +79,14 @@ export class BackgroundTasks {
|
|
|
79
79
|
* Wait until all tasks currently scheduled have finished.
|
|
80
80
|
* If tasks schedule more tasks, this will continue draining until idle.
|
|
81
81
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* What happens to work waiting on the clock follows the clock. Where
|
|
83
|
+
* simulated time stands still the work stays where it is, scheduled for an
|
|
84
|
+
* instant only a caller can bring, and this returns without it. Where
|
|
85
|
+
* simulated time runs, the instant arrives by itself and this waits for the
|
|
86
|
+
* work to get through it.
|
|
85
87
|
*/
|
|
86
88
|
async complete() {
|
|
87
|
-
await this.pending.complete();
|
|
89
|
+
await this.pending.complete(this.clockIsRunning);
|
|
88
90
|
}
|
|
89
91
|
/**
|
|
90
92
|
* See how many outstanding background tasks are scheduled.
|
|
@@ -98,4 +100,12 @@ export class BackgroundTasks {
|
|
|
98
100
|
get dueTaskCount() {
|
|
99
101
|
return this.dueTasks.size;
|
|
100
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Whether simulated time reaches a scheduled instant on its own.
|
|
105
|
+
*
|
|
106
|
+
* A clock with nothing to say about it advances, as the host clock does.
|
|
107
|
+
*/
|
|
108
|
+
get clockIsRunning() {
|
|
109
|
+
return this.clock.advances !== false;
|
|
110
|
+
}
|
|
101
111
|
}
|
|
@@ -55,6 +55,10 @@ export declare class NonDeterministicBackgroundTasks implements BackgroundSchedu
|
|
|
55
55
|
/**
|
|
56
56
|
* Wait until all tasks currently scheduled have finished.
|
|
57
57
|
* If tasks schedule more tasks, this will continue draining until idle.
|
|
58
|
+
*
|
|
59
|
+
* Work waiting on the clock is waited for where simulated time runs, and
|
|
60
|
+
* left where it is where simulated time stands still, exactly as it is on
|
|
61
|
+
* the deterministic scheduler.
|
|
58
62
|
*/
|
|
59
63
|
complete(): Promise<void>;
|
|
60
64
|
/**
|
|
@@ -79,9 +79,13 @@ export class NonDeterministicBackgroundTasks {
|
|
|
79
79
|
/**
|
|
80
80
|
* Wait until all tasks currently scheduled have finished.
|
|
81
81
|
* If tasks schedule more tasks, this will continue draining until idle.
|
|
82
|
+
*
|
|
83
|
+
* Work waiting on the clock is waited for where simulated time runs, and
|
|
84
|
+
* left where it is where simulated time stands still, exactly as it is on
|
|
85
|
+
* the deterministic scheduler.
|
|
82
86
|
*/
|
|
83
87
|
async complete() {
|
|
84
|
-
await this.pending.complete();
|
|
88
|
+
await this.pending.complete(this.clock.advances !== false);
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
87
91
|
* See how many outstanding background tasks are scheduled.
|
|
@@ -11,6 +11,18 @@ export interface SimClock {
|
|
|
11
11
|
* Get the current time in this simulation.
|
|
12
12
|
*/
|
|
13
13
|
now(): Date;
|
|
14
|
+
/**
|
|
15
|
+
* Whether simulated time moves on this clock by itself.
|
|
16
|
+
*
|
|
17
|
+
* A scheduler reads this to decide what waiting for a simulation to settle
|
|
18
|
+
* means. Time that advances brings the instant a task is scheduled for on
|
|
19
|
+
* its own, and settling waits for that task. Time that stands still leaves
|
|
20
|
+
* the instant to whoever moves the clock, and settling leaves the task where
|
|
21
|
+
* it is.
|
|
22
|
+
*
|
|
23
|
+
* A clock that says nothing advances, as the host clock does.
|
|
24
|
+
*/
|
|
25
|
+
readonly advances?: boolean;
|
|
14
26
|
}
|
|
15
27
|
/**
|
|
16
28
|
* Clock that reports the real system time.
|
|
@@ -19,6 +31,8 @@ export interface SimClock {
|
|
|
19
31
|
* something deliberately replaces it.
|
|
20
32
|
*/
|
|
21
33
|
export declare class SimRealClock implements SimClock {
|
|
34
|
+
/** Real time moves by itself. */
|
|
35
|
+
readonly advances = true;
|
|
22
36
|
/**
|
|
23
37
|
* Get the current real system time.
|
|
24
38
|
*/
|
|
@@ -31,6 +45,8 @@ export declare class SimRealClock implements SimClock {
|
|
|
31
45
|
* reaching for a library that replaces the clock for the whole process.
|
|
32
46
|
*/
|
|
33
47
|
export declare class SimFixedClock implements SimClock {
|
|
48
|
+
/** A fixed instant is the whole of this clock. Time stands still on it. */
|
|
49
|
+
readonly advances = false;
|
|
34
50
|
private readonly instant;
|
|
35
51
|
constructor(instant: Date);
|
|
36
52
|
/**
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* something deliberately replaces it.
|
|
6
6
|
*/
|
|
7
7
|
export class SimRealClock {
|
|
8
|
+
/** Real time moves by itself. */
|
|
9
|
+
advances = true;
|
|
8
10
|
/**
|
|
9
11
|
* Get the current real system time.
|
|
10
12
|
*/
|
|
@@ -19,6 +21,8 @@ export class SimRealClock {
|
|
|
19
21
|
* reaching for a library that replaces the clock for the whole process.
|
|
20
22
|
*/
|
|
21
23
|
export class SimFixedClock {
|
|
24
|
+
/** A fixed instant is the whole of this clock. Time stands still on it. */
|
|
25
|
+
advances = false;
|
|
22
26
|
instant;
|
|
23
27
|
constructor(instant) {
|
|
24
28
|
this.instant = new Date(instant);
|
|
@@ -33,6 +33,17 @@ export declare class SimControllableClock implements SimClock {
|
|
|
33
33
|
* Whether simulated time is currently standing still.
|
|
34
34
|
*/
|
|
35
35
|
get isFrozen(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Whether simulated time moves here by itself.
|
|
38
|
+
*
|
|
39
|
+
* A frozen clock moves only where something moves it. So does a running
|
|
40
|
+
* clock over a base that stands still. The offset a running mode applies is
|
|
41
|
+
* fixed, so simulated time here moves exactly as far as the clock underneath
|
|
42
|
+
* moves, and a fixed clock underneath moves nowhere. Freezing and resuming
|
|
43
|
+
* such a clock changes which instant it reports and leaves it as still as it
|
|
44
|
+
* was.
|
|
45
|
+
*/
|
|
46
|
+
get advances(): boolean;
|
|
36
47
|
/**
|
|
37
48
|
* Stop simulated time where it currently reads.
|
|
38
49
|
*/
|
|
@@ -32,6 +32,19 @@ export class SimControllableClock {
|
|
|
32
32
|
get isFrozen() {
|
|
33
33
|
return this.mode.isFrozen;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Whether simulated time moves here by itself.
|
|
37
|
+
*
|
|
38
|
+
* A frozen clock moves only where something moves it. So does a running
|
|
39
|
+
* clock over a base that stands still. The offset a running mode applies is
|
|
40
|
+
* fixed, so simulated time here moves exactly as far as the clock underneath
|
|
41
|
+
* moves, and a fixed clock underneath moves nowhere. Freezing and resuming
|
|
42
|
+
* such a clock changes which instant it reports and leaves it as still as it
|
|
43
|
+
* was.
|
|
44
|
+
*/
|
|
45
|
+
get advances() {
|
|
46
|
+
return !this.mode.isFrozen && this.base.advances !== false;
|
|
47
|
+
}
|
|
35
48
|
/**
|
|
36
49
|
* Stop simulated time where it currently reads.
|
|
37
50
|
*/
|
|
@@ -3269,6 +3269,17 @@ An interval runs once for each period an advance covers. Advancing eleven second
|
|
|
3269
3269
|
interval runs it five times. A delay of zero, or none at all, is due at the instant it was asked
|
|
3270
3270
|
for, and a handler yielding with `setTimeout(resolve, 0)` gets going again without the clock moving.
|
|
3271
3271
|
|
|
3272
|
+
Where the clock is left running, the delay passes in real time and nothing has to move it.
|
|
3273
|
+
`simAws.backgroundTasksComplete()` waits for a handler sleeping on a clock that is moving. An S3
|
|
3274
|
+
event notification, a stream record or an asynchronous invocation whose handler uses a timer has
|
|
3275
|
+
finished by the time the drain returns, and the function's `Timeout` bounds how long that wait can
|
|
3276
|
+
last.
|
|
3277
|
+
|
|
3278
|
+
Two things leave a clock standing still. `freeze()`, `advanceBy(...)` and `setTo(...)` all leave it
|
|
3279
|
+
frozen, and a `SimAws` built on a `SimFixedClock` reports one instant however long the host runs.
|
|
3280
|
+
Under either the drain comes back while the handler sleeps, and moving the clock is what releases
|
|
3281
|
+
it.
|
|
3282
|
+
|
|
3272
3283
|
The function's `Timeout` is a deadline on the same clock. Where it arrives before the handler
|
|
3273
3284
|
answers, the invocation ends in the error the real runtime reports.
|
|
3274
3285
|
|
package/docs/time/README.md
CHANGED
|
@@ -63,6 +63,13 @@ example, a simulation advanced by one hour continues to run one hour ahead of th
|
|
|
63
63
|
|
|
64
64
|
Read `simAws.clock().isFrozen` to check the current mode.
|
|
65
65
|
|
|
66
|
+
The mode also decides what waiting for the simulation to settle means.
|
|
67
|
+
`simAws.backgroundTasksComplete()` waits for background work sleeping on a clock that is moving,
|
|
68
|
+
because the instant that work sleeps until arrives by itself. Under a clock standing still the same
|
|
69
|
+
work is left where it is, and `advanceBy(...)` or a forward `setTo(...)` is what brings the instant
|
|
70
|
+
and waits for what follows from it. A simulation built on a `SimFixedClock` stands still under a
|
|
71
|
+
running mode too, since simulated time here moves only as far as the clock underneath moves.
|
|
72
|
+
|
|
66
73
|
## Advancing time
|
|
67
74
|
|
|
68
75
|
`advanceBy(...)` accepts days, hours, minutes, seconds, and milliseconds. The values are added
|
package/package.json
CHANGED