@supalive/core 1.20.2 → 1.21.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/ephemeral-BVeIVuYw.js +276 -0
- package/dist/ephemeral-BVeIVuYw.js.map +1 -0
- package/dist/ephemeral-CkidSG9y.js +295 -0
- package/dist/ephemeral-CkidSG9y.js.map +1 -0
- package/dist/index-CzW0TkpK.d.ts +2729 -0
- package/dist/index-CzW0TkpK.d.ts.map +1 -0
- package/dist/index-DB7_pv9P.d.ts +2746 -0
- package/dist/index-DB7_pv9P.d.ts.map +1 -0
- package/dist/logger-BJNCJkFh.js +463 -0
- package/dist/logger-BJNCJkFh.js.map +1 -0
- package/dist/logger-By9Pw-X2.js +454 -0
- package/dist/logger-By9Pw-X2.js.map +1 -0
- package/dist/mysql-Bvc_iWUy.d.ts +114 -0
- package/dist/mysql-Bvc_iWUy.d.ts.map +1 -0
- package/dist/mysql-CcIuIAt0.js +622 -0
- package/dist/mysql-CcIuIAt0.js.map +1 -0
- package/dist/mysql-DTK2f5oU.d.ts +114 -0
- package/dist/mysql-DTK2f5oU.d.ts.map +1 -0
- package/dist/one-shot-query-BNYLU19W.js +573 -0
- package/dist/one-shot-query-BNYLU19W.js.map +1 -0
- package/dist/one-shot-query-BSK7adwG.js +573 -0
- package/dist/one-shot-query-BSK7adwG.js.map +1 -0
- package/dist/one-shot-query-DAAHGTcI.js +573 -0
- package/dist/one-shot-query-DAAHGTcI.js.map +1 -0
- package/dist/overlap-checker-DseE1Lvh.js +300 -0
- package/dist/overlap-checker-DseE1Lvh.js.map +1 -0
- package/dist/postgres-Bp7SMb9D.d.ts +118 -0
- package/dist/postgres-Bp7SMb9D.d.ts.map +1 -0
- package/dist/postgres-C5CbPBcp.d.ts +118 -0
- package/dist/postgres-C5CbPBcp.d.ts.map +1 -0
- package/dist/postgres-CLhoKn_R.js +867 -0
- package/dist/postgres-CLhoKn_R.js.map +1 -0
- package/dist/realtime_db-CTGOrFuV.js +463 -0
- package/dist/realtime_db-CTGOrFuV.js.map +1 -0
- package/dist/src/client/index.d.ts +2 -2
- package/dist/src/client/index.js +6 -5
- package/dist/src/client/index.js.map +1 -1
- package/dist/src/exports/mysql.d.ts +1 -1
- package/dist/src/exports/mysql.js +1 -1
- package/dist/src/exports/postgres.d.ts +1 -1
- package/dist/src/exports/postgres.js +1 -1
- package/dist/src/exports/procedure.d.ts +2 -2
- package/dist/src/exports/procedure.d.ts.map +1 -1
- package/dist/src/exports/procedure.js +2 -1
- package/dist/src/exports/procedure.js.map +1 -1
- package/dist/src/exports/schema-sql.d.ts +1 -1
- package/dist/src/exports/server.d.ts +56 -5
- package/dist/src/exports/server.d.ts.map +1 -1
- package/dist/src/exports/server.js +165 -7
- package/dist/src/exports/server.js.map +1 -1
- package/dist/src/exports/sub-manager-worker-entry.js +1 -1
- package/dist/src/exports/types.d.ts +2 -2
- package/dist/src/exports/types.js +2 -2
- package/dist/sub-worker-dispatch-C20KTMfg.js +925 -0
- package/dist/sub-worker-dispatch-C20KTMfg.js.map +1 -0
- package/dist/sub-worker-dispatch-CQCuwZPm.js +925 -0
- package/dist/sub-worker-dispatch-CQCuwZPm.js.map +1 -0
- package/dist/sub-worker-dispatch-Dwrp3c40.js +925 -0
- package/dist/sub-worker-dispatch-Dwrp3c40.js.map +1 -0
- package/dist/types_client_rpc-CqUVHTwT.js +163 -0
- package/dist/types_client_rpc-CqUVHTwT.js.map +1 -0
- package/dist/types_db-DPMeNETt.js +173 -0
- package/dist/types_db-DPMeNETt.js.map +1 -0
- package/dist/types_server-hiwqDm4G.d.ts +737 -0
- package/dist/types_server-hiwqDm4G.d.ts.map +1 -0
- package/dist/types_server-xHmZ6baD.d.ts +737 -0
- package/dist/types_server-xHmZ6baD.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as MySqlDatabase } from "../../mysql-
|
|
1
|
+
import { t as MySqlDatabase } from "../../mysql-CcIuIAt0.js";
|
|
2
2
|
export { MySqlDatabase };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as PgDatabase } from "../../postgres-
|
|
1
|
+
import { t as PgDatabase } from "../../postgres-C5CbPBcp.js";
|
|
2
2
|
export { PgDatabase };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as PgDatabase } from "../../postgres-
|
|
1
|
+
import { t as PgDatabase } from "../../postgres-CLhoKn_R.js";
|
|
2
2
|
export { PgDatabase };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ActionProcedures, An as
|
|
1
|
+
import { $ as ActionProcedures, $n as schemaRegistry, An as ComputedCodec, At as QueryFn, Bn as MutationArgs, Cn as buildPredicateSql, Ct as MutationConfig, Dn as matchesPredicate, Dt as OutputOf, En as jsonPathExtract, Et as MutationProcedure, Fn as DefineSchemaConfig, Ft as createMutationBuilder, Gn as ReturnQuery, Hn as Prettify, In as IndexDefinition, It as createQueryBuilder, Jn as SchemaColumnsOptions, Kn as SchemaCodecs, Ln as InferSchema, Mn as ComputedField, Mt as TypeOf, Nn as ComputedFieldConfig, Nt as createActionBuilder, On as ActionArgs, Ot as QueryConfig, Pn as DeclarativeIndex, Pt as createJobBuilder, Qn as defineSchema, Rn as InsertData, Sn as QueryBuilder, St as JobProcedure, Tn as jsonPathExists, Tt as MutationFn, Un as QueryArgs, Vn as OverrideField, Wn as ReturnLiveQuery, Xn as StoredSchemaColumnsOptions, Yn as SchemaDefinition, Zn as defineComputedField, _n as JsonHasKeyMultiOptions, _t as HandlerLogger, at as PublicProcedures, bn as OrderDirection, bt as JobCtx, cn as EphemeralFlushError, ct as Router, dn as EphemeralSetOptions, dt as ActionConfig, er as shouldTrackSchema, et as AppRouter, ft as ActionCtx, gn as JsonContainsOptions, gt as ContextOf, hn as IdAndCommitTs, ht as AnyProcedure, it as ProcedureNames, jn as ComputedDataType, jt as QueryProcedure, kn as ColumnCodec, kt as QueryCtx, ln as EphemeralKeyNotFoundError, lt as getContextRegistry, mt as ActionProcedure, nt as JobProcedures, on as EPHEMERAL_DEFAULT_TTL_SECONDS, ot as QueryProcedures, pn as EphemeralWriter, pt as ActionFn, qn as SchemaColumnMapping, rt as MutationProcedures, sn as EphemeralDecodeError, st as RegisteredProcedure, tr as tableNameToId, tt as ContextRegistry, un as EphemeralReader, ut as router, vn as JsonOpOptions, vt as HandlerObservability, wn as jsonContains, wt as MutationCtx, xn as PaginationClause, xt as JobFn, yn as OrderByOptions, yt as JobConfig, zn as Model } from "../../index-DB7_pv9P.js";
|
|
2
2
|
import { n as stableStringify, r as supaliveStringify, t as groupByToMap } from "../../helper-CiacMqje.js";
|
|
3
3
|
import * as z$2 from "zod";
|
|
4
4
|
|
|
@@ -17,5 +17,5 @@ declare module "zod" {
|
|
|
17
17
|
}
|
|
18
18
|
} //# sourceMappingURL=procedure.d.ts.map
|
|
19
19
|
//#endregion
|
|
20
|
-
export { ActionArgs, type ActionConfig, type ActionCtx, type ActionFn, type ActionProcedure, type ActionProcedures, type AnyProcedure, type AppRouter, ColumnCodec, ComputedCodec, ComputedDataType, ComputedField, ComputedFieldConfig, type ContextOf, ContextRegistry, DeclarativeIndex, DefineSchemaConfig, type HandlerLogger, type HandlerObservability, IdAndCommitTs, IndexDefinition, InferSchema, InsertData, type JobConfig, type JobCtx, type JobFn, type JobProcedure, type JobProcedures, JsonContainsOptions, JsonHasKeyMultiOptions, JsonOpOptions, Model, MutationArgs, type MutationConfig, type MutationCtx, type MutationFn, type MutationProcedure, type MutationProcedures, OrderByOptions, OrderDirection, type OutputOf, OverrideField, PaginationClause, Prettify, type ProcedureNames, type PublicProcedures, QueryArgs, QueryBuilder, type QueryConfig, type QueryCtx, type QueryFn, type QueryProcedure, type QueryProcedures, type RegisteredProcedure, ReturnLiveQuery, ReturnQuery, type Router, SchemaCodecs, SchemaColumnMapping, SchemaColumnsOptions, SchemaDefinition, StoredSchemaColumnsOptions, type TypeOf, buildPredicateSql, createActionBuilder, createJobBuilder, createMutationBuilder, createQueryBuilder, defineComputedField, defineSchema, getContextRegistry, groupByToMap, jsonContains, jsonPathExists, jsonPathExtract, matchesPredicate, patchZod, router, schemaRegistry, shouldTrackSchema, stableStringify, supaliveStringify, tableNameToId };
|
|
20
|
+
export { ActionArgs, type ActionConfig, type ActionCtx, type ActionFn, type ActionProcedure, type ActionProcedures, type AnyProcedure, type AppRouter, ColumnCodec, ComputedCodec, ComputedDataType, ComputedField, ComputedFieldConfig, type ContextOf, ContextRegistry, DeclarativeIndex, DefineSchemaConfig, EPHEMERAL_DEFAULT_TTL_SECONDS, EphemeralDecodeError, EphemeralFlushError, EphemeralKeyNotFoundError, type EphemeralReader, type EphemeralSetOptions, type EphemeralWriter, type HandlerLogger, type HandlerObservability, IdAndCommitTs, IndexDefinition, InferSchema, InsertData, type JobConfig, type JobCtx, type JobFn, type JobProcedure, type JobProcedures, JsonContainsOptions, JsonHasKeyMultiOptions, JsonOpOptions, Model, MutationArgs, type MutationConfig, type MutationCtx, type MutationFn, type MutationProcedure, type MutationProcedures, OrderByOptions, OrderDirection, type OutputOf, OverrideField, PaginationClause, Prettify, type ProcedureNames, type PublicProcedures, QueryArgs, QueryBuilder, type QueryConfig, type QueryCtx, type QueryFn, type QueryProcedure, type QueryProcedures, type RegisteredProcedure, ReturnLiveQuery, ReturnQuery, type Router, SchemaCodecs, SchemaColumnMapping, SchemaColumnsOptions, SchemaDefinition, StoredSchemaColumnsOptions, type TypeOf, buildPredicateSql, createActionBuilder, createJobBuilder, createMutationBuilder, createQueryBuilder, defineComputedField, defineSchema, getContextRegistry, groupByToMap, jsonContains, jsonPathExists, jsonPathExtract, matchesPredicate, patchZod, router, schemaRegistry, shouldTrackSchema, stableStringify, supaliveStringify, tableNameToId };
|
|
21
21
|
//# sourceMappingURL=procedure.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"procedure.d.ts","names":[],"sources":["../../../src/router/zod_patch.ts","../../../src/exports/procedure.ts"],"mappings":";;;;;;;;;AAgBA;iBAAgB,QAAA,CAAS,SAAmB,SAAD,GAAC;;;;
|
|
1
|
+
{"version":3,"file":"procedure.d.ts","names":[],"sources":["../../../src/router/zod_patch.ts","../../../src/exports/procedure.ts"],"mappings":";;;;;;;;;AAgBA;iBAAgB,QAAA,CAAS,SAAmB,SAAD,GAAC;;;;YCAhC,OAAA;IACR,SAAA,CAAU,IAAA;EAAA;AAAA"}
|
|
@@ -3,6 +3,7 @@ import { n as tableNameToId } from "../../table-id-DyrJBKAQ.js";
|
|
|
3
3
|
import { n as stableStringify, r as supaliveStringify, t as groupByToMap } from "../../helper-zdJT5FUc.js";
|
|
4
4
|
import { a as jsonPathExtract, i as jsonPathExists, n as buildPredicateSql, o as matchesPredicate, r as jsonContains, t as QueryBuilder } from "../../query-LJranz0c.js";
|
|
5
5
|
import { i as shouldTrackSchema, n as defineSchema, r as schemaRegistry, t as defineComputedField } from "../../schema-DRtz5h5l.js";
|
|
6
|
+
import { a as EphemeralKeyNotFoundError, i as EphemeralFlushError, n as EPHEMERAL_DEFAULT_TTL_SECONDS, r as EphemeralDecodeError } from "../../ephemeral-CkidSG9y.js";
|
|
6
7
|
//#region src/router/zod_patch.ts
|
|
7
8
|
/**
|
|
8
9
|
* Patch all Zod schema types on the given `z` namespace with `.modelName(name)`.
|
|
@@ -66,6 +67,6 @@ function patchZod(zInstance) {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
//#endregion
|
|
69
|
-
export { ContextRegistry, QueryBuilder, buildPredicateSql, createActionBuilder, createJobBuilder, createMutationBuilder, createQueryBuilder, defineComputedField, defineSchema, getContextRegistry, groupByToMap, jsonContains, jsonPathExists, jsonPathExtract, matchesPredicate, patchZod, router, schemaRegistry, shouldTrackSchema, stableStringify, supaliveStringify, tableNameToId };
|
|
70
|
+
export { ContextRegistry, EPHEMERAL_DEFAULT_TTL_SECONDS, EphemeralDecodeError, EphemeralFlushError, EphemeralKeyNotFoundError, QueryBuilder, buildPredicateSql, createActionBuilder, createJobBuilder, createMutationBuilder, createQueryBuilder, defineComputedField, defineSchema, getContextRegistry, groupByToMap, jsonContains, jsonPathExists, jsonPathExtract, matchesPredicate, patchZod, router, schemaRegistry, shouldTrackSchema, stableStringify, supaliveStringify, tableNameToId };
|
|
70
71
|
|
|
71
72
|
//# sourceMappingURL=procedure.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"procedure.js","names":[],"sources":["../../../src/router/zod_patch.ts"],"sourcesContent":["// ─── Zod .modelName() extension ─────────────────────────────────────────────\n// Patches every Zod schema type with a `.modelName(\"Name\")` method that sets\n// `__genType` metadata for codegen model renaming.\n//\n// Zod v4: `z.string` is a factory — `z.string.prototype` is NOT the real class\n// prototype. We collect the actual prototypes by creating one instance per type,\n// then patch each unique prototype once.\n\nimport type { ZodType } from \"zod\";\nimport * as z from \"zod\";\n\n/**\n * Patch all Zod schema types on the given `z` namespace with `.modelName(name)`.\n * Must be called with the same `z` instance the consumer uses so the prototypes\n * match. Runs once per unique `z` instance (tracked via a WeakSet).\n */\nexport function patchZod(zInstance: typeof z): void {\n const key = \"supalive_model_name_ext\";\n const patchedInstances: Set<object> = (globalThis as any)[key] ??= new Set();\n if (patchedInstances.has(zInstance)) return;\n patchedInstances.add(zInstance);\n\n const patched = new Set<object>();\n const samples: ZodType[] = [\n zInstance.string(), zInstance.number(), zInstance.boolean(), zInstance.bigint(), zInstance.date(),\n zInstance.object({}), zInstance.array(zInstance.string()), zInstance.enum([\"_\"]),\n zInstance.literal(\"_\"), zInstance.null(), zInstance.undefined(), zInstance.any(), zInstance.unknown(),\n zInstance.void(), zInstance.never(), zInstance.nan(), zInstance.record(zInstance.string(), zInstance.string()),\n zInstance.union([zInstance.string(), zInstance.number()]), zInstance.intersection(zInstance.string(), zInstance.string()),\n zInstance.tuple([zInstance.string()]), zInstance.promise(zInstance.string()), zInstance.custom(),\n zInstance.coerce.string(), zInstance.coerce.number(), zInstance.coerce.boolean(),\n zInstance.coerce.bigint(), zInstance.coerce.date(),\n zInstance.string().optional(), zInstance.string().nullable(), zInstance.string().default(\"\"),\n zInstance.string().pipe(zInstance.string()), zInstance.string().transform(() => \"\"),\n ];\n for (const inst of samples) {\n const proto = Object.getPrototypeOf(inst);\n if (patched.has(proto)) continue;\n patched.add(proto);\n const metaDesc = Object.getOwnPropertyDescriptor(proto, \"meta\");\n if (!metaDesc || !metaDesc.get) continue;\n if ((proto as any).modelName) continue;\n Object.defineProperty(proto, \"modelName\", {\n value: function modelName(name: string) {\n return this.meta({ __genType: name });\n },\n writable: true,\n configurable: true,\n });\n }\n}"],"mappings":"
|
|
1
|
+
{"version":3,"file":"procedure.js","names":[],"sources":["../../../src/router/zod_patch.ts"],"sourcesContent":["// ─── Zod .modelName() extension ─────────────────────────────────────────────\n// Patches every Zod schema type with a `.modelName(\"Name\")` method that sets\n// `__genType` metadata for codegen model renaming.\n//\n// Zod v4: `z.string` is a factory — `z.string.prototype` is NOT the real class\n// prototype. We collect the actual prototypes by creating one instance per type,\n// then patch each unique prototype once.\n\nimport type { ZodType } from \"zod\";\nimport * as z from \"zod\";\n\n/**\n * Patch all Zod schema types on the given `z` namespace with `.modelName(name)`.\n * Must be called with the same `z` instance the consumer uses so the prototypes\n * match. Runs once per unique `z` instance (tracked via a WeakSet).\n */\nexport function patchZod(zInstance: typeof z): void {\n const key = \"supalive_model_name_ext\";\n const patchedInstances: Set<object> = (globalThis as any)[key] ??= new Set();\n if (patchedInstances.has(zInstance)) return;\n patchedInstances.add(zInstance);\n\n const patched = new Set<object>();\n const samples: ZodType[] = [\n zInstance.string(), zInstance.number(), zInstance.boolean(), zInstance.bigint(), zInstance.date(),\n zInstance.object({}), zInstance.array(zInstance.string()), zInstance.enum([\"_\"]),\n zInstance.literal(\"_\"), zInstance.null(), zInstance.undefined(), zInstance.any(), zInstance.unknown(),\n zInstance.void(), zInstance.never(), zInstance.nan(), zInstance.record(zInstance.string(), zInstance.string()),\n zInstance.union([zInstance.string(), zInstance.number()]), zInstance.intersection(zInstance.string(), zInstance.string()),\n zInstance.tuple([zInstance.string()]), zInstance.promise(zInstance.string()), zInstance.custom(),\n zInstance.coerce.string(), zInstance.coerce.number(), zInstance.coerce.boolean(),\n zInstance.coerce.bigint(), zInstance.coerce.date(),\n zInstance.string().optional(), zInstance.string().nullable(), zInstance.string().default(\"\"),\n zInstance.string().pipe(zInstance.string()), zInstance.string().transform(() => \"\"),\n ];\n for (const inst of samples) {\n const proto = Object.getPrototypeOf(inst);\n if (patched.has(proto)) continue;\n patched.add(proto);\n const metaDesc = Object.getOwnPropertyDescriptor(proto, \"meta\");\n if (!metaDesc || !metaDesc.get) continue;\n if ((proto as any).modelName) continue;\n Object.defineProperty(proto, \"modelName\", {\n value: function modelName(name: string) {\n return this.meta({ __genType: name });\n },\n writable: true,\n configurable: true,\n });\n }\n}"],"mappings":";;;;;;;;;;;;AAgBA,SAAgB,SAAS,WAA2B;CAChD,MAAM,MAAM;CACZ,MAAM,mBAAgC,WAAoB,yBAAS,IAAI,IAAI;CAC3E,IAAI,iBAAiB,IAAI,SAAS,GAAG;CACrC,iBAAiB,IAAI,SAAS;CAE9B,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,UAAqB;EACvB,UAAU,OAAO;EAAG,UAAU,OAAO;EAAG,UAAU,QAAQ;EAAG,UAAU,OAAO;EAAG,UAAU,KAAK;EAChG,UAAU,OAAO,CAAC,CAAC;EAAG,UAAU,MAAM,UAAU,OAAO,CAAC;EAAG,UAAU,KAAK,CAAC,GAAG,CAAC;EAC/E,UAAU,QAAQ,GAAG;EAAG,UAAU,KAAK;EAAG,UAAU,UAAU;EAAG,UAAU,IAAI;EAAG,UAAU,QAAQ;EACpG,UAAU,KAAK;EAAG,UAAU,MAAM;EAAG,UAAU,IAAI;EAAG,UAAU,OAAO,UAAU,OAAO,GAAG,UAAU,OAAO,CAAC;EAC7G,UAAU,MAAM,CAAC,UAAU,OAAO,GAAG,UAAU,OAAO,CAAC,CAAC;EAAG,UAAU,aAAa,UAAU,OAAO,GAAG,UAAU,OAAO,CAAC;EACxH,UAAU,MAAM,CAAC,UAAU,OAAO,CAAC,CAAC;EAAG,UAAU,QAAQ,UAAU,OAAO,CAAC;EAAG,UAAU,OAAO;EAC/F,UAAU,OAAO,OAAO;EAAG,UAAU,OAAO,OAAO;EAAG,UAAU,OAAO,QAAQ;EAC/E,UAAU,OAAO,OAAO;EAAG,UAAU,OAAO,KAAK;EACjD,UAAU,OAAO,CAAC,CAAC,SAAS;EAAG,UAAU,OAAO,CAAC,CAAC,SAAS;EAAG,UAAU,OAAO,CAAC,CAAC,QAAQ,EAAE;EAC3F,UAAU,OAAO,CAAC,CAAC,KAAK,UAAU,OAAO,CAAC;EAAG,UAAU,OAAO,CAAC,CAAC,gBAAgB,EAAE;CACtF;CACA,KAAK,MAAM,QAAQ,SAAS;EACxB,MAAM,QAAQ,OAAO,eAAe,IAAI;EACxC,IAAI,QAAQ,IAAI,KAAK,GAAG;EACxB,QAAQ,IAAI,KAAK;EACjB,MAAM,WAAW,OAAO,yBAAyB,OAAO,MAAM;EAC9D,IAAI,CAAC,YAAY,CAAC,SAAS,KAAK;EAChC,IAAK,MAAc,WAAW;EAC9B,OAAO,eAAe,OAAO,aAAa;GACtC,OAAO,SAAS,UAAU,MAAc;IACpC,OAAO,KAAK,KAAK,EAAE,WAAW,KAAK,CAAC;GACxC;GACA,UAAU;GACV,cAAc;EAClB,CAAC;CACL;AACJ"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Bt as IncomingJobRequest, D as Context, Gt as ScheduleHandle, Ht as JobScheduler, Kt as ScheduledJobDef, Lt as DevScheduler, Rt as DevSchedulerOptions, Ut as QStashScheduler, Vt as JobClient, Wt as QStashSchedulerOptions, _r as
|
|
2
|
-
import { t as MySqlDatabase } from "../../mysql-
|
|
3
|
-
import { t as PgDatabase } from "../../postgres-
|
|
4
|
-
import { A as QueryTrigger, C as SubManagerLink, D as OperationKind, E as OperationEvent, F as startTimer, I as traceQueryExecution, M as configureRootLogger, N as elapsedMs, O as OperationOutcome, P as getRootLogger, S as SubManagerClient, T as ObservabilityOptions, b as SupaliveServerConfig, j as RequestLogMode, k as OperationTransport, p as DatabaseConfig, u as SubId, w as Observability, x as UpstashConfig, y as SubscriptionManagerConfig } from "../../types_server-
|
|
1
|
+
import { Ar as UpdateSubscriptionReadSetParamsSchema, Bt as IncomingJobRequest, Cr as RegisterSubscriptionResult, D as Context, Er as UnregisterSubscriptionResult, Gt as ScheduleHandle, Ht as JobScheduler, Kt as ScheduledJobDef, Lt as DevScheduler, Rt as DevSchedulerOptions, Sr as RegisterSubscriptionParamsSchema, Tr as UnregisterSubscriptionParamsSchema, Ut as QStashScheduler, Vt as JobClient, Wt as QStashSchedulerOptions, _r as InvalidateEphemeralResult, an as EMPTY_EPHEMERAL_KEYS, br as InvalidateWritesetResult, cn as EphemeralFlushError, ct as Router, dn as EphemeralSetOptions, fn as EphemeralStore, fr as CacheLayer, gr as InvalidateEphemeralParamsSchema, hr as InvalidateEphemeralParams, jr as UpdateSubscriptionReadSetResult, kr as UpdateSubscriptionReadSetParams, ln as EphemeralKeyNotFoundError, mn as createMemoryEphemeralStore, mr as AffectedSubscription, on as EPHEMERAL_DEFAULT_TTL_SECONDS, pn as EphemeralWriter, pr as IORedisClient, qt as SupaliveDb, rr as Database, sn as EphemeralDecodeError, un as EphemeralReader, vr as InvalidateWritesetParams, wr as UnregisterSubscriptionParams, xr as RegisterSubscriptionParams, yr as InvalidateWritesetParamsSchema, zt as EnqueueOptions } from "../../index-DB7_pv9P.js";
|
|
2
|
+
import { t as MySqlDatabase } from "../../mysql-Bvc_iWUy.js";
|
|
3
|
+
import { t as PgDatabase } from "../../postgres-C5CbPBcp.js";
|
|
4
|
+
import { A as QueryTrigger, C as SubManagerLink, D as OperationKind, E as OperationEvent, F as startTimer, I as traceQueryExecution, M as configureRootLogger, N as elapsedMs, O as OperationOutcome, P as getRootLogger, S as SubManagerClient, T as ObservabilityOptions, b as SupaliveServerConfig, j as RequestLogMode, k as OperationTransport, p as DatabaseConfig, u as SubId, w as Observability, x as UpstashConfig, y as SubscriptionManagerConfig } from "../../types_server-xHmZ6baD.js";
|
|
5
5
|
import pino, { Level } from "pino";
|
|
6
6
|
|
|
7
7
|
//#region src/server/supalive-server.d.ts
|
|
@@ -151,6 +151,16 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
151
151
|
*/
|
|
152
152
|
private dropSubscriptionLocally;
|
|
153
153
|
private handleMutationCommit;
|
|
154
|
+
/**
|
|
155
|
+
* Invalidate subscriptions that read any of `keys`. The ephemeral twin of
|
|
156
|
+
* {@link handleMutationCommit} (db/ephemeral.ts): same central sub-manager,
|
|
157
|
+
* same dispatch, same recompute — only the matching differs (exact key lookup
|
|
158
|
+
* instead of write-set/read-set overlap).
|
|
159
|
+
*
|
|
160
|
+
* `version` is the store's monotonic write sequence, standing in for a
|
|
161
|
+
* mutation's `commitTs` as the cross-instance recompute-lock discriminator.
|
|
162
|
+
*/
|
|
163
|
+
private handleEphemeralWrite;
|
|
154
164
|
/**
|
|
155
165
|
* Route an affected sub to whichever instance can actually run the
|
|
156
166
|
* recompute:
|
|
@@ -163,11 +173,42 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
163
173
|
*
|
|
164
174
|
* If `notifyInstances` is empty (the sub has no live holders), we drop
|
|
165
175
|
* the message — the next subscribe will recompute fresh state.
|
|
176
|
+
*
|
|
177
|
+
* `commitTs` identifies the write being reacted to — a mutation's `commitTs`,
|
|
178
|
+
* or an ephemeral write's sequence number(revision). Its only job is that every
|
|
179
|
+
* instance racing over the SAME write derives the same lock key, so any
|
|
180
|
+
* monotonic token works.
|
|
166
181
|
*/
|
|
167
182
|
private dispatchAffected;
|
|
168
183
|
private hasLocalSessionFor;
|
|
169
184
|
private publishRecomputeRace;
|
|
185
|
+
/**
|
|
186
|
+
* Recomputes currently running, keyed by subId. Holds the in-flight promise
|
|
187
|
+
* plus the newest request that arrived while it was running — see
|
|
188
|
+
* {@link reexecuteAffectedQuery}.
|
|
189
|
+
*/
|
|
190
|
+
private recomputesInFlight;
|
|
191
|
+
/**
|
|
192
|
+
* Recompute a subscription and push the result, coalescing concurrent
|
|
193
|
+
* requests for the same subId.
|
|
194
|
+
*
|
|
195
|
+
* A subscription is already shared by every session watching the same
|
|
196
|
+
* (procedure, args, identity), so one write produces one recompute no matter
|
|
197
|
+
* how many clients are attached. What that does NOT cover is RATE: two writes
|
|
198
|
+
* arriving 60ms apart used to start two overlapping recomputes of the same
|
|
199
|
+
* sub, which could finish out of order and leave clients on the older of the
|
|
200
|
+
* two results — `handleSubscriptionUpdate` applies whatever lands last.
|
|
201
|
+
*
|
|
202
|
+
* High-frequency ephemeral state (a position stream) makes that the normal
|
|
203
|
+
* case rather than a rare one, so requests are serialized per subId here:
|
|
204
|
+
* while one runs, later requests collapse into a single follow-up that fires
|
|
205
|
+
* once it finishes. Each recompute reads current state, so the follow-up
|
|
206
|
+
* reflects every write that arrived during the previous run — collapsing
|
|
207
|
+
* loses nothing but redundant work, and the last result published is always
|
|
208
|
+
* the newest.
|
|
209
|
+
*/
|
|
170
210
|
private reexecuteAffectedQuery;
|
|
211
|
+
private runRecompute;
|
|
171
212
|
private executeLiveQuery;
|
|
172
213
|
private sendMessage;
|
|
173
214
|
private sendError;
|
|
@@ -256,6 +297,13 @@ declare class SubscriptionManager {
|
|
|
256
297
|
private unregisterSubscription;
|
|
257
298
|
private unregisterSubscriptions;
|
|
258
299
|
private invalidateWriteset;
|
|
300
|
+
/**
|
|
301
|
+
* Ephemeral-key invalidation. Fans out to every worker exactly like
|
|
302
|
+
* {@link invalidateWriteset}: subscriptions are routed by hash(subId), which
|
|
303
|
+
* says nothing about which keys they read, so the holders of a given key can
|
|
304
|
+
* sit in any slice.
|
|
305
|
+
*/
|
|
306
|
+
private invalidateEphemeral;
|
|
259
307
|
}
|
|
260
308
|
//#endregion
|
|
261
309
|
//#region src/db/init_db.d.ts
|
|
@@ -299,6 +347,9 @@ type InitDbOptions = {
|
|
|
299
347
|
CacheLayer: CacheLayer;
|
|
300
348
|
forceBootstrapReload?: boolean;
|
|
301
349
|
workerId?: number;
|
|
350
|
+
/** Default TTL for `ctx.db.ephemeral` writes (see db/ephemeral.ts).
|
|
351
|
+
* Defaults to 7 days. A server overrides this from its own config. */
|
|
352
|
+
ephemeralTtlSeconds?: number;
|
|
302
353
|
};
|
|
303
354
|
declare function initDatabase(options: InitDbOptions): Promise<SupaliveDb>;
|
|
304
355
|
declare function createDatabase(config: DatabaseConfig, workerId?: number): PgDatabase | MySqlDatabase;
|
|
@@ -353,5 +404,5 @@ declare function generateSubscriptionId(procedure: string, input: unknown | stri
|
|
|
353
404
|
*/
|
|
354
405
|
declare function generateCacheKey(queryName: string, input: unknown | string, queryIdentity: string): Promise<string>;
|
|
355
406
|
//#endregion
|
|
356
|
-
export { ANONYMOUS_IDENTITY, type AffectedSubscription, CORE_VERSION, CacheLayer, DB_QUERY_TIMEOUT_MS, DevScheduler, type DevSchedulerOptions, type EnqueueOptions, type IncomingJobRequest, InitCacheLayerOptions, InitDbOptions, type InvalidateWritesetParams, InvalidateWritesetParamsSchema, type InvalidateWritesetResult, JobClient, type JobScheduler, Observability, ObservabilityOptions, OperationEvent, OperationKind, OperationOutcome, OperationTransport, QStashScheduler, type QStashSchedulerOptions, QueryTrigger, type RegisterSubscriptionParams, RegisterSubscriptionParamsSchema, type RegisterSubscriptionResult, RequestLogMode, type ScheduleHandle, type ScheduledJobDef, type SubId, SubManagerClient, type SubManagerLink, SubscriptionManager, SupaliveWebSocketServer, type UnregisterSubscriptionParams, UnregisterSubscriptionParamsSchema, type UnregisterSubscriptionResult, type UpdateSubscriptionReadSetParams, UpdateSubscriptionReadSetParamsSchema, type UpdateSubscriptionReadSetResult, appInstanceId, bootstrapDbTypes, configureRootLogger, createDatabase, elapsedMs, generateCacheKey, generateSubscriptionId, getHashOf, getRootLogger, initCacheLayer, initCore, initDatabase, isProduction, logLevelOf, logger, serializeMapValue, startTimer, traceQueryExecution };
|
|
407
|
+
export { ANONYMOUS_IDENTITY, type AffectedSubscription, CORE_VERSION, CacheLayer, DB_QUERY_TIMEOUT_MS, DevScheduler, type DevSchedulerOptions, EMPTY_EPHEMERAL_KEYS, EPHEMERAL_DEFAULT_TTL_SECONDS, type EnqueueOptions, EphemeralDecodeError, EphemeralFlushError, EphemeralKeyNotFoundError, type EphemeralReader, type EphemeralSetOptions, EphemeralStore, type EphemeralWriter, type IncomingJobRequest, InitCacheLayerOptions, InitDbOptions, type InvalidateEphemeralParams, InvalidateEphemeralParamsSchema, type InvalidateEphemeralResult, type InvalidateWritesetParams, InvalidateWritesetParamsSchema, type InvalidateWritesetResult, JobClient, type JobScheduler, Observability, ObservabilityOptions, OperationEvent, OperationKind, OperationOutcome, OperationTransport, QStashScheduler, type QStashSchedulerOptions, QueryTrigger, type RegisterSubscriptionParams, RegisterSubscriptionParamsSchema, type RegisterSubscriptionResult, RequestLogMode, type ScheduleHandle, type ScheduledJobDef, type SubId, SubManagerClient, type SubManagerLink, SubscriptionManager, SupaliveWebSocketServer, type UnregisterSubscriptionParams, UnregisterSubscriptionParamsSchema, type UnregisterSubscriptionResult, type UpdateSubscriptionReadSetParams, UpdateSubscriptionReadSetParamsSchema, type UpdateSubscriptionReadSetResult, appInstanceId, bootstrapDbTypes, configureRootLogger, createDatabase, createMemoryEphemeralStore, elapsedMs, generateCacheKey, generateSubscriptionId, getHashOf, getRootLogger, initCacheLayer, initCore, initDatabase, isProduction, logLevelOf, logger, serializeMapValue, startTimer, traceQueryExecution };
|
|
357
408
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","names":[],"sources":["../../../src/server/supalive-server.ts","../../../src/logger.ts","../../../src/server/sub-manager.ts","../../../src/db/init_db.ts","../../../src/server/sub_hash.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","names":[],"sources":["../../../src/server/supalive-server.ts","../../../src/logger.ts","../../../src/server/sub-manager.ts","../../../src/db/init_db.ts","../../../src/server/sub_hash.ts"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { l as primaryOnlyConn, n as getContextRegistry } from "../../router-DP2ThAwh.js";
|
|
2
2
|
import { n as stableStringify, r as supaliveStringify, t as groupByToMap } from "../../helper-zdJT5FUc.js";
|
|
3
|
-
import { i as
|
|
3
|
+
import { a as EphemeralKeyNotFoundError, c as createMemoryEphemeralStore, i as EphemeralFlushError, n as EPHEMERAL_DEFAULT_TTL_SECONDS, o as EphemeralStore, r as EphemeralDecodeError, t as EMPTY_EPHEMERAL_KEYS } from "../../ephemeral-CkidSG9y.js";
|
|
4
|
+
import { i as AuthenticationError, o as ClientMessageSchema } from "../../types_client_rpc-CqUVHTwT.js";
|
|
4
5
|
import { n as RemoteSubscriptionMessageSchema } from "../../types_server-BhC19R2a.js";
|
|
5
|
-
import { a as
|
|
6
|
-
import { a as elapsedMs, c as traceQueryExecution, d as generateSubscriptionId, f as getHashOf, i as configureRootLogger, l as ANONYMOUS_IDENTITY, o as getRootLogger, p as resolveQueryIdentity, r as Observability, s as startTimer, t as runCachedQuery, u as generateCacheKey } from "../../one-shot-query-
|
|
7
|
-
import { S as
|
|
6
|
+
import { a as logLevelOf, i as isProduction, n as sleep, o as logger, r as appInstanceId, s as serializeMapValue } from "../../realtime_db-CTGOrFuV.js";
|
|
7
|
+
import { a as elapsedMs, c as traceQueryExecution, d as generateSubscriptionId, f as getHashOf, i as configureRootLogger, l as ANONYMOUS_IDENTITY, o as getRootLogger, p as resolveQueryIdentity, r as Observability, s as startTimer, t as runCachedQuery, u as generateCacheKey } from "../../one-shot-query-DAAHGTcI.js";
|
|
8
|
+
import { C as RETENTION_WATERMARK_CHANNEL, S as UpdateSubscriptionReadSetResultSchema, _ as RegisterSubscriptionResultSchema, a as bootstrapDbTypes, b as UnregisterSubscriptionsResultSchema, c as initCore, d as InvalidateEphemeralParamsSchema, f as InvalidateEphemeralResultSchema, g as RegisterSubscriptionParamsSchema, h as RegisterSubscriptionBatchResultSchema, i as DB_QUERY_TIMEOUT_MS, l as initDatabase, m as InvalidateWritesetResultSchema, n as SubscriptionWorker, o as createDatabase, p as InvalidateWritesetParamsSchema, r as CORE_VERSION, s as initCacheLayer, t as dispatchWorkerMessage, u as CacheLayer, v as UnregisterSubscriptionParamsSchema, w as RetentionWatermark, x as UpdateSubscriptionReadSetParamsSchema, y as UnregisterSubscriptionResultSchema } from "../../sub-worker-dispatch-Dwrp3c40.js";
|
|
8
9
|
import { context, trace } from "@opentelemetry/api";
|
|
9
10
|
import { v4 } from "uuid";
|
|
10
11
|
import { createServer } from "http";
|
|
@@ -58,6 +59,16 @@ var SubManagerClient = class {
|
|
|
58
59
|
bufferedWriteSets = [];
|
|
59
60
|
bufferLimit;
|
|
60
61
|
bufferDroppedDuringOutage = false;
|
|
62
|
+
/**
|
|
63
|
+
* Ephemeral keys written while state === 'busy', mapped to the latest version
|
|
64
|
+
* seen for each. A MAP, not a queue like `bufferedWriteSets`: an ephemeral
|
|
65
|
+
* recompute re-reads the current value from Redis, so N writes to one key
|
|
66
|
+
* during an outage collapse into a single post-recovery invalidation with no
|
|
67
|
+
* loss of information. That makes the buffer self-bounding at the number of
|
|
68
|
+
* DISTINCT keys — which is what lets a 60ms position stream survive a long
|
|
69
|
+
* reconnect without a size limit or a drop path.
|
|
70
|
+
*/
|
|
71
|
+
bufferedEphemeralKeys = /* @__PURE__ */ new Map();
|
|
61
72
|
recoveryDriver;
|
|
62
73
|
affectedHandler;
|
|
63
74
|
constructor(urlOrOptions) {
|
|
@@ -120,6 +131,24 @@ var SubManagerClient = class {
|
|
|
120
131
|
return this.call("invalidateWriteset", params, InvalidateWritesetResultSchema);
|
|
121
132
|
}
|
|
122
133
|
/**
|
|
134
|
+
* Ephemeral-key counterpart of {@link invalidateWriteset}. Buffers the same
|
|
135
|
+
* way during an outage, but into {@link bufferedEphemeralKeys} — see there for
|
|
136
|
+
* why a map rather than a queue.
|
|
137
|
+
*
|
|
138
|
+
* Unlike the write-set buffer there is no drop path: ephemeral state has no
|
|
139
|
+
* commit log for `register` to replay, so a dropped key would leave its
|
|
140
|
+
* subscribers stale until something else happened to invalidate them.
|
|
141
|
+
* Collapsing per key keeps the buffer small enough that dropping is never
|
|
142
|
+
* needed.
|
|
143
|
+
*/
|
|
144
|
+
async invalidateEphemeral(params) {
|
|
145
|
+
if (this.state === "busy") {
|
|
146
|
+
for (const key of params.keys) this.bufferedEphemeralKeys.set(key, params.version);
|
|
147
|
+
return { affected: [] };
|
|
148
|
+
}
|
|
149
|
+
return this.call("invalidateEphemeral", params, InvalidateEphemeralResultSchema);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
123
152
|
* Single point through which RPCs go. Throws on transport / server error.
|
|
124
153
|
* `registerSubscription`, `updateSubscriptionReadSet`, and
|
|
125
154
|
* `unregisterSubscription` are NOT gated on the ready state: during a
|
|
@@ -142,6 +171,9 @@ var SubManagerClient = class {
|
|
|
142
171
|
this.bufferedWriteSets.push(...writeSet);
|
|
143
172
|
}
|
|
144
173
|
async flushBuffer() {
|
|
174
|
+
await Promise.all([this.flushWriteSetBuffer(), this.flushEphemeralBuffer()]);
|
|
175
|
+
}
|
|
176
|
+
async flushWriteSetBuffer() {
|
|
145
177
|
if (this.bufferedWriteSets.length === 0) return;
|
|
146
178
|
const writeSet = this.bufferedWriteSets;
|
|
147
179
|
this.bufferedWriteSets = [];
|
|
@@ -153,6 +185,28 @@ var SubManagerClient = class {
|
|
|
153
185
|
logger$3.error(err, "Failed to flush invalidate buffer after recovery");
|
|
154
186
|
}
|
|
155
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Replay the outage's ephemeral writes as ONE invalidation. The version sent
|
|
190
|
+
* is the highest buffered — every collapsed write is subsumed by the single
|
|
191
|
+
* recompute this triggers, which reads whatever Redis holds now, so using the
|
|
192
|
+
* newest version keeps the recompute lock keyed to the most recent write
|
|
193
|
+
* rather than an already-superseded one.
|
|
194
|
+
*/
|
|
195
|
+
async flushEphemeralBuffer() {
|
|
196
|
+
if (this.bufferedEphemeralKeys.size === 0) return;
|
|
197
|
+
const keys = [...this.bufferedEphemeralKeys.keys()];
|
|
198
|
+
const version = [...this.bufferedEphemeralKeys.values()].reduce((a, b) => BigInt(b) > BigInt(a) ? b : a);
|
|
199
|
+
this.bufferedEphemeralKeys.clear();
|
|
200
|
+
try {
|
|
201
|
+
const result = await this.call("invalidateEphemeral", {
|
|
202
|
+
keys,
|
|
203
|
+
version
|
|
204
|
+
}, InvalidateEphemeralResultSchema);
|
|
205
|
+
if (this.affectedHandler && result.affected.length > 0) await this.affectedHandler(result.affected);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
logger$3.error(err, "Failed to flush ephemeral invalidate buffer after recovery");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
156
210
|
markBusy() {
|
|
157
211
|
if (this.state === "busy") return;
|
|
158
212
|
this.state = "busy";
|
|
@@ -202,6 +256,10 @@ var SubManagerClient = class {
|
|
|
202
256
|
bufferSize() {
|
|
203
257
|
return this.bufferedWriteSets.length;
|
|
204
258
|
}
|
|
259
|
+
/** @internal */
|
|
260
|
+
ephemeralBufferSize() {
|
|
261
|
+
return this.bufferedEphemeralKeys.size;
|
|
262
|
+
}
|
|
205
263
|
};
|
|
206
264
|
//#endregion
|
|
207
265
|
//#region src/jobs/scheduler.ts
|
|
@@ -958,6 +1016,9 @@ var SupaliveWebSocketServer = class {
|
|
|
958
1016
|
this.db.setOnAfterCommit((writeSet, commitTs) => {
|
|
959
1017
|
this.handleMutationCommit(writeSet, commitTs).catch((err) => this.log.error(err, "post-commit invalidation failed"));
|
|
960
1018
|
});
|
|
1019
|
+
this.db.setOnAfterEphemeralWrite((keys, version) => {
|
|
1020
|
+
this.handleEphemeralWrite(keys, version).catch((err) => this.log.error(err, "ephemeral invalidation failed"));
|
|
1021
|
+
});
|
|
961
1022
|
this.scheduler = config.scheduler;
|
|
962
1023
|
this.jobPath = normalizeJobPath(config.jobPath ?? "/_jobs");
|
|
963
1024
|
this.jobClient = new JobClient(this.scheduler, (name) => this.endpointFor(name));
|
|
@@ -1589,6 +1650,7 @@ var SupaliveWebSocketServer = class {
|
|
|
1589
1650
|
subId,
|
|
1590
1651
|
lastSnapshotTs: liveResult.ts,
|
|
1591
1652
|
readSet: liveResult.readSet,
|
|
1653
|
+
ephemeralKeys: liveResult.ephemeralKeys,
|
|
1592
1654
|
instanceName: this.instanceId
|
|
1593
1655
|
});
|
|
1594
1656
|
this.cache.setQueryCacheFor(cacheKey, data, liveResult.ts).catch((err) => this.log.warn(err, "writing query cache failed"));
|
|
@@ -1775,12 +1837,38 @@ var SupaliveWebSocketServer = class {
|
|
|
1775
1837
|
try {
|
|
1776
1838
|
const result = await this.subManagerClient.invalidateWriteset({ writeSet });
|
|
1777
1839
|
this.log.debug({ affected: result }, "Sub-managers invalidation result");
|
|
1778
|
-
if (result?.affected?.length > 0) await Promise.allSettled(result.affected.map((affected) => this.dispatchAffected(affected, commitTs)));
|
|
1840
|
+
if (result?.affected?.length > 0) await Promise.allSettled(result.affected.map((affected) => this.dispatchAffected(affected, commitTs.toString())));
|
|
1779
1841
|
} catch (err) {
|
|
1780
1842
|
this.log.error(err, "Failed to notify sub-managers");
|
|
1781
1843
|
}
|
|
1782
1844
|
}
|
|
1783
1845
|
/**
|
|
1846
|
+
* Invalidate subscriptions that read any of `keys`. The ephemeral twin of
|
|
1847
|
+
* {@link handleMutationCommit} (db/ephemeral.ts): same central sub-manager,
|
|
1848
|
+
* same dispatch, same recompute — only the matching differs (exact key lookup
|
|
1849
|
+
* instead of write-set/read-set overlap).
|
|
1850
|
+
*
|
|
1851
|
+
* `version` is the store's monotonic write sequence, standing in for a
|
|
1852
|
+
* mutation's `commitTs` as the cross-instance recompute-lock discriminator.
|
|
1853
|
+
*/
|
|
1854
|
+
async handleEphemeralWrite(keys, version) {
|
|
1855
|
+
if (keys.length === 0) return;
|
|
1856
|
+
this.log.debug({
|
|
1857
|
+
keys,
|
|
1858
|
+
version
|
|
1859
|
+
}, "Ephemeral write committed");
|
|
1860
|
+
try {
|
|
1861
|
+
const result = await this.subManagerClient.invalidateEphemeral({
|
|
1862
|
+
keys,
|
|
1863
|
+
version
|
|
1864
|
+
});
|
|
1865
|
+
this.log.debug({ affected: result }, "Ephemeral invalidation result");
|
|
1866
|
+
if (result?.affected?.length > 0) await Promise.allSettled(result.affected.map((affected) => this.dispatchAffected(affected, version)));
|
|
1867
|
+
} catch (err) {
|
|
1868
|
+
this.log.error(err, "Failed to notify sub-managers of ephemeral write");
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1784
1872
|
* Route an affected sub to whichever instance can actually run the
|
|
1785
1873
|
* recompute:
|
|
1786
1874
|
* • If this instance has a local session for the sub, recompute here
|
|
@@ -1792,6 +1880,11 @@ var SupaliveWebSocketServer = class {
|
|
|
1792
1880
|
*
|
|
1793
1881
|
* If `notifyInstances` is empty (the sub has no live holders), we drop
|
|
1794
1882
|
* the message — the next subscribe will recompute fresh state.
|
|
1883
|
+
*
|
|
1884
|
+
* `commitTs` identifies the write being reacted to — a mutation's `commitTs`,
|
|
1885
|
+
* or an ephemeral write's sequence number(revision). Its only job is that every
|
|
1886
|
+
* instance racing over the SAME write derives the same lock key, so any
|
|
1887
|
+
* monotonic token works.
|
|
1795
1888
|
*/
|
|
1796
1889
|
async dispatchAffected(affected, commitTs) {
|
|
1797
1890
|
if (this.hasLocalSessionFor(affected.subId)) {
|
|
@@ -1816,7 +1909,7 @@ var SupaliveWebSocketServer = class {
|
|
|
1816
1909
|
queryName: affected.queryName,
|
|
1817
1910
|
args: affected.args,
|
|
1818
1911
|
notifyInstances: affected.notifyInstances,
|
|
1819
|
-
commitTs
|
|
1912
|
+
commitTs,
|
|
1820
1913
|
originInstance: this.instanceId
|
|
1821
1914
|
});
|
|
1822
1915
|
const publishPromises = affected.notifyInstances.map(async (instance) => {
|
|
@@ -1830,7 +1923,60 @@ var SupaliveWebSocketServer = class {
|
|
|
1830
1923
|
});
|
|
1831
1924
|
await Promise.all(publishPromises);
|
|
1832
1925
|
}
|
|
1926
|
+
/**
|
|
1927
|
+
* Recomputes currently running, keyed by subId. Holds the in-flight promise
|
|
1928
|
+
* plus the newest request that arrived while it was running — see
|
|
1929
|
+
* {@link reexecuteAffectedQuery}.
|
|
1930
|
+
*/
|
|
1931
|
+
recomputesInFlight = /* @__PURE__ */ new Map();
|
|
1932
|
+
/**
|
|
1933
|
+
* Recompute a subscription and push the result, coalescing concurrent
|
|
1934
|
+
* requests for the same subId.
|
|
1935
|
+
*
|
|
1936
|
+
* A subscription is already shared by every session watching the same
|
|
1937
|
+
* (procedure, args, identity), so one write produces one recompute no matter
|
|
1938
|
+
* how many clients are attached. What that does NOT cover is RATE: two writes
|
|
1939
|
+
* arriving 60ms apart used to start two overlapping recomputes of the same
|
|
1940
|
+
* sub, which could finish out of order and leave clients on the older of the
|
|
1941
|
+
* two results — `handleSubscriptionUpdate` applies whatever lands last.
|
|
1942
|
+
*
|
|
1943
|
+
* High-frequency ephemeral state (a position stream) makes that the normal
|
|
1944
|
+
* case rather than a rare one, so requests are serialized per subId here:
|
|
1945
|
+
* while one runs, later requests collapse into a single follow-up that fires
|
|
1946
|
+
* once it finishes. Each recompute reads current state, so the follow-up
|
|
1947
|
+
* reflects every write that arrived during the previous run — collapsing
|
|
1948
|
+
* loses nothing but redundant work, and the last result published is always
|
|
1949
|
+
* the newest.
|
|
1950
|
+
*/
|
|
1833
1951
|
async reexecuteAffectedQuery(affected, trigger = "recompute") {
|
|
1952
|
+
const inFlight = this.recomputesInFlight.get(affected.subId);
|
|
1953
|
+
if (inFlight) {
|
|
1954
|
+
inFlight.pending = {
|
|
1955
|
+
affected,
|
|
1956
|
+
trigger
|
|
1957
|
+
};
|
|
1958
|
+
return inFlight.running;
|
|
1959
|
+
}
|
|
1960
|
+
const entry = { running: Promise.resolve() };
|
|
1961
|
+
this.recomputesInFlight.set(affected.subId, entry);
|
|
1962
|
+
entry.running = (async () => {
|
|
1963
|
+
try {
|
|
1964
|
+
let next = {
|
|
1965
|
+
affected,
|
|
1966
|
+
trigger
|
|
1967
|
+
};
|
|
1968
|
+
while (next) {
|
|
1969
|
+
await this.runRecompute(next.affected, next.trigger);
|
|
1970
|
+
next = entry.pending;
|
|
1971
|
+
entry.pending = void 0;
|
|
1972
|
+
}
|
|
1973
|
+
} finally {
|
|
1974
|
+
this.recomputesInFlight.delete(affected.subId);
|
|
1975
|
+
}
|
|
1976
|
+
})();
|
|
1977
|
+
return entry.running;
|
|
1978
|
+
}
|
|
1979
|
+
async runRecompute(affected, trigger = "recompute") {
|
|
1834
1980
|
let foundSession = null;
|
|
1835
1981
|
for (const [, session] of this.sessions) if (session.subIds.has(affected.subId)) {
|
|
1836
1982
|
foundSession = session;
|
|
@@ -1848,6 +1994,7 @@ var SupaliveWebSocketServer = class {
|
|
|
1848
1994
|
subId: affected.subId,
|
|
1849
1995
|
lastSnapshotTs: liveResult.ts,
|
|
1850
1996
|
readSet: liveResult.readSet,
|
|
1997
|
+
ephemeralKeys: liveResult.ephemeralKeys,
|
|
1851
1998
|
instanceName: this.instanceId
|
|
1852
1999
|
}), this.cache.setQueryCacheFor(affected.cacheKey, liveResult.data, liveResult.ts)]);
|
|
1853
2000
|
if (!updateResult.tracked) {
|
|
@@ -2288,6 +2435,7 @@ var SubscriptionManager = class SubscriptionManager {
|
|
|
2288
2435
|
unregisterSubscription: (p) => this.unregisterSubscription(p),
|
|
2289
2436
|
unregisterSubscriptions: (p) => this.unregisterSubscriptions(p),
|
|
2290
2437
|
invalidateWriteset: (p) => this.invalidateWriteset(p),
|
|
2438
|
+
invalidateEphemeral: (p) => this.invalidateEphemeral(p),
|
|
2291
2439
|
setRecoveryDriver: () => {},
|
|
2292
2440
|
setAffectedHandler: () => {}
|
|
2293
2441
|
};
|
|
@@ -2330,6 +2478,7 @@ var SubscriptionManager = class SubscriptionManager {
|
|
|
2330
2478
|
wss.register("registerSubscriptionBatch", this.registerSubscriptionBatch.bind(this));
|
|
2331
2479
|
wss.register("updateSubscriptionReadSet", this.updateSubscriptionReadSet.bind(this));
|
|
2332
2480
|
wss.register("invalidateWriteset", this.invalidateWriteset.bind(this));
|
|
2481
|
+
wss.register("invalidateEphemeral", this.invalidateEphemeral.bind(this));
|
|
2333
2482
|
wss.register("unregisterSubscription", this.unregisterSubscription.bind(this));
|
|
2334
2483
|
wss.register("unregisterSubscriptions", this.unregisterSubscriptions.bind(this));
|
|
2335
2484
|
}
|
|
@@ -2387,6 +2536,15 @@ var SubscriptionManager = class SubscriptionManager {
|
|
|
2387
2536
|
async invalidateWriteset(params) {
|
|
2388
2537
|
return { affected: (await Promise.all(this.workers.map((w) => w.send(7, params)))).flat() };
|
|
2389
2538
|
}
|
|
2539
|
+
/**
|
|
2540
|
+
* Ephemeral-key invalidation. Fans out to every worker exactly like
|
|
2541
|
+
* {@link invalidateWriteset}: subscriptions are routed by hash(subId), which
|
|
2542
|
+
* says nothing about which keys they read, so the holders of a given key can
|
|
2543
|
+
* sit in any slice.
|
|
2544
|
+
*/
|
|
2545
|
+
async invalidateEphemeral(params) {
|
|
2546
|
+
return { affected: (await Promise.all(this.workers.map((w) => w.send(14, params)))).flat() };
|
|
2547
|
+
}
|
|
2390
2548
|
};
|
|
2391
2549
|
function resolveWorkerCount(configured) {
|
|
2392
2550
|
if (typeof configured === "number" && configured > 0) return Math.floor(configured);
|
|
@@ -2403,6 +2561,6 @@ function resolveMaxConnectionsPerWorker(config, workers) {
|
|
|
2403
2561
|
return Math.max(1, Math.floor(total / workers));
|
|
2404
2562
|
}
|
|
2405
2563
|
//#endregion
|
|
2406
|
-
export { ANONYMOUS_IDENTITY, CORE_VERSION, CacheLayer, DB_QUERY_TIMEOUT_MS, DevScheduler, InvalidateWritesetParamsSchema, JobClient, Observability, QStashScheduler, RegisterSubscriptionParamsSchema, SubManagerClient, SubscriptionManager, SupaliveWebSocketServer, UnregisterSubscriptionParamsSchema, UpdateSubscriptionReadSetParamsSchema, appInstanceId, bootstrapDbTypes, configureRootLogger, createDatabase, elapsedMs, generateCacheKey, generateSubscriptionId, getHashOf, getRootLogger, initCacheLayer, initCore, initDatabase, isProduction, logLevelOf, logger, serializeMapValue, startTimer, traceQueryExecution };
|
|
2564
|
+
export { ANONYMOUS_IDENTITY, CORE_VERSION, CacheLayer, DB_QUERY_TIMEOUT_MS, DevScheduler, EMPTY_EPHEMERAL_KEYS, EPHEMERAL_DEFAULT_TTL_SECONDS, EphemeralDecodeError, EphemeralFlushError, EphemeralKeyNotFoundError, EphemeralStore, InvalidateEphemeralParamsSchema, InvalidateWritesetParamsSchema, JobClient, Observability, QStashScheduler, RegisterSubscriptionParamsSchema, SubManagerClient, SubscriptionManager, SupaliveWebSocketServer, UnregisterSubscriptionParamsSchema, UpdateSubscriptionReadSetParamsSchema, appInstanceId, bootstrapDbTypes, configureRootLogger, createDatabase, createMemoryEphemeralStore, elapsedMs, generateCacheKey, generateSubscriptionId, getHashOf, getRootLogger, initCacheLayer, initCore, initDatabase, isProduction, logLevelOf, logger, serializeMapValue, startTimer, traceQueryExecution };
|
|
2407
2565
|
|
|
2408
2566
|
//# sourceMappingURL=server.js.map
|