brass-runtime 1.13.8 → 1.14.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/agent/cli/main.cjs +43 -43
- package/dist/agent/cli/main.js +2 -2
- package/dist/agent/cli/main.mjs +2 -2
- package/dist/agent/index.cjs +3 -3
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +2 -2
- package/dist/agent/index.mjs +2 -2
- package/dist/chunk-4N2JEK4H.mjs +3897 -0
- package/dist/chunk-BKBFSOGT.cjs +3897 -0
- package/dist/{chunk-XNOTJSMZ.mjs → chunk-BMRF4FN6.js} +268 -8
- package/dist/chunk-JT7D6M5H.js +3897 -0
- package/dist/{chunk-3R7ZYRK2.mjs → chunk-MQF7HZ7Y.mjs} +1 -1
- package/dist/chunk-SKVY72E5.cjs +667 -0
- package/dist/{chunk-ATHSSDUF.js → chunk-UWMMYKVK.mjs} +268 -8
- package/dist/{chunk-INZBKOHY.js → chunk-WJESVBWN.js} +1 -1
- package/dist/{chunk-XDINDYNA.cjs → chunk-XTMZTVIT.cjs} +134 -134
- package/dist/{effect-ISvXPLgc.d.ts → effect-DM56H743.d.ts} +191 -21
- package/dist/http/index.cjs +808 -140
- package/dist/http/index.d.ts +181 -8
- package/dist/http/index.js +793 -125
- package/dist/http/index.mjs +793 -125
- package/dist/index.cjs +1785 -137
- package/dist/index.d.ts +979 -36
- package/dist/index.js +1675 -27
- package/dist/index.mjs +1675 -27
- package/dist/stream-Oqe6WeLE.d.ts +173 -0
- package/package.json +1 -1
- package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
- package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
- package/dist/chunk-2P4PD6D7.cjs +0 -2557
- package/dist/chunk-7F2R7A2V.mjs +0 -2557
- package/dist/chunk-L6KKKM66.js +0 -2557
- package/dist/chunk-ZTDK2DLG.cjs +0 -407
- package/dist/stream-BvukHxCv.d.ts +0 -66
|
@@ -22,7 +22,214 @@ import {
|
|
|
22
22
|
sync,
|
|
23
23
|
unsafeGetCurrentRuntime,
|
|
24
24
|
unsafeRunFoldWithEnv
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-4N2JEK4H.mjs";
|
|
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
|
+
}
|
|
26
233
|
|
|
27
234
|
// src/core/stream/stream.ts
|
|
28
235
|
var widenOpt = (opt) => opt._tag === "None" ? none : some(opt.value);
|
|
@@ -111,6 +318,12 @@ function uncons(self) {
|
|
|
111
318
|
switch (self._tag) {
|
|
112
319
|
case "Empty":
|
|
113
320
|
return fail(none);
|
|
321
|
+
case "FromArray": {
|
|
322
|
+
const arr = self.values;
|
|
323
|
+
if (arr.length === 0) return fail(none);
|
|
324
|
+
const tail = arr.length === 1 ? EMPTY_STREAM : { _tag: "FromArray", values: arr.slice(1) };
|
|
325
|
+
return succeed([arr[0], tail]);
|
|
326
|
+
}
|
|
114
327
|
case "Emit":
|
|
115
328
|
return map(
|
|
116
329
|
mapError(self.value, (e) => some(e)),
|
|
@@ -244,6 +457,8 @@ function mapStream(self, f) {
|
|
|
244
457
|
switch (self._tag) {
|
|
245
458
|
case "Empty":
|
|
246
459
|
return emptyStream();
|
|
460
|
+
case "FromArray":
|
|
461
|
+
return { _tag: "FromArray", values: self.values.map(f) };
|
|
247
462
|
case "Emit":
|
|
248
463
|
return emitStream(map(self.value, f));
|
|
249
464
|
case "FromPull":
|
|
@@ -327,27 +542,66 @@ function foreachStream(stream, f) {
|
|
|
327
542
|
);
|
|
328
543
|
}
|
|
329
544
|
function fromArray(values) {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const head = emitStream(succeed(values[i]));
|
|
333
|
-
s = concatStream(head, s);
|
|
334
|
-
}
|
|
335
|
-
return s;
|
|
545
|
+
if (values.length === 0) return emptyStream();
|
|
546
|
+
return { _tag: "FromArray", values };
|
|
336
547
|
}
|
|
337
548
|
function collectStream(stream) {
|
|
549
|
+
const syncResult = drainStreamSyncFull(stream);
|
|
550
|
+
if (syncResult !== null) {
|
|
551
|
+
return asyncSucceed(syncResult);
|
|
552
|
+
}
|
|
338
553
|
const loop = (cur, acc) => asyncFold(
|
|
339
554
|
uncons(cur),
|
|
340
555
|
(opt) => {
|
|
341
556
|
if (opt._tag === "None") return succeed(acc);
|
|
342
557
|
return fail(opt);
|
|
343
558
|
},
|
|
344
|
-
([a, tail]) =>
|
|
559
|
+
([a, tail]) => {
|
|
560
|
+
acc.push(a);
|
|
561
|
+
return loop(tail, acc);
|
|
562
|
+
}
|
|
345
563
|
);
|
|
346
564
|
return mapError(loop(stream, []), (opt) => {
|
|
347
565
|
if (opt._tag === "Some") return opt.value;
|
|
348
566
|
throw new Error("unreachable: stream end handled as success");
|
|
349
567
|
});
|
|
350
568
|
}
|
|
569
|
+
function drainStreamSyncFull(stream) {
|
|
570
|
+
const result = [];
|
|
571
|
+
let cur = stream;
|
|
572
|
+
while (true) {
|
|
573
|
+
switch (cur._tag) {
|
|
574
|
+
case "Empty":
|
|
575
|
+
return result;
|
|
576
|
+
case "FromArray": {
|
|
577
|
+
const arr = cur.values;
|
|
578
|
+
for (let i = 0; i < arr.length; i++) {
|
|
579
|
+
result.push(arr[i]);
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
case "Emit": {
|
|
584
|
+
const zio = cur.value;
|
|
585
|
+
if (zio._tag === "Succeed") {
|
|
586
|
+
result.push(zio.value);
|
|
587
|
+
return result;
|
|
588
|
+
}
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
case "Concat": {
|
|
592
|
+
const leftItems = drainStreamSyncFull(cur.left);
|
|
593
|
+
if (leftItems === null) return null;
|
|
594
|
+
for (let i = 0; i < leftItems.length; i++) {
|
|
595
|
+
result.push(leftItems[i]);
|
|
596
|
+
}
|
|
597
|
+
cur = cur.right;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
default:
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
351
605
|
function readerStream(reader, normalizeError) {
|
|
352
606
|
const pull = async((_, cb) => {
|
|
353
607
|
reader.read().then(({ done, value }) => {
|
|
@@ -385,6 +639,12 @@ function streamFromReadableStream(body, normalizeError) {
|
|
|
385
639
|
}
|
|
386
640
|
|
|
387
641
|
export {
|
|
642
|
+
sleep,
|
|
643
|
+
timeout,
|
|
644
|
+
retry,
|
|
645
|
+
retryN,
|
|
646
|
+
retryWithBackoff,
|
|
647
|
+
makeCircuitBreaker,
|
|
388
648
|
widenOpt,
|
|
389
649
|
fromPull,
|
|
390
650
|
unwrapScoped,
|