brass-runtime 1.14.0 → 1.15.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/README.md +6 -3
- package/dist/agent/cli/main.cjs +44 -43
- package/dist/agent/cli/main.js +5 -4
- package/dist/agent/cli/main.mjs +5 -4
- package/dist/agent/index.cjs +4 -3
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +3 -2
- package/dist/agent/index.mjs +3 -2
- package/dist/{chunk-WJESVBWN.js → chunk-3QMOKAS5.js} +9 -7
- package/dist/{chunk-BMRF4FN6.js → chunk-4NHES7VK.mjs} +59 -237
- package/dist/chunk-AR22SXML.js +1043 -0
- package/dist/{chunk-4N2JEK4H.mjs → chunk-BDF4AMWX.mjs} +27 -151
- package/dist/chunk-BDYEENHT.js +224 -0
- package/dist/{chunk-JT7D6M5H.js → chunk-BMH5AV44.js} +27 -151
- package/dist/chunk-ELOOF35R.mjs +131 -0
- package/dist/chunk-JFPU5GQI.mjs +1043 -0
- package/dist/{chunk-MQF7HZ7Y.mjs → chunk-K6M7MDZ4.mjs} +9 -7
- package/dist/chunk-MS34J5LY.cjs +224 -0
- package/dist/{chunk-UWMMYKVK.mjs → chunk-PPUXIH5R.js} +59 -237
- package/dist/chunk-R3R2FVLG.cjs +131 -0
- package/dist/chunk-STVLQ3XD.cjs +489 -0
- package/dist/{chunk-BKBFSOGT.cjs → chunk-TGIFUAK4.cjs} +26 -150
- package/dist/chunk-TO7IKXYT.js +131 -0
- package/dist/chunk-UMAZLXAB.mjs +224 -0
- package/dist/{chunk-XTMZTVIT.cjs → chunk-VEZNF5GZ.cjs} +136 -134
- package/dist/chunk-XPZNXSVN.cjs +1043 -0
- package/dist/core/index.cjs +216 -0
- package/dist/core/index.d.ts +673 -0
- package/dist/core/index.js +216 -0
- package/dist/core/index.mjs +216 -0
- package/dist/{effect-DM56H743.d.ts → effect-CMOQKX8y.d.ts} +12 -11
- package/dist/http/index.cjs +2557 -235
- package/dist/http/index.d.ts +1514 -4
- package/dist/http/index.js +2549 -227
- package/dist/http/index.mjs +2549 -227
- package/dist/index.cjs +237 -1168
- package/dist/index.d.ts +7 -673
- package/dist/index.js +77 -1008
- package/dist/index.mjs +77 -1008
- package/dist/stream-FQm9h4Mg.d.ts +74 -0
- package/dist/tracing-DNT9jEbr.d.ts +106 -0
- package/package.json +11 -3
- package/dist/chunk-SKVY72E5.cjs +0 -667
- package/dist/stream-Oqe6WeLE.d.ts +0 -173
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
raceWith
|
|
3
|
+
} from "./chunk-ELOOF35R.mjs";
|
|
1
4
|
import {
|
|
2
5
|
Cause,
|
|
3
6
|
Exit,
|
|
4
7
|
Scope,
|
|
5
|
-
|
|
8
|
+
asyncEffect,
|
|
6
9
|
asyncFail,
|
|
7
10
|
asyncFlatMap,
|
|
8
11
|
asyncFold,
|
|
@@ -16,220 +19,12 @@ import {
|
|
|
16
19
|
mapError,
|
|
17
20
|
none,
|
|
18
21
|
orElseOptional,
|
|
19
|
-
raceWith,
|
|
20
22
|
some,
|
|
21
23
|
succeed,
|
|
22
24
|
sync,
|
|
23
25
|
unsafeGetCurrentRuntime,
|
|
24
26
|
unsafeRunFoldWithEnv
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
|
|
27
|
-
// src/core/runtime/combinators.ts
|
|
28
|
-
function sleep(ms) {
|
|
29
|
-
return async((_env, cb) => {
|
|
30
|
-
const delay = Math.max(0, Math.floor(ms));
|
|
31
|
-
const id = setTimeout(() => cb({ _tag: "Success", value: void 0 }), delay);
|
|
32
|
-
return () => clearTimeout(id);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function timeout(effect, ms) {
|
|
36
|
-
return async((env, cb) => {
|
|
37
|
-
let done = false;
|
|
38
|
-
let timerId;
|
|
39
|
-
let effectRunning = true;
|
|
40
|
-
timerId = setTimeout(() => {
|
|
41
|
-
if (done) return;
|
|
42
|
-
done = true;
|
|
43
|
-
effectRunning = false;
|
|
44
|
-
cb({
|
|
45
|
-
_tag: "Failure",
|
|
46
|
-
cause: { _tag: "Fail", error: { _tag: "TimeoutError", ms } }
|
|
47
|
-
});
|
|
48
|
-
}, Math.max(0, Math.floor(ms)));
|
|
49
|
-
const runtime = unsafeGetCurrentRuntime();
|
|
50
|
-
if (runtime) {
|
|
51
|
-
const fiber = runtime.fork(effect);
|
|
52
|
-
fiber.join((exit) => {
|
|
53
|
-
if (done) return;
|
|
54
|
-
done = true;
|
|
55
|
-
clearTimeout(timerId);
|
|
56
|
-
cb(exit);
|
|
57
|
-
});
|
|
58
|
-
return () => {
|
|
59
|
-
if (done) return;
|
|
60
|
-
done = true;
|
|
61
|
-
clearTimeout(timerId);
|
|
62
|
-
fiber.interrupt();
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
return () => {
|
|
66
|
-
if (done) return;
|
|
67
|
-
done = true;
|
|
68
|
-
clearTimeout(timerId);
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
function retry(effect, policy) {
|
|
73
|
-
const shouldRetry = policy.shouldRetry ?? (() => true);
|
|
74
|
-
const jitter = policy.jitter ?? "full";
|
|
75
|
-
const maxElapsedMs = policy.maxElapsedMs;
|
|
76
|
-
const computeDelay = (attempt) => {
|
|
77
|
-
const exp = policy.baseDelayMs * Math.pow(2, attempt);
|
|
78
|
-
const capped = Math.min(exp, policy.maxDelayMs);
|
|
79
|
-
if (jitter === "none") return capped;
|
|
80
|
-
return Math.floor(Math.random() * capped);
|
|
81
|
-
};
|
|
82
|
-
const loop = (attempt, startedAt) => asyncFold(
|
|
83
|
-
effect,
|
|
84
|
-
(error) => {
|
|
85
|
-
if (attempt >= policy.maxRetries) return asyncFail(error);
|
|
86
|
-
if (!shouldRetry(error, attempt)) return asyncFail(error);
|
|
87
|
-
if (maxElapsedMs !== void 0) {
|
|
88
|
-
const elapsed = performance.now() - startedAt;
|
|
89
|
-
if (elapsed >= maxElapsedMs) return asyncFail(error);
|
|
90
|
-
}
|
|
91
|
-
const delay = computeDelay(attempt);
|
|
92
|
-
return asyncFlatMap(sleep(delay), () => loop(attempt + 1, startedAt));
|
|
93
|
-
},
|
|
94
|
-
(value) => asyncSucceed(value)
|
|
95
|
-
);
|
|
96
|
-
return asyncFlatMap(
|
|
97
|
-
{ _tag: "Sync", thunk: () => performance.now() },
|
|
98
|
-
(startedAt) => loop(0, startedAt)
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
function retryN(effect, n) {
|
|
102
|
-
return retry(effect, {
|
|
103
|
-
maxRetries: n,
|
|
104
|
-
baseDelayMs: 0,
|
|
105
|
-
maxDelayMs: 0,
|
|
106
|
-
jitter: "none"
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
function retryWithBackoff(effect, opts = {}) {
|
|
110
|
-
return retry(effect, {
|
|
111
|
-
maxRetries: opts.maxRetries ?? 3,
|
|
112
|
-
baseDelayMs: opts.baseDelayMs ?? 100,
|
|
113
|
-
maxDelayMs: opts.maxDelayMs ?? 1e4,
|
|
114
|
-
maxElapsedMs: opts.maxElapsedMs,
|
|
115
|
-
shouldRetry: opts.shouldRetry,
|
|
116
|
-
jitter: "full"
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/core/runtime/circuitBreaker.ts
|
|
121
|
-
function makeCircuitBreaker(config = {}) {
|
|
122
|
-
const failureThreshold = config.failureThreshold ?? 5;
|
|
123
|
-
const resetTimeoutMs = config.resetTimeoutMs ?? 3e4;
|
|
124
|
-
const successThreshold = config.successThreshold ?? 1;
|
|
125
|
-
const isFailure = config.isFailure ?? (() => true);
|
|
126
|
-
const onStateChange = config.onStateChange;
|
|
127
|
-
let currentState = "closed";
|
|
128
|
-
let consecutiveFailures = 0;
|
|
129
|
-
let consecutiveSuccesses = 0;
|
|
130
|
-
let openedAt = 0;
|
|
131
|
-
let totalRequests = 0;
|
|
132
|
-
let totalFailures = 0;
|
|
133
|
-
let totalSuccesses = 0;
|
|
134
|
-
let totalRejected = 0;
|
|
135
|
-
let lastFailureTime = null;
|
|
136
|
-
let lastSuccessTime = null;
|
|
137
|
-
const transition = (to) => {
|
|
138
|
-
if (currentState === to) return;
|
|
139
|
-
const from = currentState;
|
|
140
|
-
currentState = to;
|
|
141
|
-
onStateChange?.(from, to);
|
|
142
|
-
};
|
|
143
|
-
const onSuccess = () => {
|
|
144
|
-
totalSuccesses++;
|
|
145
|
-
lastSuccessTime = Date.now();
|
|
146
|
-
consecutiveFailures = 0;
|
|
147
|
-
if (currentState === "half-open") {
|
|
148
|
-
consecutiveSuccesses++;
|
|
149
|
-
if (consecutiveSuccesses >= successThreshold) {
|
|
150
|
-
consecutiveSuccesses = 0;
|
|
151
|
-
transition("closed");
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
const onFailure = (error) => {
|
|
156
|
-
if (!isFailure(error)) {
|
|
157
|
-
onSuccess();
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
totalFailures++;
|
|
161
|
-
lastFailureTime = Date.now();
|
|
162
|
-
consecutiveSuccesses = 0;
|
|
163
|
-
consecutiveFailures++;
|
|
164
|
-
if (currentState === "half-open") {
|
|
165
|
-
openedAt = Date.now();
|
|
166
|
-
transition("open");
|
|
167
|
-
} else if (currentState === "closed" && consecutiveFailures >= failureThreshold) {
|
|
168
|
-
openedAt = Date.now();
|
|
169
|
-
transition("open");
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
const shouldAllow = () => {
|
|
173
|
-
switch (currentState) {
|
|
174
|
-
case "closed":
|
|
175
|
-
return true;
|
|
176
|
-
case "open": {
|
|
177
|
-
const elapsed = Date.now() - openedAt;
|
|
178
|
-
if (elapsed >= resetTimeoutMs) {
|
|
179
|
-
transition("half-open");
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
case "half-open":
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
const protect = (effect) => {
|
|
189
|
-
totalRequests++;
|
|
190
|
-
if (!shouldAllow()) {
|
|
191
|
-
totalRejected++;
|
|
192
|
-
return asyncFail({
|
|
193
|
-
_tag: "CircuitBreakerOpen",
|
|
194
|
-
openSince: openedAt,
|
|
195
|
-
failures: consecutiveFailures
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
return asyncFold(
|
|
199
|
-
effect,
|
|
200
|
-
(error) => {
|
|
201
|
-
onFailure(error);
|
|
202
|
-
return asyncFail(error);
|
|
203
|
-
},
|
|
204
|
-
(value) => {
|
|
205
|
-
onSuccess();
|
|
206
|
-
return asyncSucceed(value);
|
|
207
|
-
}
|
|
208
|
-
);
|
|
209
|
-
};
|
|
210
|
-
const stats = () => ({
|
|
211
|
-
state: currentState,
|
|
212
|
-
failures: consecutiveFailures,
|
|
213
|
-
successes: consecutiveSuccesses,
|
|
214
|
-
totalRequests,
|
|
215
|
-
totalFailures,
|
|
216
|
-
totalSuccesses,
|
|
217
|
-
totalRejected,
|
|
218
|
-
lastFailureTime,
|
|
219
|
-
lastSuccessTime
|
|
220
|
-
});
|
|
221
|
-
const reset = () => {
|
|
222
|
-
consecutiveFailures = 0;
|
|
223
|
-
consecutiveSuccesses = 0;
|
|
224
|
-
transition("closed");
|
|
225
|
-
};
|
|
226
|
-
return {
|
|
227
|
-
state: () => currentState,
|
|
228
|
-
protect,
|
|
229
|
-
stats,
|
|
230
|
-
reset
|
|
231
|
-
};
|
|
232
|
-
}
|
|
27
|
+
} from "./chunk-BDF4AMWX.mjs";
|
|
233
28
|
|
|
234
29
|
// src/core/stream/stream.ts
|
|
235
30
|
var widenOpt = (opt) => opt._tag === "None" ? none : some(opt.value);
|
|
@@ -280,7 +75,7 @@ function streamToRaceWithHandler(winnerSide, leftStream, rightStream, flip, id)
|
|
|
280
75
|
return asyncSucceed([a, next]);
|
|
281
76
|
}
|
|
282
77
|
if (exit.cause._tag === "Interrupt") {
|
|
283
|
-
return
|
|
78
|
+
return asyncEffect((_env, cb) => {
|
|
284
79
|
cb(Exit.failCause(Cause.interrupt()));
|
|
285
80
|
});
|
|
286
81
|
}
|
|
@@ -295,7 +90,7 @@ function makeMergePull(onLeft, onRight, flip, mergePullId) {
|
|
|
295
90
|
const id = ++mergePullId;
|
|
296
91
|
const onLeftHandler = streamToRaceWithHandler("L", onLeft, onRight, flip, id);
|
|
297
92
|
const onRightHandler = streamToRaceWithHandler("R", onLeft, onRight, flip, id);
|
|
298
|
-
return
|
|
93
|
+
return asyncEffect((_env, cb) => {
|
|
299
94
|
const runtime = unsafeGetCurrentRuntime();
|
|
300
95
|
const scope = new Scope(runtime);
|
|
301
96
|
const handler = raceWith(
|
|
@@ -356,7 +151,7 @@ function uncons(self) {
|
|
|
356
151
|
case "Merge":
|
|
357
152
|
return makeMergePull(self.left, self.right, self.flip, 0);
|
|
358
153
|
case "Scoped":
|
|
359
|
-
return
|
|
154
|
+
return asyncEffect((env, cb) => {
|
|
360
155
|
const runtime = unsafeGetCurrentRuntime();
|
|
361
156
|
const scope = new Scope(runtime);
|
|
362
157
|
const fiber = getCurrentFiber();
|
|
@@ -377,7 +172,7 @@ function uncons(self) {
|
|
|
377
172
|
scope.close(exit);
|
|
378
173
|
};
|
|
379
174
|
const wrap = (s) => fromPull(
|
|
380
|
-
|
|
175
|
+
asyncEffect((env2, cb2) => {
|
|
381
176
|
const pull = uncons(s);
|
|
382
177
|
unsafeRunFoldWithEnv(
|
|
383
178
|
pull,
|
|
@@ -405,7 +200,7 @@ function uncons(self) {
|
|
|
405
200
|
});
|
|
406
201
|
});
|
|
407
202
|
case "Managed":
|
|
408
|
-
return
|
|
203
|
+
return asyncEffect((env, cb) => {
|
|
409
204
|
const runtime = unsafeGetCurrentRuntime();
|
|
410
205
|
const scope = new Scope(runtime);
|
|
411
206
|
getCurrentFiber()?.addFinalizer((exit) => {
|
|
@@ -433,16 +228,19 @@ function uncons(self) {
|
|
|
433
228
|
const { stream: inner, release } = ex.value;
|
|
434
229
|
scope.addFinalizer((exit) => release(exit));
|
|
435
230
|
const wrap = (s) => fromPull(
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
231
|
+
asyncEffect((env2, cb2) => {
|
|
232
|
+
unsafeRunFoldWithEnv(
|
|
233
|
+
uncons(s),
|
|
234
|
+
env2,
|
|
235
|
+
(cause) => {
|
|
236
|
+
const ex2 = Exit.failCause(cause);
|
|
439
237
|
closeWith(ex2);
|
|
440
238
|
cb2(ex2);
|
|
441
|
-
|
|
239
|
+
},
|
|
240
|
+
([a, tail]) => {
|
|
241
|
+
cb2(Exit.succeed([a, wrap(tail)]));
|
|
442
242
|
}
|
|
443
|
-
|
|
444
|
-
cb2(Exit.succeed([a, wrap(tail)]));
|
|
445
|
-
});
|
|
243
|
+
);
|
|
446
244
|
})
|
|
447
245
|
);
|
|
448
246
|
unsafeGetCurrentRuntime().fork(uncons(wrap(inner))).join(cb);
|
|
@@ -602,49 +400,73 @@ function drainStreamSyncFull(stream) {
|
|
|
602
400
|
}
|
|
603
401
|
}
|
|
604
402
|
}
|
|
605
|
-
function readerStream(reader, normalizeError) {
|
|
606
|
-
const pull =
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
403
|
+
function readerStream(reader, normalizeError, signal) {
|
|
404
|
+
const pull = asyncEffect((_, cb) => {
|
|
405
|
+
let done = false;
|
|
406
|
+
const cleanup = () => signal?.removeEventListener("abort", abort);
|
|
407
|
+
const finish = (exit) => {
|
|
408
|
+
if (done) return;
|
|
409
|
+
done = true;
|
|
410
|
+
cleanup();
|
|
411
|
+
cb(exit);
|
|
412
|
+
};
|
|
413
|
+
const abort = () => {
|
|
414
|
+
try {
|
|
415
|
+
reader.cancel();
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
const error = typeof DOMException === "function" ? new DOMException("aborted", "AbortError") : new Error("aborted");
|
|
419
|
+
finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(error)) } });
|
|
420
|
+
};
|
|
421
|
+
if (signal?.aborted) {
|
|
422
|
+
abort();
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
426
|
+
reader.read().then(({ done: done2, value }) => {
|
|
427
|
+
if (done2) {
|
|
428
|
+
finish({ _tag: "Failure", cause: { _tag: "Fail", error: none } });
|
|
610
429
|
return;
|
|
611
430
|
}
|
|
612
|
-
|
|
431
|
+
finish({
|
|
613
432
|
_tag: "Success",
|
|
614
433
|
value: [value, fromPull(pull)]
|
|
615
434
|
});
|
|
616
435
|
}).catch((e) => {
|
|
617
|
-
|
|
436
|
+
finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(e)) } });
|
|
618
437
|
});
|
|
438
|
+
return () => {
|
|
439
|
+
cleanup();
|
|
440
|
+
try {
|
|
441
|
+
reader.cancel();
|
|
442
|
+
} catch {
|
|
443
|
+
}
|
|
444
|
+
};
|
|
619
445
|
});
|
|
620
446
|
return fromPull(pull);
|
|
621
447
|
}
|
|
622
|
-
function streamFromReadableStream(body, normalizeError) {
|
|
448
|
+
function streamFromReadableStream(body, normalizeError, options = {}) {
|
|
623
449
|
if (!body) return emptyStream();
|
|
624
450
|
let reader;
|
|
625
451
|
return unwrapScoped(
|
|
626
452
|
// acquire: produce un ZStream
|
|
627
453
|
sync(() => {
|
|
628
454
|
reader = body.getReader();
|
|
629
|
-
return readerStream(reader, normalizeError);
|
|
455
|
+
return readerStream(reader, normalizeError, options.signal);
|
|
630
456
|
}),
|
|
631
457
|
// release: se corre en fin / error / interrupción
|
|
632
458
|
() => asyncSync(() => {
|
|
633
459
|
try {
|
|
634
460
|
reader?.cancel();
|
|
635
461
|
} catch {
|
|
462
|
+
} finally {
|
|
463
|
+
options.onRelease?.();
|
|
636
464
|
}
|
|
637
465
|
})
|
|
638
466
|
);
|
|
639
467
|
}
|
|
640
468
|
|
|
641
469
|
export {
|
|
642
|
-
sleep,
|
|
643
|
-
timeout,
|
|
644
|
-
retry,
|
|
645
|
-
retryN,
|
|
646
|
-
retryWithBackoff,
|
|
647
|
-
makeCircuitBreaker,
|
|
648
470
|
widenOpt,
|
|
649
471
|
fromPull,
|
|
650
472
|
unwrapScoped,
|