@rotorsoft/act 1.23.5 → 1.23.7
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/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
- package/dist/@types/builders/act-builder.d.ts.map +1 -1
- package/dist/@types/builders/state-builder.d.ts.map +1 -1
- package/dist/@types/internal/autoclose-reaction.d.ts +1 -1
- package/dist/@types/internal/autoclose-reaction.d.ts.map +1 -1
- package/dist/@types/internal/autoclose-window.d.ts +66 -0
- package/dist/@types/internal/autoclose-window.d.ts.map +1 -0
- package/dist/@types/internal/backoff.d.ts.map +1 -1
- package/dist/@types/internal/builder-utils.d.ts.map +1 -1
- package/dist/@types/internal/circuit-breaker.d.ts +1 -19
- package/dist/@types/internal/circuit-breaker.d.ts.map +1 -1
- package/dist/@types/internal/config.d.ts +139 -0
- package/dist/@types/internal/config.d.ts.map +1 -0
- package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
- package/dist/@types/internal/index.d.ts +4 -3
- package/dist/@types/internal/index.d.ts.map +1 -1
- package/dist/@types/internal/projection-fold.d.ts +2 -11
- package/dist/@types/internal/projection-fold.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +14 -3
- package/dist/@types/types/action.d.ts.map +1 -1
- package/dist/{chunk-DORIRU2I.js → chunk-C7H3GARW.js} +14 -11
- package/dist/chunk-C7H3GARW.js.map +1 -0
- package/dist/index.cjs +200 -118
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +188 -109
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +13 -10
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.js +1 -1
- package/package.json +2 -2
- package/dist/@types/internal/autoclose-config.d.ts +0 -142
- package/dist/@types/internal/autoclose-config.d.ts.map +0 -1
- package/dist/chunk-DORIRU2I.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -907,7 +907,18 @@ var InMemoryStore = class {
|
|
|
907
907
|
async query(callback, query) {
|
|
908
908
|
await sleep();
|
|
909
909
|
let count = 0;
|
|
910
|
+
let floor_index = -1;
|
|
911
|
+
if (query?.with_snaps && query.stream_exact && query.stream !== void 0 && query.after === void 0) {
|
|
912
|
+
for (let j = this._events.length - 1; j >= 0; j--) {
|
|
913
|
+
const e = this._events[j];
|
|
914
|
+
if (e.stream === query.stream && e.name === SNAP_EVENT) {
|
|
915
|
+
floor_index = j;
|
|
916
|
+
break;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
910
920
|
if (query?.backward) {
|
|
921
|
+
const floor_id = floor_index >= 0 ? this._events[floor_index].id : -1;
|
|
911
922
|
let i = (query?.before !== void 0 ? this._first_index_after(query.before - 1) : this._events.length) - 1;
|
|
912
923
|
while (i >= 0) {
|
|
913
924
|
const e = this._events[i--];
|
|
@@ -915,6 +926,7 @@ var InMemoryStore = class {
|
|
|
915
926
|
if (query?.created_before && e.created >= query.created_before)
|
|
916
927
|
continue;
|
|
917
928
|
if (query.after !== void 0 && e.id <= query.after) break;
|
|
929
|
+
if (floor_id >= 0 && e.id < floor_id) break;
|
|
918
930
|
if (query.created_after && e.created <= query.created_after) continue;
|
|
919
931
|
await Promise.resolve(
|
|
920
932
|
callback(this._with_pii(e))
|
|
@@ -923,16 +935,7 @@ var InMemoryStore = class {
|
|
|
923
935
|
if (query?.limit && count >= query.limit) break;
|
|
924
936
|
}
|
|
925
937
|
} else {
|
|
926
|
-
let i = this._first_index_after(query?.after ?? -1);
|
|
927
|
-
if (query?.with_snaps && query.stream_exact && query.stream !== void 0 && query.after === void 0 && query.created_before === void 0 && query.created_after === void 0) {
|
|
928
|
-
for (let j = this._events.length - 1; j >= 0; j--) {
|
|
929
|
-
const e = this._events[j];
|
|
930
|
-
if (e.stream === query.stream && e.name === SNAP_EVENT) {
|
|
931
|
-
i = j;
|
|
932
|
-
break;
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
}
|
|
938
|
+
let i = floor_index >= 0 ? floor_index : this._first_index_after(query?.after ?? -1);
|
|
936
939
|
while (i < this._events.length) {
|
|
937
940
|
const e = this._events[i++];
|
|
938
941
|
if (query && !this.in_query(query, e)) continue;
|
|
@@ -2041,84 +2044,8 @@ var PASS_FACTORIES = {
|
|
|
2041
2044
|
"clock-anomalies": make_clock_anomalies_pass
|
|
2042
2045
|
};
|
|
2043
2046
|
|
|
2044
|
-
// src/internal/autoclose-config.ts
|
|
2045
|
-
var import_zod5 = require("zod");
|
|
2046
|
-
var DEFAULT_AUTOCLOSE_CYCLE_MINUTES = 720;
|
|
2047
|
-
var DEFAULT_CLOSE_BATCH_SIZE = 64;
|
|
2048
|
-
var DEFAULT_CLOSE_YIELD_MS = 0;
|
|
2049
|
-
var DEFAULT_AUTOCLOSE_WINDOW_TZ = "UTC";
|
|
2050
|
-
function is_valid_time_zone(tz) {
|
|
2051
|
-
try {
|
|
2052
|
-
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
2053
|
-
return true;
|
|
2054
|
-
} catch {
|
|
2055
|
-
return false;
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
var AutocloseWindowSchema = import_zod5.z.object({
|
|
2059
|
-
start: import_zod5.z.number().int().min(0).max(23, { message: "autocloseWindow.start must be an hour in [0, 23]" }),
|
|
2060
|
-
end: import_zod5.z.number().int().min(0).max(23, { message: "autocloseWindow.end must be an hour in [0, 23]" }),
|
|
2061
|
-
timeZone: import_zod5.z.string().refine(is_valid_time_zone, {
|
|
2062
|
-
message: "autocloseWindow.timeZone must be a valid IANA time zone"
|
|
2063
|
-
}).default(DEFAULT_AUTOCLOSE_WINDOW_TZ)
|
|
2064
|
-
}).refine((w) => w.start !== w.end, {
|
|
2065
|
-
message: "autocloseWindow.start and end must differ \u2014 an empty window disables autoclose"
|
|
2066
|
-
});
|
|
2067
|
-
var AutocloseOptionsSchema = import_zod5.z.object({
|
|
2068
|
-
autocloseCycleMinutes: import_zod5.z.number().int().min(1).max(1440).default(DEFAULT_AUTOCLOSE_CYCLE_MINUTES),
|
|
2069
|
-
closeBatchSize: import_zod5.z.number().int().min(1).max(1024).default(DEFAULT_CLOSE_BATCH_SIZE),
|
|
2070
|
-
closeYieldMs: import_zod5.z.number().min(0).max(1e3).default(DEFAULT_CLOSE_YIELD_MS),
|
|
2071
|
-
closeOnError: import_zod5.z.boolean().default(false),
|
|
2072
|
-
autocloseWindow: AutocloseWindowSchema.optional()
|
|
2073
|
-
});
|
|
2074
|
-
function resolveAutocloseConfig(options) {
|
|
2075
|
-
return AutocloseOptionsSchema.parse({
|
|
2076
|
-
autocloseCycleMinutes: options?.autocloseCycleMinutes,
|
|
2077
|
-
closeBatchSize: options?.closeBatchSize,
|
|
2078
|
-
closeYieldMs: options?.closeYieldMs,
|
|
2079
|
-
closeOnError: options?.closeOnError,
|
|
2080
|
-
autocloseWindow: options?.autocloseWindow
|
|
2081
|
-
});
|
|
2082
|
-
}
|
|
2083
|
-
function hour_in_zone(now, timeZone) {
|
|
2084
|
-
const parts = new Intl.DateTimeFormat("en-US", {
|
|
2085
|
-
timeZone,
|
|
2086
|
-
hour: "2-digit",
|
|
2087
|
-
hourCycle: "h23"
|
|
2088
|
-
}).formatToParts(now);
|
|
2089
|
-
return Number(parts.find((p) => p.type === "hour")?.value);
|
|
2090
|
-
}
|
|
2091
|
-
function hour_in_range(hour, start, end) {
|
|
2092
|
-
return start < end ? hour >= start && hour < end : hour >= start || hour < end;
|
|
2093
|
-
}
|
|
2094
|
-
function is_dst_gap_open(now, timeZone, start) {
|
|
2095
|
-
const hour = hour_in_zone(now, timeZone);
|
|
2096
|
-
if (hour <= start) return false;
|
|
2097
|
-
const prev = hour_in_zone(new Date(now.getTime() - 36e5), timeZone);
|
|
2098
|
-
return prev === start - 1 && hour === start + 1;
|
|
2099
|
-
}
|
|
2100
|
-
function in_autoclose_window(window, now) {
|
|
2101
|
-
if (!window) return true;
|
|
2102
|
-
const hour = hour_in_zone(now, window.timeZone);
|
|
2103
|
-
return hour_in_range(hour, window.start, window.end) || is_dst_gap_open(now, window.timeZone, window.start);
|
|
2104
|
-
}
|
|
2105
|
-
function next_window_open(window, now) {
|
|
2106
|
-
const start_ms = now.getTime();
|
|
2107
|
-
for (let h = 0; h <= 48; h++) {
|
|
2108
|
-
const candidate = new Date(start_ms + h * 36e5);
|
|
2109
|
-
if (hour_in_zone(candidate, window.timeZone) === window.start)
|
|
2110
|
-
return candidate;
|
|
2111
|
-
const boundary = new Date(
|
|
2112
|
-
candidate.getTime() - candidate.getTime() % 36e5
|
|
2113
|
-
);
|
|
2114
|
-
if (is_dst_gap_open(boundary, window.timeZone, window.start))
|
|
2115
|
-
return boundary;
|
|
2116
|
-
}
|
|
2117
|
-
return new Date(start_ms + 864e5);
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
2047
|
// src/internal/autoclose-policy.ts
|
|
2121
|
-
var
|
|
2048
|
+
var import_zod5 = require("zod");
|
|
2122
2049
|
var DAY_MS = 864e5;
|
|
2123
2050
|
var MIN_AFTER_DAYS = 1 / 1440;
|
|
2124
2051
|
var MIN_KEEP_DAYS = 1;
|
|
@@ -2128,21 +2055,21 @@ function days_after(date, days) {
|
|
|
2128
2055
|
function days_before_now(days) {
|
|
2129
2056
|
return new Date(Date.now() - days * DAY_MS);
|
|
2130
2057
|
}
|
|
2131
|
-
var window_schema = (field, min_days, floor) =>
|
|
2132
|
-
days:
|
|
2058
|
+
var window_schema = (field, min_days, floor) => import_zod5.z.object({
|
|
2059
|
+
days: import_zod5.z.number({ message: `autocloses: ${field}.days must be a number` }).positive(`autocloses: ${field}.days must be > 0`)
|
|
2133
2060
|
}).refine((o) => o.days >= min_days, {
|
|
2134
2061
|
message: `autocloses: ${field} resolves to < ${floor}, which is too short to be a meaningful retention window`
|
|
2135
2062
|
});
|
|
2136
2063
|
var AfterSchema = window_schema("after", MIN_AFTER_DAYS, "one minute");
|
|
2137
2064
|
var KeepSchema = window_schema("keep", MIN_KEEP_DAYS, "one day");
|
|
2138
|
-
var IsSchema =
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2065
|
+
var IsSchema = import_zod5.z.union([
|
|
2066
|
+
import_zod5.z.string().min(1, "autocloses: is must be a non-empty event name"),
|
|
2067
|
+
import_zod5.z.array(
|
|
2068
|
+
import_zod5.z.string().min(1, "autocloses: is entries must be non-empty event names")
|
|
2142
2069
|
).min(1, "autocloses: is must include at least one event name").readonly()
|
|
2143
2070
|
]);
|
|
2144
|
-
var ReachesSchema =
|
|
2145
|
-
var OrBlockSchema =
|
|
2071
|
+
var ReachesSchema = import_zod5.z.number({ message: "autocloses: reaches must be a number" }).int("autocloses: reaches must be an integer").min(1, "autocloses: reaches must be >= 1");
|
|
2072
|
+
var OrBlockSchema = import_zod5.z.object({
|
|
2146
2073
|
after: AfterSchema.optional(),
|
|
2147
2074
|
is: IsSchema.optional(),
|
|
2148
2075
|
reaches: ReachesSchema.optional()
|
|
@@ -2152,7 +2079,7 @@ var OrBlockSchema = import_zod6.z.object({
|
|
|
2152
2079
|
message: "autocloses: `or` block must include at least one of after / is / reaches"
|
|
2153
2080
|
}
|
|
2154
2081
|
);
|
|
2155
|
-
var AutoclosePolicySchema =
|
|
2082
|
+
var AutoclosePolicySchema = import_zod5.z.object({
|
|
2156
2083
|
after: AfterSchema.optional(),
|
|
2157
2084
|
is: IsSchema.optional(),
|
|
2158
2085
|
reaches: ReachesSchema.optional(),
|
|
@@ -2208,6 +2135,44 @@ function compile_autoclose_policy(options) {
|
|
|
2208
2135
|
};
|
|
2209
2136
|
}
|
|
2210
2137
|
|
|
2138
|
+
// src/internal/autoclose-window.ts
|
|
2139
|
+
function hour_in_zone(now, timeZone) {
|
|
2140
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
2141
|
+
timeZone,
|
|
2142
|
+
hour: "2-digit",
|
|
2143
|
+
hourCycle: "h23"
|
|
2144
|
+
}).formatToParts(now);
|
|
2145
|
+
return Number(parts.find((p) => p.type === "hour")?.value);
|
|
2146
|
+
}
|
|
2147
|
+
function hour_in_range(hour, start, end) {
|
|
2148
|
+
return start < end ? hour >= start && hour < end : hour >= start || hour < end;
|
|
2149
|
+
}
|
|
2150
|
+
function is_dst_gap_open(now, timeZone, start) {
|
|
2151
|
+
const hour = hour_in_zone(now, timeZone);
|
|
2152
|
+
if (hour <= start) return false;
|
|
2153
|
+
const prev = hour_in_zone(new Date(now.getTime() - 36e5), timeZone);
|
|
2154
|
+
return prev === start - 1 && hour === start + 1;
|
|
2155
|
+
}
|
|
2156
|
+
function in_autoclose_window(window, now) {
|
|
2157
|
+
if (!window) return true;
|
|
2158
|
+
const hour = hour_in_zone(now, window.timeZone);
|
|
2159
|
+
return hour_in_range(hour, window.start, window.end) || is_dst_gap_open(now, window.timeZone, window.start);
|
|
2160
|
+
}
|
|
2161
|
+
function next_window_open(window, now) {
|
|
2162
|
+
const start_ms = now.getTime();
|
|
2163
|
+
for (let h = 0; h <= 48; h++) {
|
|
2164
|
+
const candidate = new Date(start_ms + h * 36e5);
|
|
2165
|
+
if (hour_in_zone(candidate, window.timeZone) === window.start)
|
|
2166
|
+
return candidate;
|
|
2167
|
+
const boundary = new Date(
|
|
2168
|
+
candidate.getTime() - candidate.getTime() % 36e5
|
|
2169
|
+
);
|
|
2170
|
+
if (is_dst_gap_open(boundary, window.timeZone, window.start))
|
|
2171
|
+
return boundary;
|
|
2172
|
+
}
|
|
2173
|
+
return new Date(start_ms + 864e5);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2211
2176
|
// src/internal/close-signal.ts
|
|
2212
2177
|
var CloseSignal = class extends Error {
|
|
2213
2178
|
/**
|
|
@@ -2388,6 +2353,123 @@ function classify_registry(registry, states) {
|
|
|
2388
2353
|
};
|
|
2389
2354
|
}
|
|
2390
2355
|
|
|
2356
|
+
// src/internal/config.ts
|
|
2357
|
+
var import_zod6 = require("zod");
|
|
2358
|
+
var BackoffOptionsSchema = import_zod6.z.object({
|
|
2359
|
+
strategy: import_zod6.z.enum(["fixed", "linear", "exponential"]),
|
|
2360
|
+
baseMs: import_zod6.z.number().min(0),
|
|
2361
|
+
maxMs: import_zod6.z.number().gt(0).optional(),
|
|
2362
|
+
jitter: import_zod6.z.boolean().optional()
|
|
2363
|
+
});
|
|
2364
|
+
var ReactionOptionsSchema = import_zod6.z.object({
|
|
2365
|
+
blockOnError: import_zod6.z.boolean(),
|
|
2366
|
+
maxRetries: import_zod6.z.number().int().min(0),
|
|
2367
|
+
backoff: BackoffOptionsSchema.optional()
|
|
2368
|
+
});
|
|
2369
|
+
function resolveReactionConfig(options) {
|
|
2370
|
+
return ReactionOptionsSchema.parse(options);
|
|
2371
|
+
}
|
|
2372
|
+
var ActionOptionsSchema = import_zod6.z.object({
|
|
2373
|
+
maxRetries: import_zod6.z.number().int().min(0).optional(),
|
|
2374
|
+
backoff: BackoffOptionsSchema.optional()
|
|
2375
|
+
});
|
|
2376
|
+
function resolveActionConfig(options) {
|
|
2377
|
+
return ActionOptionsSchema.parse(options);
|
|
2378
|
+
}
|
|
2379
|
+
var LaneConfigSchema = import_zod6.z.object({
|
|
2380
|
+
name: import_zod6.z.string().min(1),
|
|
2381
|
+
leaseMillis: import_zod6.z.number().min(0).optional(),
|
|
2382
|
+
streamLimit: import_zod6.z.number().int().min(0).optional(),
|
|
2383
|
+
cycleMs: import_zod6.z.number().min(0).optional()
|
|
2384
|
+
});
|
|
2385
|
+
function resolveLaneConfig(options) {
|
|
2386
|
+
LaneConfigSchema.parse(options);
|
|
2387
|
+
return options;
|
|
2388
|
+
}
|
|
2389
|
+
var DrainOptionsSchema = import_zod6.z.object({
|
|
2390
|
+
streamLimit: import_zod6.z.number().int().min(0).optional(),
|
|
2391
|
+
eventLimit: import_zod6.z.number().int().min(0).optional(),
|
|
2392
|
+
leaseMillis: import_zod6.z.number().min(0).optional()
|
|
2393
|
+
});
|
|
2394
|
+
function resolveDrainConfig(options) {
|
|
2395
|
+
if (options === void 0) return void 0;
|
|
2396
|
+
DrainOptionsSchema.parse(options);
|
|
2397
|
+
return options;
|
|
2398
|
+
}
|
|
2399
|
+
var SettleOptionsSchema = DrainOptionsSchema.extend({
|
|
2400
|
+
debounceMs: import_zod6.z.number().min(0).optional(),
|
|
2401
|
+
// `maxPasses` defaults to Infinity (no cap) when omitted; a present value is
|
|
2402
|
+
// a non-negative integer — `0` is legal and means "run no passes".
|
|
2403
|
+
maxPasses: import_zod6.z.number().int().min(0).optional()
|
|
2404
|
+
}).loose();
|
|
2405
|
+
function resolveSettleConfig(options) {
|
|
2406
|
+
if (options === void 0) return void 0;
|
|
2407
|
+
SettleOptionsSchema.parse(options);
|
|
2408
|
+
return options;
|
|
2409
|
+
}
|
|
2410
|
+
var ActOptionsSchema = import_zod6.z.object({
|
|
2411
|
+
maxSubscribedStreams: import_zod6.z.number().int().min(1).optional(),
|
|
2412
|
+
settleDebounceMs: import_zod6.z.number().int().min(0).optional()
|
|
2413
|
+
}).loose();
|
|
2414
|
+
function resolveActConfig(options) {
|
|
2415
|
+
if (options === void 0) return void 0;
|
|
2416
|
+
ActOptionsSchema.parse(options);
|
|
2417
|
+
return options;
|
|
2418
|
+
}
|
|
2419
|
+
var DEFAULT_AUTOCLOSE_CYCLE_MINUTES = 720;
|
|
2420
|
+
var DEFAULT_CLOSE_BATCH_SIZE = 64;
|
|
2421
|
+
var DEFAULT_CLOSE_YIELD_MS = 0;
|
|
2422
|
+
var DEFAULT_AUTOCLOSE_WINDOW_TZ = "UTC";
|
|
2423
|
+
function is_valid_time_zone(tz) {
|
|
2424
|
+
try {
|
|
2425
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
2426
|
+
return true;
|
|
2427
|
+
} catch {
|
|
2428
|
+
return false;
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
var AutocloseWindowSchema = import_zod6.z.object({
|
|
2432
|
+
start: import_zod6.z.number().int().min(0).max(23, { message: "autocloseWindow.start must be an hour in [0, 23]" }),
|
|
2433
|
+
end: import_zod6.z.number().int().min(0).max(23, { message: "autocloseWindow.end must be an hour in [0, 23]" }),
|
|
2434
|
+
timeZone: import_zod6.z.string().refine(is_valid_time_zone, {
|
|
2435
|
+
message: "autocloseWindow.timeZone must be a valid IANA time zone"
|
|
2436
|
+
}).default(DEFAULT_AUTOCLOSE_WINDOW_TZ)
|
|
2437
|
+
}).refine((w) => w.start !== w.end, {
|
|
2438
|
+
message: "autocloseWindow.start and end must differ \u2014 an empty window disables autoclose"
|
|
2439
|
+
});
|
|
2440
|
+
var AutocloseOptionsSchema = import_zod6.z.object({
|
|
2441
|
+
autocloseCycleMinutes: import_zod6.z.number().int().min(1).max(1440).default(DEFAULT_AUTOCLOSE_CYCLE_MINUTES),
|
|
2442
|
+
closeBatchSize: import_zod6.z.number().int().min(1).max(1024).default(DEFAULT_CLOSE_BATCH_SIZE),
|
|
2443
|
+
closeYieldMs: import_zod6.z.number().min(0).max(1e3).default(DEFAULT_CLOSE_YIELD_MS),
|
|
2444
|
+
closeOnError: import_zod6.z.boolean().default(false),
|
|
2445
|
+
autocloseWindow: AutocloseWindowSchema.optional()
|
|
2446
|
+
});
|
|
2447
|
+
function resolveAutocloseConfig(options) {
|
|
2448
|
+
return AutocloseOptionsSchema.parse({
|
|
2449
|
+
autocloseCycleMinutes: options?.autocloseCycleMinutes,
|
|
2450
|
+
closeBatchSize: options?.closeBatchSize,
|
|
2451
|
+
closeYieldMs: options?.closeYieldMs,
|
|
2452
|
+
closeOnError: options?.closeOnError,
|
|
2453
|
+
autocloseWindow: options?.autocloseWindow
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
var DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;
|
|
2457
|
+
var DEFAULT_CIRCUIT_COOLDOWN_MS = 3e4;
|
|
2458
|
+
var CircuitBreakerOptionsSchema = import_zod6.z.object({
|
|
2459
|
+
failureThreshold: import_zod6.z.number().int().min(1).default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),
|
|
2460
|
+
cooldownMs: import_zod6.z.number().int().min(100).max(36e5).default(DEFAULT_CIRCUIT_COOLDOWN_MS)
|
|
2461
|
+
});
|
|
2462
|
+
var resolveCircuitBreakerConfig = (options) => CircuitBreakerOptionsSchema.parse(options ?? {});
|
|
2463
|
+
var DEFAULT_FOLD_FLUSH_EVERY = 1e3;
|
|
2464
|
+
var DEFAULT_MAX_CACHED_STATES = 1e4;
|
|
2465
|
+
var FoldOptionsSchema = import_zod6.z.object({
|
|
2466
|
+
flushEvery: import_zod6.z.number().int().min(1).default(DEFAULT_FOLD_FLUSH_EVERY),
|
|
2467
|
+
maxCachedStates: import_zod6.z.number().int().min(1).default(DEFAULT_MAX_CACHED_STATES)
|
|
2468
|
+
});
|
|
2469
|
+
function resolveFoldConfig(options) {
|
|
2470
|
+
return FoldOptionsSchema.parse(options);
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2391
2473
|
// src/internal/defer-config.ts
|
|
2392
2474
|
var import_zod7 = require("zod");
|
|
2393
2475
|
var DeferDurationSchema = import_zod7.z.object({
|
|
@@ -2595,11 +2677,14 @@ function reaction_on(event, events, builder) {
|
|
|
2595
2677
|
const reaction = {
|
|
2596
2678
|
handler: schedule ? make_deferred(handler, schedule) : handler,
|
|
2597
2679
|
resolver: _this_,
|
|
2598
|
-
|
|
2680
|
+
// #1269: validate the whole bag at the declaration site so a bad
|
|
2681
|
+
// `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,
|
|
2682
|
+
// not a NaN gate on the first retry.
|
|
2683
|
+
options: resolveReactionConfig({
|
|
2599
2684
|
blockOnError: options?.blockOnError ?? true,
|
|
2600
2685
|
maxRetries: options?.maxRetries ?? 3,
|
|
2601
2686
|
backoff: options?.backoff
|
|
2602
|
-
}
|
|
2687
|
+
})
|
|
2603
2688
|
};
|
|
2604
2689
|
events[event].reactions.set(handler.name, reaction);
|
|
2605
2690
|
return Object.assign(builder, {
|
|
@@ -2618,14 +2703,6 @@ function reaction_on(event, events, builder) {
|
|
|
2618
2703
|
}
|
|
2619
2704
|
|
|
2620
2705
|
// src/internal/circuit-breaker.ts
|
|
2621
|
-
var import_zod9 = require("zod");
|
|
2622
|
-
var DEFAULT_CIRCUIT_FAILURE_THRESHOLD = 5;
|
|
2623
|
-
var DEFAULT_CIRCUIT_COOLDOWN_MS = 3e4;
|
|
2624
|
-
var CircuitBreakerOptionsSchema = import_zod9.z.object({
|
|
2625
|
-
failureThreshold: import_zod9.z.number().int().min(1).default(DEFAULT_CIRCUIT_FAILURE_THRESHOLD),
|
|
2626
|
-
cooldownMs: import_zod9.z.number().int().min(100).max(36e5).default(DEFAULT_CIRCUIT_COOLDOWN_MS)
|
|
2627
|
-
});
|
|
2628
|
-
var resolveCircuitBreakerConfig = (options) => CircuitBreakerOptionsSchema.parse(options ?? {});
|
|
2629
2706
|
var CircuitBreaker = class {
|
|
2630
2707
|
_failures = 0;
|
|
2631
2708
|
_opened_at;
|
|
@@ -3293,6 +3370,10 @@ function compute_backoff_delay(retry, opts) {
|
|
|
3293
3370
|
delay = opts.baseMs * 2 ** r;
|
|
3294
3371
|
if (opts.maxMs !== void 0) delay = Math.min(delay, opts.maxMs);
|
|
3295
3372
|
break;
|
|
3373
|
+
default: {
|
|
3374
|
+
const _never = opts.strategy;
|
|
3375
|
+
throw new Error(`unknown backoff strategy: ${String(_never)}`);
|
|
3376
|
+
}
|
|
3296
3377
|
}
|
|
3297
3378
|
if (opts.jitter) delay = delay * (0.5 + Math.random());
|
|
3298
3379
|
return Math.max(0, Math.floor(delay));
|
|
@@ -3503,7 +3584,14 @@ async function load(me, target, callback, patch_fn = bare_patch) {
|
|
|
3503
3584
|
{
|
|
3504
3585
|
stream,
|
|
3505
3586
|
stream_exact: true,
|
|
3506
|
-
|
|
3587
|
+
// The snapshot resume floor is a current-state optimization: it only
|
|
3588
|
+
// holds when the load has no window of its own. `time_travel` already
|
|
3589
|
+
// captures that (any `asOf` bound set), so request `with_snaps` only for
|
|
3590
|
+
// a non-time-travel cold load — a bounded load full-scans real events
|
|
3591
|
+
// under its `asOf` filter. This is the single floor-eligibility decision
|
|
3592
|
+
// for the whole system; the stores apply the floor whenever asked and
|
|
3593
|
+
// never re-derive it (RFC 1274). The warm path resumes from `after`.
|
|
3594
|
+
...cached ? { after: cached.event_id } : { ...time_travel ? {} : { with_snaps: true }, ...asOf }
|
|
3507
3595
|
}
|
|
3508
3596
|
);
|
|
3509
3597
|
const head_is_tombstone = event?.name === TOMBSTONE_EVENT;
|
|
@@ -4042,16 +4130,6 @@ var DrainController = class {
|
|
|
4042
4130
|
};
|
|
4043
4131
|
|
|
4044
4132
|
// src/internal/projection-fold.ts
|
|
4045
|
-
var import_zod10 = require("zod");
|
|
4046
|
-
var DEFAULT_FOLD_FLUSH_EVERY = 1e3;
|
|
4047
|
-
var DEFAULT_MAX_CACHED_STATES = 1e4;
|
|
4048
|
-
var FoldOptionsSchema = import_zod10.z.object({
|
|
4049
|
-
flushEvery: import_zod10.z.number().int().min(1).default(DEFAULT_FOLD_FLUSH_EVERY),
|
|
4050
|
-
maxCachedStates: import_zod10.z.number().int().min(1).default(DEFAULT_MAX_CACHED_STATES)
|
|
4051
|
-
});
|
|
4052
|
-
function resolveFoldConfig(options) {
|
|
4053
|
-
return FoldOptionsSchema.parse(options);
|
|
4054
|
-
}
|
|
4055
4133
|
function make_fold_handler(me, flush, config2, patch_fn = bare_patch) {
|
|
4056
4134
|
const cache3 = /* @__PURE__ */ new Map();
|
|
4057
4135
|
const row = ({ dirty: _, ...row2 }) => row2;
|
|
@@ -5078,6 +5156,7 @@ var Act = class {
|
|
|
5078
5156
|
* @see {@link start_correlations} for automatic correlation
|
|
5079
5157
|
*/
|
|
5080
5158
|
async drain(options = {}) {
|
|
5159
|
+
resolveDrainConfig(options);
|
|
5081
5160
|
if (!this._drain)
|
|
5082
5161
|
return { fetched: [], leased: [], acked: [], blocked: [] };
|
|
5083
5162
|
return this._scoped(() => this._drain_all(options));
|
|
@@ -5640,6 +5719,7 @@ var Act = class {
|
|
|
5640
5719
|
* @see {@link correlate} for manual correlation
|
|
5641
5720
|
*/
|
|
5642
5721
|
settle(options = {}) {
|
|
5722
|
+
resolveSettleConfig(options);
|
|
5643
5723
|
if (!this._drain) return;
|
|
5644
5724
|
this._settle.schedule(options);
|
|
5645
5725
|
}
|
|
@@ -5760,11 +5840,12 @@ function act() {
|
|
|
5760
5840
|
},
|
|
5761
5841
|
withActor: () => builder,
|
|
5762
5842
|
withLane: (config2) => {
|
|
5763
|
-
register_lane(config2, lanes);
|
|
5843
|
+
register_lane(resolveLaneConfig(config2), lanes);
|
|
5764
5844
|
return builder;
|
|
5765
5845
|
},
|
|
5766
5846
|
on: (event) => reaction_on(event, registry.events, builder),
|
|
5767
5847
|
build: (options) => {
|
|
5848
|
+
resolveActConfig(options);
|
|
5768
5849
|
const patch_fn = options?.validateFoldedState === true ? validating_patch : bare_patch;
|
|
5769
5850
|
if (!_built) {
|
|
5770
5851
|
for (const proj of pending_projections) {
|
|
@@ -6081,6 +6162,7 @@ function action_builder(state2) {
|
|
|
6081
6162
|
throw new Error(`Duplicate action "${action2}"`);
|
|
6082
6163
|
internal.actions[action2] = schema;
|
|
6083
6164
|
if (options) {
|
|
6165
|
+
resolveActionConfig(options);
|
|
6084
6166
|
internal.options ??= {};
|
|
6085
6167
|
internal.options[action2] = options;
|
|
6086
6168
|
}
|