@btravstack/core 0.28.0 → 0.30.0
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/index.cjs +19 -7
- package/dist/index.d.cts +16 -2
- package/dist/index.d.mts +16 -2
- package/dist/index.mjs +20 -8
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -124,14 +124,18 @@ const noObserver = () => () => {};
|
|
|
124
124
|
* matters because the settling call sites are error paths, where a `tap` and a
|
|
125
125
|
* `tapFailure` on the same chain, or a retry, is exactly the shape that fires
|
|
126
126
|
* twice and doubles a failure count.
|
|
127
|
+
*
|
|
128
|
+
* A broken observer is dropped independently, on startup and settlement. No
|
|
129
|
+
* recursive reporting is attempted: telemetry must never alter the operation
|
|
130
|
+
* or prevent another observer from settling.
|
|
127
131
|
*/
|
|
128
132
|
const observe = (observers, operation) => {
|
|
129
|
-
const settlers = observers.map((observer) => observer(operation));
|
|
133
|
+
const settlers = observers.map((observer) => (0, unthrown.fromSafeThrowable)(observer)(operation).recoverDefect(() => (0, unthrown.Ok)(noObserver())).get());
|
|
130
134
|
let done = false;
|
|
131
135
|
return (settled) => {
|
|
132
136
|
if (done) return;
|
|
133
137
|
done = true;
|
|
134
|
-
for (const settle of settlers) settle(settled);
|
|
138
|
+
for (const settle of settlers) (0, unthrown.fromSafeThrowable)(settle)(settled).recoverDefect(() => (0, unthrown.Ok)()).get();
|
|
135
139
|
};
|
|
136
140
|
};
|
|
137
141
|
/**
|
|
@@ -143,14 +147,21 @@ const observe = (observers, operation) => {
|
|
|
143
147
|
*
|
|
144
148
|
* `settled` replaces either default where a starter has more to say: `ok`
|
|
145
149
|
* receives the value (a cache reports a hit or a miss), `failure` the
|
|
146
|
-
* `FailureView` (a store reports a missing object as an ordinary answer).
|
|
150
|
+
* `FailureView` (a store reports a missing object as an ordinary answer). A
|
|
151
|
+
* throwing shaping hook is dropped and the ordinary settlement is used.
|
|
147
152
|
*/
|
|
148
153
|
const observed = (observers, operation, call, settled = {}) => {
|
|
149
154
|
const settle = observe(observers, operation);
|
|
150
|
-
return
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}))
|
|
155
|
+
return (0, unthrown.OkAsync)().flatMap(call).tap((value) => {
|
|
156
|
+
const rendered = (0, unthrown.fromSafeThrowable)(() => settled.ok?.(value))().recoverDefect(() => (0, unthrown.Ok)(void 0)).get();
|
|
157
|
+
settle(rendered ?? { outcome: "ok" });
|
|
158
|
+
}).tapFailure((failure) => {
|
|
159
|
+
const rendered = (0, unthrown.fromSafeThrowable)(() => settled.failure?.(failure))().recoverDefect(() => (0, unthrown.Ok)(void 0)).get();
|
|
160
|
+
settle(rendered ?? {
|
|
161
|
+
outcome: "error",
|
|
162
|
+
cause: failure.tag === "Err" ? failure.error : failure.cause
|
|
163
|
+
});
|
|
164
|
+
});
|
|
154
165
|
};
|
|
155
166
|
//#endregion
|
|
156
167
|
//#region src/clock.ts
|
|
@@ -520,6 +531,7 @@ const createUnitRegistry = () => {
|
|
|
520
531
|
} finally {
|
|
521
532
|
open.delete(controller);
|
|
522
533
|
closedCount += 1;
|
|
534
|
+
controller.abort(new DOMException("The unit has settled", "AbortError"));
|
|
523
535
|
settleIfIdle();
|
|
524
536
|
}
|
|
525
537
|
})).flatMap((result) => result);
|
package/dist/index.d.cts
CHANGED
|
@@ -309,6 +309,10 @@ export declare const noObserver: () => Settle;
|
|
|
309
309
|
* matters because the settling call sites are error paths, where a `tap` and a
|
|
310
310
|
* `tapFailure` on the same chain, or a retry, is exactly the shape that fires
|
|
311
311
|
* twice and doubles a failure count.
|
|
312
|
+
*
|
|
313
|
+
* A broken observer is dropped independently, on startup and settlement. No
|
|
314
|
+
* recursive reporting is attempted: telemetry must never alter the operation
|
|
315
|
+
* or prevent another observer from settling.
|
|
312
316
|
*/
|
|
313
317
|
export declare const observe: (observers: readonly ((operation: Operation) => Settle)[], operation: Operation) => Settle;
|
|
314
318
|
/**
|
|
@@ -320,7 +324,8 @@ export declare const observe: (observers: readonly ((operation: Operation) => Se
|
|
|
320
324
|
*
|
|
321
325
|
* `settled` replaces either default where a starter has more to say: `ok`
|
|
322
326
|
* receives the value (a cache reports a hit or a miss), `failure` the
|
|
323
|
-
* `FailureView` (a store reports a missing object as an ordinary answer).
|
|
327
|
+
* `FailureView` (a store reports a missing object as an ordinary answer). A
|
|
328
|
+
* throwing shaping hook is dropped and the ordinary settlement is used.
|
|
324
329
|
*/
|
|
325
330
|
export declare const observed: <T, E>(observers: readonly ((operation: Operation) => Settle)[], operation: Operation, call: () => AsyncResult<T, E>, settled?: {
|
|
326
331
|
readonly ok?: (value: T) => Settled;
|
|
@@ -340,7 +345,11 @@ export declare const systemClock: Clock;
|
|
|
340
345
|
* record of **data about this unit**, and never a service.
|
|
341
346
|
*
|
|
342
347
|
* `signal` is the same `AbortSignal` the work callback receives — aborted at
|
|
343
|
-
* the drain deadline,
|
|
348
|
+
* the drain deadline, at once on a path that skips the drain, and once the
|
|
349
|
+
* unit has settled, so work that outlives its unit — an HTTP handler whose
|
|
350
|
+
* client disconnected — is told to stop. The settle abort's `reason` is an
|
|
351
|
+
* `AbortError` `DOMException` whose message is `"The unit has settled"`; the
|
|
352
|
+
* kernel's own aborts keep the default reason. It is here
|
|
344
353
|
* because the callback is not always where the work is: a middleware-shaped
|
|
345
354
|
* runtime opens the unit around a call whose arguments it does not own. A
|
|
346
355
|
* transport's own cancellation is a different clock, not this one.
|
|
@@ -481,6 +490,11 @@ export declare class RuntimeStartFailed extends RuntimeStartFailed_base<{
|
|
|
481
490
|
* moment it holds the unit's input; the kernel closes that scope when the
|
|
482
491
|
* unit settles, after the response is flushed. Work that subscribes to an
|
|
483
492
|
* event after a `fork` must first check whether it already fired.
|
|
493
|
+
*
|
|
494
|
+
* `signal` aborts at the drain deadline, at once when the drain is skipped,
|
|
495
|
+
* and once the unit settles — after its scope has closed — so work the
|
|
496
|
+
* runtime left running past the unit, such as an HTTP handler whose client
|
|
497
|
+
* disconnected, is told to stop. Only the first two count as `abandoned`.
|
|
484
498
|
*/
|
|
485
499
|
type RunUnit<Resolves extends AnyPort> = <T, E>(meta: UnitMeta, work: (unit: UnitHost<Resolves>, signal: AbortSignal) => ReturnType<UnitWork<T, E>>) => AsyncResult<T, E>;
|
|
486
500
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -309,6 +309,10 @@ export declare const noObserver: () => Settle;
|
|
|
309
309
|
* matters because the settling call sites are error paths, where a `tap` and a
|
|
310
310
|
* `tapFailure` on the same chain, or a retry, is exactly the shape that fires
|
|
311
311
|
* twice and doubles a failure count.
|
|
312
|
+
*
|
|
313
|
+
* A broken observer is dropped independently, on startup and settlement. No
|
|
314
|
+
* recursive reporting is attempted: telemetry must never alter the operation
|
|
315
|
+
* or prevent another observer from settling.
|
|
312
316
|
*/
|
|
313
317
|
export declare const observe: (observers: readonly ((operation: Operation) => Settle)[], operation: Operation) => Settle;
|
|
314
318
|
/**
|
|
@@ -320,7 +324,8 @@ export declare const observe: (observers: readonly ((operation: Operation) => Se
|
|
|
320
324
|
*
|
|
321
325
|
* `settled` replaces either default where a starter has more to say: `ok`
|
|
322
326
|
* receives the value (a cache reports a hit or a miss), `failure` the
|
|
323
|
-
* `FailureView` (a store reports a missing object as an ordinary answer).
|
|
327
|
+
* `FailureView` (a store reports a missing object as an ordinary answer). A
|
|
328
|
+
* throwing shaping hook is dropped and the ordinary settlement is used.
|
|
324
329
|
*/
|
|
325
330
|
export declare const observed: <T, E>(observers: readonly ((operation: Operation) => Settle)[], operation: Operation, call: () => AsyncResult<T, E>, settled?: {
|
|
326
331
|
readonly ok?: (value: T) => Settled;
|
|
@@ -340,7 +345,11 @@ export declare const systemClock: Clock;
|
|
|
340
345
|
* record of **data about this unit**, and never a service.
|
|
341
346
|
*
|
|
342
347
|
* `signal` is the same `AbortSignal` the work callback receives — aborted at
|
|
343
|
-
* the drain deadline,
|
|
348
|
+
* the drain deadline, at once on a path that skips the drain, and once the
|
|
349
|
+
* unit has settled, so work that outlives its unit — an HTTP handler whose
|
|
350
|
+
* client disconnected — is told to stop. The settle abort's `reason` is an
|
|
351
|
+
* `AbortError` `DOMException` whose message is `"The unit has settled"`; the
|
|
352
|
+
* kernel's own aborts keep the default reason. It is here
|
|
344
353
|
* because the callback is not always where the work is: a middleware-shaped
|
|
345
354
|
* runtime opens the unit around a call whose arguments it does not own. A
|
|
346
355
|
* transport's own cancellation is a different clock, not this one.
|
|
@@ -481,6 +490,11 @@ export declare class RuntimeStartFailed extends RuntimeStartFailed_base<{
|
|
|
481
490
|
* moment it holds the unit's input; the kernel closes that scope when the
|
|
482
491
|
* unit settles, after the response is flushed. Work that subscribes to an
|
|
483
492
|
* event after a `fork` must first check whether it already fired.
|
|
493
|
+
*
|
|
494
|
+
* `signal` aborts at the drain deadline, at once when the drain is skipped,
|
|
495
|
+
* and once the unit settles — after its scope has closed — so work the
|
|
496
|
+
* runtime left running past the unit, such as an HTTP handler whose client
|
|
497
|
+
* disconnected, is told to stop. Only the first two count as `abandoned`.
|
|
484
498
|
*/
|
|
485
499
|
type RunUnit<Resolves extends AnyPort> = <T, E>(meta: UnitMeta, work: (unit: UnitHost<Resolves>, signal: AbortSignal) => ReturnType<UnitWork<T, E>>) => AsyncResult<T, E>;
|
|
486
500
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Module, Port, Provider } from "@btravstack/di";
|
|
2
|
-
import { Err, Ok, OkAsync, P, TaggedError, allAsync, fromSafePromise } from "unthrown";
|
|
2
|
+
import { Err, Ok, OkAsync, P, TaggedError, allAsync, fromSafePromise, fromSafeThrowable } from "unthrown";
|
|
3
3
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
4
4
|
import { Config, ConfigInvalid, Env } from "@btravstack/config";
|
|
5
5
|
import { createServer } from "node:http";
|
|
@@ -123,14 +123,18 @@ const noObserver = () => () => {};
|
|
|
123
123
|
* matters because the settling call sites are error paths, where a `tap` and a
|
|
124
124
|
* `tapFailure` on the same chain, or a retry, is exactly the shape that fires
|
|
125
125
|
* twice and doubles a failure count.
|
|
126
|
+
*
|
|
127
|
+
* A broken observer is dropped independently, on startup and settlement. No
|
|
128
|
+
* recursive reporting is attempted: telemetry must never alter the operation
|
|
129
|
+
* or prevent another observer from settling.
|
|
126
130
|
*/
|
|
127
131
|
const observe = (observers, operation) => {
|
|
128
|
-
const settlers = observers.map((observer) => observer(operation));
|
|
132
|
+
const settlers = observers.map((observer) => fromSafeThrowable(observer)(operation).recoverDefect(() => Ok(noObserver())).get());
|
|
129
133
|
let done = false;
|
|
130
134
|
return (settled) => {
|
|
131
135
|
if (done) return;
|
|
132
136
|
done = true;
|
|
133
|
-
for (const settle of settlers) settle(settled);
|
|
137
|
+
for (const settle of settlers) fromSafeThrowable(settle)(settled).recoverDefect(() => Ok()).get();
|
|
134
138
|
};
|
|
135
139
|
};
|
|
136
140
|
/**
|
|
@@ -142,14 +146,21 @@ const observe = (observers, operation) => {
|
|
|
142
146
|
*
|
|
143
147
|
* `settled` replaces either default where a starter has more to say: `ok`
|
|
144
148
|
* receives the value (a cache reports a hit or a miss), `failure` the
|
|
145
|
-
* `FailureView` (a store reports a missing object as an ordinary answer).
|
|
149
|
+
* `FailureView` (a store reports a missing object as an ordinary answer). A
|
|
150
|
+
* throwing shaping hook is dropped and the ordinary settlement is used.
|
|
146
151
|
*/
|
|
147
152
|
const observed = (observers, operation, call, settled = {}) => {
|
|
148
153
|
const settle = observe(observers, operation);
|
|
149
|
-
return
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}))
|
|
154
|
+
return OkAsync().flatMap(call).tap((value) => {
|
|
155
|
+
const rendered = fromSafeThrowable(() => settled.ok?.(value))().recoverDefect(() => Ok(void 0)).get();
|
|
156
|
+
settle(rendered ?? { outcome: "ok" });
|
|
157
|
+
}).tapFailure((failure) => {
|
|
158
|
+
const rendered = fromSafeThrowable(() => settled.failure?.(failure))().recoverDefect(() => Ok(void 0)).get();
|
|
159
|
+
settle(rendered ?? {
|
|
160
|
+
outcome: "error",
|
|
161
|
+
cause: failure.tag === "Err" ? failure.error : failure.cause
|
|
162
|
+
});
|
|
163
|
+
});
|
|
153
164
|
};
|
|
154
165
|
//#endregion
|
|
155
166
|
//#region src/clock.ts
|
|
@@ -519,6 +530,7 @@ const createUnitRegistry = () => {
|
|
|
519
530
|
} finally {
|
|
520
531
|
open.delete(controller);
|
|
521
532
|
closedCount += 1;
|
|
533
|
+
controller.abort(new DOMException("The unit has settled", "AbortError"));
|
|
522
534
|
settleIfIdle();
|
|
523
535
|
}
|
|
524
536
|
})).flatMap((result) => result);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btravstack/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "The application kernel: boot a di module into a running process, and stop it without losing work",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"application",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"./package.json": "./package.json"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@btravstack/config": "0.
|
|
49
|
-
"@btravstack/di": "0.
|
|
48
|
+
"@btravstack/config": "0.30.0",
|
|
49
|
+
"@btravstack/di": "0.30.0",
|
|
50
50
|
"@btravstack/tsconfig": "0.4.0",
|
|
51
51
|
"@stryker-mutator/core": "10.0.0",
|
|
52
52
|
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"vitest": "5.0.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@btravstack/config": "^0.
|
|
64
|
-
"@btravstack/di": "^0.
|
|
63
|
+
"@btravstack/config": "^0.30.0",
|
|
64
|
+
"@btravstack/di": "^0.30.0",
|
|
65
65
|
"unthrown": "^5.0.0"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|