@camera.ui/transport 0.0.24 → 0.0.25
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.js +11 -9
- package/dist/race.d.ts +3 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -192,7 +192,7 @@ var RaceFirstError = class extends Error {
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
function raceFirst(candidates, options = {}) {
|
|
195
|
-
const { timeoutByMode = (mode) => DEFAULT_RACE_TIMEOUT_BY_MODE[mode] ?? 5e3, shortCircuit, parentSignal, prefer } = options;
|
|
195
|
+
const { timeoutByMode = (mode) => DEFAULT_RACE_TIMEOUT_BY_MODE[mode] ?? 5e3, shortCircuit, informative, parentSignal, prefer } = options;
|
|
196
196
|
const preferGraceMs = options.preferGraceMs ?? DEFAULT_PREFER_GRACE_MS;
|
|
197
197
|
return new Promise((resolve, reject) => {
|
|
198
198
|
if (candidates.length === 0) {
|
|
@@ -215,7 +215,7 @@ function raceFirst(candidates, options = {}) {
|
|
|
215
215
|
const timers = [];
|
|
216
216
|
function cleanupAllExcept(except) {
|
|
217
217
|
for (const t of timers) clearTimeout(t);
|
|
218
|
-
for (const a of abortControllers) if (a !== except) a.abort();
|
|
218
|
+
for (const a of abortControllers) if (a !== except) a.abort("race-settled");
|
|
219
219
|
}
|
|
220
220
|
function finishSuccess(endpoint, value, except) {
|
|
221
221
|
if (settled) return;
|
|
@@ -259,7 +259,7 @@ function raceFirst(candidates, options = {}) {
|
|
|
259
259
|
const ctrl = new AbortController();
|
|
260
260
|
abortControllers.push(ctrl);
|
|
261
261
|
const delay = timeoutByMode(cand.endpoint.mode);
|
|
262
|
-
const timer = setTimeout(() => ctrl.abort(), delay);
|
|
262
|
+
const timer = setTimeout(() => ctrl.abort("race-timeout"), delay);
|
|
263
263
|
timers.push(timer);
|
|
264
264
|
cand.run(ctrl.signal).then((value) => handleSuccess(cand.endpoint, value, ctrl), (err) => {
|
|
265
265
|
if (settled) {
|
|
@@ -282,10 +282,11 @@ function raceFirst(candidates, options = {}) {
|
|
|
282
282
|
}
|
|
283
283
|
remaining--;
|
|
284
284
|
if (remaining <= 0) {
|
|
285
|
-
const
|
|
285
|
+
const usable = [...lastErrors.entries()].filter(([, e]) => {
|
|
286
286
|
if (e instanceof RaceFirstError) return e.kind !== "all-failed" || !(e.cause instanceof Error && e.cause.message === "aborted");
|
|
287
287
|
return true;
|
|
288
|
-
})
|
|
288
|
+
});
|
|
289
|
+
const [endpoint, cause] = (informative ? usable.find(([, e]) => informative(e instanceof RaceFirstError ? e.cause : e)) : void 0) ?? usable[0] ?? [cand.endpoint, finalErr];
|
|
289
290
|
finishFail(new RaceFirstError("raceFirst: all candidates failed", endpoint, cause, "all-failed"));
|
|
290
291
|
}
|
|
291
292
|
});
|
|
@@ -778,9 +779,9 @@ function attachProbeLoop(options) {
|
|
|
778
779
|
options.onProbeSuccess?.(endpoint, tokens);
|
|
779
780
|
return tokens;
|
|
780
781
|
} catch (err) {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
782
|
+
let finalErr = err;
|
|
783
|
+
if (signal.aborted && !ctrl.signal.aborted && !isProbeFailure(err)) if (signal.reason === "race-settled") finalErr = makeProbeFailure("transient", "superseded");
|
|
784
|
+
else finalErr = makeProbeFailure("transient", `timeout (${(options.timeoutByMode ?? ((m) => DEFAULT_RACE_TIMEOUT_BY_MODE[m] ?? 5e3))(endpoint.mode)}ms)`);
|
|
784
785
|
options.onProbeError?.(endpoint, finalErr);
|
|
785
786
|
throw finalErr;
|
|
786
787
|
}
|
|
@@ -792,7 +793,8 @@ function attachProbeLoop(options) {
|
|
|
792
793
|
parentSignal: ctrl.signal,
|
|
793
794
|
prefer: options.prefer,
|
|
794
795
|
preferGraceMs: options.preferGraceMs,
|
|
795
|
-
shortCircuit: (err) => isProbeFailure(err) && (err.kind === "needs-auth" || err.kind === "fatal"
|
|
796
|
+
shortCircuit: (err) => isProbeFailure(err) && (err.kind === "needs-auth" || err.kind === "fatal"),
|
|
797
|
+
informative: (cause) => !(isProbeFailure(cause) && cause.kind === "aborted")
|
|
796
798
|
});
|
|
797
799
|
if (ctrl.signal.aborted) return;
|
|
798
800
|
options.kernel.dispatch({
|
package/dist/race.d.ts
CHANGED
|
@@ -6,11 +6,12 @@ export interface RaceCandidate<T> {
|
|
|
6
6
|
readonly run: (signal: AbortSignal) => Promise<T>;
|
|
7
7
|
}
|
|
8
8
|
export interface RaceFirstOptions {
|
|
9
|
+
readonly parentSignal?: AbortSignal;
|
|
10
|
+
readonly preferGraceMs?: number;
|
|
9
11
|
readonly timeoutByMode?: TimeoutByModeFn;
|
|
10
12
|
readonly shortCircuit?: (err: unknown) => boolean;
|
|
11
|
-
readonly
|
|
13
|
+
readonly informative?: (cause: unknown) => boolean;
|
|
12
14
|
readonly prefer?: (endpoint: Endpoint) => boolean;
|
|
13
|
-
readonly preferGraceMs?: number;
|
|
14
15
|
}
|
|
15
16
|
export interface RaceFirstResult<T> {
|
|
16
17
|
readonly endpoint: Endpoint;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camera.ui/transport",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "camera.ui transport layer — framework-agnostic connection kernel, reducer state, pluggable transports (HTTP/WS/Socket.IO/NATS), lifecycle effects and worker bridge",
|
|
5
5
|
"author": "seydx (https://github.com/cameraui/clients)",
|
|
6
6
|
"type": "module",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@typescript-eslint/parser": "^8.65.0",
|
|
67
67
|
"@vue/language-core": "^3.3.8",
|
|
68
68
|
"eslint": "9.39.2",
|
|
69
|
-
"globals": "^17.
|
|
69
|
+
"globals": "^17.8.0",
|
|
70
70
|
"jiti": "^2.7.0",
|
|
71
71
|
"prettier": "^3.9.6",
|
|
72
72
|
"rimraf": "^6.1.3",
|