@rotorsoft/act 1.22.4 → 1.22.6
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/adapters/in-memory-store.d.ts.map +1 -1
- package/dist/@types/internal/autoclose-config.d.ts +13 -0
- package/dist/@types/internal/autoclose-config.d.ts.map +1 -1
- package/dist/@types/internal/drain.d.ts.map +1 -1
- package/dist/@types/internal/event-versions.d.ts.map +1 -1
- package/dist/@types/types/ports.d.ts +15 -9
- package/dist/@types/types/ports.d.ts.map +1 -1
- package/dist/@types/types/reaction.d.ts +8 -6
- package/dist/@types/types/reaction.d.ts.map +1 -1
- package/dist/@types/utils.d.ts +20 -0
- package/dist/@types/utils.d.ts.map +1 -1
- package/dist/{chunk-2FN4RFBQ.js → chunk-CWBI4NQD.js} +18 -5
- package/dist/chunk-CWBI4NQD.js.map +1 -0
- package/dist/index.cjs +47 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +32 -4
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +16 -4
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-2FN4RFBQ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -70,6 +70,7 @@ __export(index_exports, {
|
|
|
70
70
|
dispose: () => dispose,
|
|
71
71
|
disposeAndExit: () => disposeAndExit,
|
|
72
72
|
extend: () => extend,
|
|
73
|
+
is_literal_source: () => is_literal_source,
|
|
73
74
|
log: () => log,
|
|
74
75
|
port: () => port,
|
|
75
76
|
projection: () => projection,
|
|
@@ -619,6 +620,10 @@ var extend = (source, schema, target) => {
|
|
|
619
620
|
async function sleep(ms) {
|
|
620
621
|
return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));
|
|
621
622
|
}
|
|
623
|
+
var SOURCE_METACHARACTERS = /[\^$.*+?()[\]{}|\\]/;
|
|
624
|
+
function is_literal_source(source) {
|
|
625
|
+
return !SOURCE_METACHARACTERS.test(source);
|
|
626
|
+
}
|
|
622
627
|
|
|
623
628
|
// src/adapters/in-memory-store.ts
|
|
624
629
|
var InMemoryStream = class {
|
|
@@ -811,8 +816,9 @@ var InMemoryStore = class {
|
|
|
811
816
|
_streams = /* @__PURE__ */ new Map();
|
|
812
817
|
// last committed version per stream — O(1) replacement for filter-on-commit
|
|
813
818
|
_stream_versions = /* @__PURE__ */ new Map();
|
|
814
|
-
// max non-snapshot event id per stream — drives the
|
|
815
|
-
//
|
|
819
|
+
// max non-snapshot event id per stream — drives the has-work probe in
|
|
820
|
+
// claim(): an O(1) lookup for a literal source, and the per-stream max
|
|
821
|
+
// that a pattern source scans, without touching the full event log.
|
|
816
822
|
_max_event_id_by_stream = /* @__PURE__ */ new Map();
|
|
817
823
|
// global max non-snapshot event id — fast pre-check for source-less streams in claim()
|
|
818
824
|
_max_non_snap_event_id = -1;
|
|
@@ -1002,8 +1008,15 @@ var InMemoryStore = class {
|
|
|
1002
1008
|
const has_work = (s) => {
|
|
1003
1009
|
if (s.at < 0) return true;
|
|
1004
1010
|
if (!s.source) return s.at < this._max_non_snap_event_id;
|
|
1005
|
-
|
|
1006
|
-
|
|
1011
|
+
if (is_literal_source(s.source)) {
|
|
1012
|
+
const max_id = this._max_event_id_by_stream.get(s.source);
|
|
1013
|
+
return max_id !== void 0 && max_id > s.at;
|
|
1014
|
+
}
|
|
1015
|
+
const re = new RegExp(s.source);
|
|
1016
|
+
for (const [stream_name, max_id] of this._max_event_id_by_stream) {
|
|
1017
|
+
if (max_id > s.at && re.test(stream_name)) return true;
|
|
1018
|
+
}
|
|
1019
|
+
return false;
|
|
1007
1020
|
};
|
|
1008
1021
|
const available = [...this._streams.values()].filter(
|
|
1009
1022
|
(s) => s.is_available && has_work(s) && (lane === void 0 || s.lane === lane)
|
|
@@ -1594,6 +1607,15 @@ function deprecated_event_names(names) {
|
|
|
1594
1607
|
const deprecated = /* @__PURE__ */ new Set();
|
|
1595
1608
|
for (const list of groups.values()) {
|
|
1596
1609
|
if (list.length < 2) continue;
|
|
1610
|
+
const by_version = /* @__PURE__ */ new Map();
|
|
1611
|
+
for (const { version, name } of list) {
|
|
1612
|
+
const clash = by_version.get(version);
|
|
1613
|
+
if (clash)
|
|
1614
|
+
throw new Error(
|
|
1615
|
+
`duplicate event version: ${clash} and ${name} both map to version ${version} \u2014 leading zeros in a \`_v<n>\` suffix are not allowed; use a single canonical spelling`
|
|
1616
|
+
);
|
|
1617
|
+
by_version.set(version, name);
|
|
1618
|
+
}
|
|
1597
1619
|
list.sort((a, b) => b.version - a.version);
|
|
1598
1620
|
for (let i = 1; i < list.length; i++) deprecated.add(list[i].name);
|
|
1599
1621
|
}
|
|
@@ -2039,18 +2061,33 @@ function hour_in_zone(now, timeZone) {
|
|
|
2039
2061
|
}).formatToParts(now);
|
|
2040
2062
|
return Number(parts.find((p) => p.type === "hour")?.value);
|
|
2041
2063
|
}
|
|
2064
|
+
function hour_in_range(hour, start, end) {
|
|
2065
|
+
return start < end ? hour >= start && hour < end : hour >= start || hour < end;
|
|
2066
|
+
}
|
|
2067
|
+
function is_dst_gap_open(now, timeZone, start) {
|
|
2068
|
+
const hour = hour_in_zone(now, timeZone);
|
|
2069
|
+
if (hour <= start) return false;
|
|
2070
|
+
const prev = hour_in_zone(new Date(now.getTime() - 36e5), timeZone);
|
|
2071
|
+
return prev === start - 1 && hour === start + 1;
|
|
2072
|
+
}
|
|
2042
2073
|
function in_autoclose_window(window, now) {
|
|
2043
2074
|
if (!window) return true;
|
|
2044
2075
|
const hour = hour_in_zone(now, window.timeZone);
|
|
2045
|
-
return
|
|
2076
|
+
return hour_in_range(hour, window.start, window.end) || is_dst_gap_open(now, window.timeZone, window.start);
|
|
2046
2077
|
}
|
|
2047
2078
|
function next_window_open(window, now) {
|
|
2079
|
+
const start_ms = now.getTime();
|
|
2048
2080
|
for (let h = 0; h <= 48; h++) {
|
|
2049
|
-
const candidate = new Date(
|
|
2081
|
+
const candidate = new Date(start_ms + h * 36e5);
|
|
2050
2082
|
if (hour_in_zone(candidate, window.timeZone) === window.start)
|
|
2051
2083
|
return candidate;
|
|
2084
|
+
const boundary = new Date(
|
|
2085
|
+
candidate.getTime() - candidate.getTime() % 36e5
|
|
2086
|
+
);
|
|
2087
|
+
if (is_dst_gap_open(boundary, window.timeZone, window.start))
|
|
2088
|
+
return boundary;
|
|
2052
2089
|
}
|
|
2053
|
-
return new Date(
|
|
2090
|
+
return new Date(start_ms + 864e5);
|
|
2054
2091
|
}
|
|
2055
2092
|
|
|
2056
2093
|
// src/internal/autoclose-policy.ts
|
|
@@ -3144,8 +3181,10 @@ async function fetch(leased, eventLimit) {
|
|
|
3144
3181
|
return Promise.all(
|
|
3145
3182
|
leased.map(async ({ stream, source, at, lagging }) => {
|
|
3146
3183
|
const events = [];
|
|
3184
|
+
const stream_exact = source !== void 0 && is_literal_source(source) ? true : void 0;
|
|
3147
3185
|
await store2().query((e) => events.push(e), {
|
|
3148
3186
|
stream: source,
|
|
3187
|
+
stream_exact,
|
|
3149
3188
|
after: at,
|
|
3150
3189
|
limit: eventLimit
|
|
3151
3190
|
});
|
|
@@ -6093,6 +6132,7 @@ function write_line(writer, line) {
|
|
|
6093
6132
|
dispose,
|
|
6094
6133
|
disposeAndExit,
|
|
6095
6134
|
extend,
|
|
6135
|
+
is_literal_source,
|
|
6096
6136
|
log,
|
|
6097
6137
|
port,
|
|
6098
6138
|
projection,
|