@voltro/runtime 0.86.0 → 0.87.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/CHANGELOG.md +5321 -0
- package/README.md +43 -0
- package/THIRD-PARTY-NOTICES.md +860 -221
- package/dist/analyticsSink.js +8 -14
- package/dist/apiKeys.js +82 -78
- package/dist/apiRoleBucketSampler.js +64 -0
- package/dist/apiRoleWorkloadHistory.js +56 -0
- package/dist/apiRoleWorkloadMetrics.js +78 -0
- package/dist/apiRoleWorkloadStorage.js +95 -0
- package/dist/approvals.js +67 -74
- package/dist/authMiddlewareLayer.js +7 -6
- package/dist/bindEvent.js +48 -28
- package/dist/bootListener.js +106 -39
- package/dist/bootStoreCodec.js +38 -37
- package/dist/circuitBreaker.js +1 -72
- package/dist/composeAnalytics.js +31 -10
- package/dist/computedQueryCache.js +231 -0
- package/dist/connectionsFacade.js +32 -30
- package/dist/coordinatedSchedule.js +84 -78
- package/dist/dataStore.js +154 -121
- package/dist/declaredTablesGuard.js +2 -1
- package/dist/dispatcher.js +403 -328
- package/dist/effectStore.js +2 -2
- package/dist/engineClients.js +24 -0
- package/dist/externalizedTasks.js +19 -6
- package/dist/fieldCipher.js +109 -40
- package/dist/fieldKeyRegistry.js +295 -0
- package/dist/fieldKeyRekey.js +286 -0
- package/dist/fieldKeyScan.js +136 -0
- package/dist/fieldKeyring.js +77 -0
- package/dist/hot.d.ts +56 -0
- package/dist/hot.js +3 -0
- package/dist/hotDataStore.js +148 -0
- package/dist/hotDataStoreSnapshot.js +98 -0
- package/dist/hotDataStoreTables.js +18 -0
- package/dist/http-range.d.ts +53 -0
- package/dist/http-range.js +52 -0
- package/dist/httpClientSsrf.js +12 -37
- package/dist/httpClientTracing.js +12 -9
- package/dist/httpCompression.js +17 -17
- package/dist/httpInputStream.js +82 -0
- package/dist/httpRouteMounts.js +1 -0
- package/dist/idempotencyStore.js +92 -52
- package/dist/index.d.ts +1164 -451
- package/dist/index.js +143 -132
- package/dist/kvFacade.js +23 -17
- package/dist/memoryQueryJoins.js +16 -16
- package/dist/memorySetOperations.js +43 -0
- package/dist/metrics.js +38 -24
- package/dist/outbox.js +1 -1
- package/dist/readRecorder.js +35 -34
- package/dist/readScopePredicate.js +12 -0
- package/dist/replicatedDataStore.js +22 -4
- package/dist/rowFilter.js +56 -39
- package/dist/rpcConnections.js +8 -8
- package/dist/rpcServer.js +522 -449
- package/dist/rpcWorkloadAdmission.js +50 -0
- package/dist/rywPositionStore.js +82 -47
- package/dist/scheduler.js +6 -1
- package/dist/servePipeline.js +215 -146
- package/dist/setReadScopes.js +28 -0
- package/dist/snapshotValueCodec.js +46 -0
- package/dist/sourceResolution.js +34 -24
- package/dist/storeMiddleware.js +211 -209
- package/dist/subscriber.js +1 -0
- package/dist/tenantScope.js +8 -20
- package/dist/traceparent.js +8 -19
- package/dist/webSocketGatewayRuntime.js +111 -71
- package/dist/workflowRuntime.js +9 -9
- package/package.json +19 -7
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Context as e, Option as t } from "effect";
|
|
2
|
+
import { EventRpcWorkload as n } from "@voltro/protocol";
|
|
3
|
+
import { RpcGroup as r, RpcSchema as i } from "effect/rpc";
|
|
4
|
+
//#region src/rpcWorkloadAdmission.ts
|
|
5
|
+
var a = (e) => {
|
|
6
|
+
if (e === void 0) return;
|
|
7
|
+
if (!e || typeof e != "object" || Array.isArray(e) || ![Object.prototype, null].includes(Object.getPrototypeOf(e))) throw Error("Invalid RPC workload admission");
|
|
8
|
+
let t = /* @__PURE__ */ new Map();
|
|
9
|
+
for (let n of Reflect.ownKeys(e)) {
|
|
10
|
+
let r = Object.getOwnPropertyDescriptor(e, n);
|
|
11
|
+
if (typeof n != "string" || ![
|
|
12
|
+
"rpc",
|
|
13
|
+
"subscriptions",
|
|
14
|
+
"events",
|
|
15
|
+
"routes"
|
|
16
|
+
].includes(n) || !r.enumerable || !("value" in r)) throw Error("RPC workload admission requires own data");
|
|
17
|
+
t.set(n, r.value);
|
|
18
|
+
}
|
|
19
|
+
let n = t.get("rpc"), r = t.get("subscriptions"), i = t.get("routes");
|
|
20
|
+
if (typeof n != "boolean" || typeof r != "boolean") throw Error("RPC workload admission requires explicit modes");
|
|
21
|
+
let a = t.get("events");
|
|
22
|
+
if (a !== void 0 && typeof a != "boolean") throw Error("Invalid event workload admission");
|
|
23
|
+
let o;
|
|
24
|
+
if (i !== void 0) {
|
|
25
|
+
if (!Array.isArray(i) || i.length > 4096 || Reflect.ownKeys(i).length !== i.length + 1) throw Error("Invalid RPC workload route filters");
|
|
26
|
+
let e = [];
|
|
27
|
+
for (let t = 0; t < i.length; t++) {
|
|
28
|
+
let n = Object.getOwnPropertyDescriptor(i, String(t));
|
|
29
|
+
if (!n?.enumerable || !("value" in n) || typeof n.value != "string" || n.value.length > 191 || !/^(?:[A-Za-z][A-Za-z0-9_-]*\.)*[A-Za-z][A-Za-z0-9_-]*(?:\.\*)?$/.test(n.value)) throw Error("Invalid RPC workload tag filter");
|
|
30
|
+
e.push(n.value);
|
|
31
|
+
}
|
|
32
|
+
if (new Set(e).size !== e.length) throw Error("Duplicate RPC workload tag filter");
|
|
33
|
+
o = Object.freeze(e);
|
|
34
|
+
}
|
|
35
|
+
return Object.freeze({
|
|
36
|
+
rpc: n,
|
|
37
|
+
subscriptions: r,
|
|
38
|
+
...a === void 0 ? {} : { events: a },
|
|
39
|
+
...o === void 0 ? {} : { routes: o }
|
|
40
|
+
});
|
|
41
|
+
}, o = (a, o, s) => {
|
|
42
|
+
if (!o) return a;
|
|
43
|
+
let c = [...a.requests.values()].filter((r) => {
|
|
44
|
+
let a = r, c = t.isSome(e.getOption(a.annotations, n)), l = o.events ?? o.subscriptions;
|
|
45
|
+
return (c ? l && (s === "websocket" || o.rpc) : s === "http" ? o.rpc : i.isStreamSchema(a.successSchema) ? o.subscriptions : o.rpc) && (o.routes === void 0 || o.routes.some((e) => e.endsWith(".*") ? r._tag.startsWith(e.slice(0, -1)) : r._tag === e));
|
|
46
|
+
});
|
|
47
|
+
return r.make(...c).annotateMerge(a.annotations);
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { a as captureRpcWorkloadAdmission, o as selectRpcWorkloadGroup };
|
package/dist/rywPositionStore.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Effect as e } from "effect";
|
|
2
|
+
import { createLogger as t } from "@voltro/logger";
|
|
2
3
|
//#region src/rywPositionStore.ts
|
|
3
|
-
var
|
|
4
|
+
var n = t({ scope: "voltro:ryw" }), r = (e = {}) => {
|
|
4
5
|
let t = e.now ?? Date.now, n = /* @__PURE__ */ new Map();
|
|
5
6
|
return {
|
|
6
7
|
get(e) {
|
|
@@ -20,65 +21,99 @@ var t = e({ scope: "voltro:ryw" }), n = (e = {}) => {
|
|
|
20
21
|
return n.size;
|
|
21
22
|
}
|
|
22
23
|
};
|
|
23
|
-
},
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
expiresAt: e.expiresAt
|
|
36
|
-
});
|
|
37
|
-
} else s.delete(e.subjectKey);
|
|
24
|
+
}, i = (e, t) => e === null ? t === void 0 ? "anon:bg" : `anon:${t}` : `subject:${e}`, a = (t) => e.gen(function* () {
|
|
25
|
+
let r = yield* e.context(), i = e.runPromiseWith(r), a = t.now ?? Date.now, s = t.keyPrefix.trim();
|
|
26
|
+
if (s.length === 0) throw Error("RYW keyPrefix must name an application/environment namespace");
|
|
27
|
+
let c = t.channel ?? `${s}:bus`;
|
|
28
|
+
if (c.trim().length === 0) throw Error("RYW channel must not be empty");
|
|
29
|
+
let l = t.onError ?? ((e, t) => {
|
|
30
|
+
n.warn("redis operation failed", { op: t });
|
|
31
|
+
}), u = (e, t) => {
|
|
32
|
+
try {
|
|
33
|
+
l(e, t);
|
|
34
|
+
} catch {
|
|
35
|
+
n.warn("redis error observer failed", { op: t });
|
|
38
36
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
}, d = `${process.pid}:${Math.random()}:${a()}`, f = /* @__PURE__ */ new Map(), p = !1, m = Promise.resolve(), h, g = yield* t.pubsub.subscribe(c, (e) => {
|
|
38
|
+
if (!p) try {
|
|
39
|
+
let t = o(e);
|
|
40
|
+
if (t.senderId === d) return;
|
|
41
|
+
t.op === "delete" ? f.delete(t.subjectKey) : t.expiresAt > a() ? f.set(t.subjectKey, {
|
|
42
|
+
position: t.position,
|
|
43
|
+
expiresAt: t.expiresAt
|
|
44
|
+
}) : f.delete(t.subjectKey);
|
|
44
45
|
} catch (e) {
|
|
45
|
-
|
|
46
|
+
u(e, "parse");
|
|
46
47
|
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
}).pipe(e.onError(() => t.pubsub.close)), _ = (e, n) => {
|
|
49
|
+
m = m.then(async () => {
|
|
50
|
+
try {
|
|
51
|
+
await n(), await i(t.pubsub.publish(c, JSON.stringify(e)));
|
|
52
|
+
} catch (t) {
|
|
53
|
+
u(t, e.op);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}, v = () => {
|
|
57
|
+
if (p) throw Error("RYW consumer is closed");
|
|
58
|
+
};
|
|
52
59
|
return {
|
|
53
60
|
get(e) {
|
|
54
|
-
let t =
|
|
61
|
+
let t = f.get(e);
|
|
55
62
|
if (t !== void 0) {
|
|
56
|
-
if (t.expiresAt <=
|
|
63
|
+
if (t.expiresAt <= a()) f.delete(e);
|
|
57
64
|
else return t;
|
|
58
65
|
}
|
|
59
66
|
},
|
|
60
|
-
set(
|
|
61
|
-
|
|
62
|
-
let
|
|
63
|
-
|
|
64
|
-
senderId:
|
|
67
|
+
set(e, n) {
|
|
68
|
+
v();
|
|
69
|
+
let r = { ...n };
|
|
70
|
+
f.set(e, r), _({
|
|
71
|
+
senderId: d,
|
|
65
72
|
op: "set",
|
|
66
|
-
subjectKey:
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
subjectKey: e,
|
|
74
|
+
...r
|
|
75
|
+
}, () => {
|
|
76
|
+
let n = r.expiresAt - a();
|
|
77
|
+
return n > 0 ? t.client.psetex(`${s}:${e}`, n, JSON.stringify(r)) : t.client.del([`${s}:${e}`]);
|
|
69
78
|
});
|
|
70
79
|
},
|
|
71
|
-
delete(
|
|
72
|
-
|
|
73
|
-
senderId:
|
|
80
|
+
delete(e) {
|
|
81
|
+
v(), f.delete(e), _({
|
|
82
|
+
senderId: d,
|
|
74
83
|
op: "delete",
|
|
75
|
-
subjectKey:
|
|
76
|
-
});
|
|
84
|
+
subjectKey: e
|
|
85
|
+
}, () => t.client.del([`${s}:${e}`]));
|
|
77
86
|
},
|
|
78
|
-
size()
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
size: () => f.size,
|
|
88
|
+
close: () => h ??= (async () => {
|
|
89
|
+
p = !0, await m;
|
|
90
|
+
try {
|
|
91
|
+
await i(g);
|
|
92
|
+
} finally {
|
|
93
|
+
try {
|
|
94
|
+
await i(t.pubsub.close);
|
|
95
|
+
} finally {
|
|
96
|
+
f.clear();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
})()
|
|
100
|
+
};
|
|
101
|
+
}), o = (e) => {
|
|
102
|
+
let t = JSON.parse(e);
|
|
103
|
+
if (typeof t != "object" || !t || !("senderId" in t) || typeof t.senderId != "string" || !("subjectKey" in t) || typeof t.subjectKey != "string" || !("op" in t) || t.op !== "set" && t.op !== "delete") throw Error("Invalid RYW message");
|
|
104
|
+
if (t.op === "delete") return {
|
|
105
|
+
senderId: t.senderId,
|
|
106
|
+
subjectKey: t.subjectKey,
|
|
107
|
+
op: "delete"
|
|
108
|
+
};
|
|
109
|
+
if (!("position" in t) || typeof t.position != "string" || !("expiresAt" in t) || typeof t.expiresAt != "number" || !Number.isFinite(t.expiresAt)) throw Error("Invalid RYW position");
|
|
110
|
+
return {
|
|
111
|
+
senderId: t.senderId,
|
|
112
|
+
subjectKey: t.subjectKey,
|
|
113
|
+
op: "set",
|
|
114
|
+
position: t.position,
|
|
115
|
+
expiresAt: t.expiresAt
|
|
81
116
|
};
|
|
82
117
|
};
|
|
83
118
|
//#endregion
|
|
84
|
-
export {
|
|
119
|
+
export { i as buildSubjectKey, r as memoryRywPositionStore, a as redisRywPositionStore };
|
package/dist/scheduler.js
CHANGED
|
@@ -363,7 +363,10 @@ var b = c, x = "default", S = {
|
|
|
363
363
|
let n = typeof t.workflow.payload == "function" ? await t.workflow.payload(a) : t.workflow.payload ?? {};
|
|
364
364
|
await e.start(t.workflow.name, n);
|
|
365
365
|
}
|
|
366
|
-
t.handler !== void 0
|
|
366
|
+
if (t.handler !== void 0) {
|
|
367
|
+
let n = t.handler, r = x.measureSync ? x.measureSync(() => n(a)) : n(a);
|
|
368
|
+
await e(r, (e) => x.runEffect ? x.runEffect(e, m.signal) : ne.runPromise(e, { signal: m.signal }));
|
|
369
|
+
}
|
|
367
370
|
}, h = k ? k(c, {
|
|
368
371
|
name: t.name,
|
|
369
372
|
scheduledAt: n,
|
|
@@ -662,6 +665,7 @@ Give each a five-field expression, or set trigger: 'self' on it.`);
|
|
|
662
665
|
};
|
|
663
666
|
Ge.length > 0 && Q !== "off" && Ye();
|
|
664
667
|
let Xe = async (e, t) => {
|
|
668
|
+
if (I) throw Error("scheduler stopped");
|
|
665
669
|
let n = V.get(e);
|
|
666
670
|
if (!n) return {
|
|
667
671
|
kind: "unknownSchedule",
|
|
@@ -730,6 +734,7 @@ Give each a five-field expression, or set trigger: 'self' on it.`);
|
|
|
730
734
|
for (let e of X) Fe(e);
|
|
731
735
|
}
|
|
732
736
|
return {
|
|
737
|
+
isRunning: () => !I,
|
|
733
738
|
triggerExternal: async (e, t) => {
|
|
734
739
|
let r = await Xe(e, t);
|
|
735
740
|
return n(e, r.kind), r;
|