@supalive/core 0.1.3 → 0.1.5
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/README.md +308 -1
- package/dist/helper-CiacMqje.d.ts +14 -0
- package/dist/helper-CiacMqje.d.ts.map +1 -0
- package/dist/helper-zdJT5FUc.js +58 -0
- package/dist/helper-zdJT5FUc.js.map +1 -0
- package/dist/index-CTyXKcq_.d.ts +1736 -0
- package/dist/index-CTyXKcq_.d.ts.map +1 -0
- package/dist/mysql-C8SN443m.d.ts +104 -0
- package/dist/mysql-C8SN443m.d.ts.map +1 -0
- package/dist/mysql-DELSRrpY.js +569 -0
- package/dist/mysql-DELSRrpY.js.map +1 -0
- package/dist/overlap-checker-CVkbbuEQ.js +187 -0
- package/dist/overlap-checker-CVkbbuEQ.js.map +1 -0
- package/dist/postgres-DE-XyNAQ.js +823 -0
- package/dist/postgres-DE-XyNAQ.js.map +1 -0
- package/dist/postgres-D_gwCHx-.d.ts +108 -0
- package/dist/postgres-D_gwCHx-.d.ts.map +1 -0
- package/dist/query-CbQLjeME.js +713 -0
- package/dist/query-CbQLjeME.js.map +1 -0
- package/dist/realtime_db-D9p2X2PH.js +246 -0
- package/dist/realtime_db-D9p2X2PH.js.map +1 -0
- package/dist/router-DlTYWpop.js +81 -0
- package/dist/router-DlTYWpop.js.map +1 -0
- package/dist/schema-SKcIWHfo.js +167 -0
- package/dist/schema-SKcIWHfo.js.map +1 -0
- package/dist/src/client/index.d.ts +2 -17
- package/dist/src/client/index.js +1151 -18
- package/dist/src/client/index.js.map +1 -1
- package/dist/src/exports/mysql.d.ts +2 -2
- package/dist/src/exports/mysql.js +2 -2
- package/dist/src/exports/postgres.d.ts +2 -2
- package/dist/src/exports/postgres.js +2 -2
- package/dist/src/exports/procedure.d.ts +3 -5
- package/dist/src/exports/procedure.js +5 -5
- package/dist/src/exports/server.d.ts +368 -2
- package/dist/src/exports/server.d.ts.map +1 -1
- package/dist/src/exports/server.js +1346 -2
- package/dist/src/exports/server.js.map +1 -1
- package/dist/src/exports/subscription-manager-worker-entry.d.ts +1 -0
- package/dist/src/exports/subscription-manager-worker-entry.js +115 -0
- package/dist/src/exports/subscription-manager-worker-entry.js.map +1 -0
- package/dist/src/exports/types.d.ts +4 -6
- package/dist/src/exports/types.js +5 -6
- package/dist/subscription-worker-BurdPO8d.js +511 -0
- package/dist/subscription-worker-BurdPO8d.js.map +1 -0
- package/dist/types_client_rpc-CIsjQQGG.js +105 -0
- package/dist/types_client_rpc-CIsjQQGG.js.map +1 -0
- package/dist/types_db-Ctf-ksoy.js +168 -0
- package/dist/types_db-Ctf-ksoy.js.map +1 -0
- package/dist/types_server-Ch56y8L3.d.ts +216 -0
- package/dist/types_server-Ch56y8L3.d.ts.map +1 -0
- package/dist/types_server-Dk6o_B7N.js +24 -0
- package/dist/types_server-Dk6o_B7N.js.map +1 -0
- package/package.json +3 -3
- package/dist/src/client/caller_client.d.ts +0 -42
- package/dist/src/client/caller_client.d.ts.map +0 -1
- package/dist/src/client/caller_client.js +0 -77
- package/dist/src/client/caller_client.js.map +0 -1
- package/dist/src/client/client.d.ts +0 -149
- package/dist/src/client/client.d.ts.map +0 -1
- package/dist/src/client/client.js +0 -308
- package/dist/src/client/client.js.map +0 -1
- package/dist/src/client/index.d.ts.map +0 -1
- package/dist/src/client/sub_key.d.ts +0 -20
- package/dist/src/client/sub_key.d.ts.map +0 -1
- package/dist/src/client/sub_key.js +0 -37
- package/dist/src/client/sub_key.js.map +0 -1
- package/dist/src/client/ws_client_manager.d.ts +0 -268
- package/dist/src/client/ws_client_manager.d.ts.map +0 -1
- package/dist/src/client/ws_client_manager.js +0 -1013
- package/dist/src/client/ws_client_manager.js.map +0 -1
- package/dist/src/config.d.ts +0 -117
- package/dist/src/config.d.ts.map +0 -1
- package/dist/src/config.js +0 -2
- package/dist/src/config.js.map +0 -1
- package/dist/src/db/bytes.d.ts +0 -4
- package/dist/src/db/bytes.d.ts.map +0 -1
- package/dist/src/db/bytes.js +0 -24
- package/dist/src/db/bytes.js.map +0 -1
- package/dist/src/db/cache.d.ts +0 -30
- package/dist/src/db/cache.d.ts.map +0 -1
- package/dist/src/db/cache.js +0 -153
- package/dist/src/db/cache.js.map +0 -1
- package/dist/src/db/codec.d.ts +0 -10
- package/dist/src/db/codec.d.ts.map +0 -1
- package/dist/src/db/codec.js +0 -73
- package/dist/src/db/codec.js.map +0 -1
- package/dist/src/db/context.d.ts +0 -28
- package/dist/src/db/context.d.ts.map +0 -1
- package/dist/src/db/context.js +0 -147
- package/dist/src/db/context.js.map +0 -1
- package/dist/src/db/db.d.ts +0 -154
- package/dist/src/db/db.d.ts.map +0 -1
- package/dist/src/db/db.js +0 -23
- package/dist/src/db/db.js.map +0 -1
- package/dist/src/db/mysql.d.ts +0 -120
- package/dist/src/db/mysql.d.ts.map +0 -1
- package/dist/src/db/mysql.js +0 -708
- package/dist/src/db/mysql.js.map +0 -1
- package/dist/src/db/postgres.d.ts +0 -116
- package/dist/src/db/postgres.d.ts.map +0 -1
- package/dist/src/db/postgres.js +0 -998
- package/dist/src/db/postgres.js.map +0 -1
- package/dist/src/db/query.d.ts +0 -174
- package/dist/src/db/query.d.ts.map +0 -1
- package/dist/src/db/query.js +0 -790
- package/dist/src/db/query.js.map +0 -1
- package/dist/src/db/query_definition.d.ts +0 -54
- package/dist/src/db/query_definition.d.ts.map +0 -1
- package/dist/src/db/query_definition.js +0 -47
- package/dist/src/db/query_definition.js.map +0 -1
- package/dist/src/db/realtime_db.d.ts +0 -19
- package/dist/src/db/realtime_db.d.ts.map +0 -1
- package/dist/src/db/realtime_db.js +0 -98
- package/dist/src/db/realtime_db.js.map +0 -1
- package/dist/src/db/schema.d.ts +0 -110
- package/dist/src/db/schema.d.ts.map +0 -1
- package/dist/src/db/schema.js +0 -47
- package/dist/src/db/schema.js.map +0 -1
- package/dist/src/db/types_client_rpc.d.ts +0 -157
- package/dist/src/db/types_client_rpc.d.ts.map +0 -1
- package/dist/src/db/types_client_rpc.js +0 -106
- package/dist/src/db/types_client_rpc.js.map +0 -1
- package/dist/src/db/types_db.d.ts +0 -236
- package/dist/src/db/types_db.d.ts.map +0 -1
- package/dist/src/db/types_db.js +0 -188
- package/dist/src/db/types_db.js.map +0 -1
- package/dist/src/exports/mysql.d.ts.map +0 -1
- package/dist/src/exports/mysql.js.map +0 -1
- package/dist/src/exports/postgres.d.ts.map +0 -1
- package/dist/src/exports/postgres.js.map +0 -1
- package/dist/src/exports/procedure.d.ts.map +0 -1
- package/dist/src/exports/procedure.js.map +0 -1
- package/dist/src/exports/types.d.ts.map +0 -1
- package/dist/src/exports/types.js.map +0 -1
- package/dist/src/helper.d.ts +0 -11
- package/dist/src/helper.d.ts.map +0 -1
- package/dist/src/helper.js +0 -45
- package/dist/src/helper.js.map +0 -1
- package/dist/src/logger.d.ts +0 -7
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js +0 -45
- package/dist/src/logger.js.map +0 -1
- package/dist/src/router/index.d.ts +0 -4
- package/dist/src/router/index.d.ts.map +0 -1
- package/dist/src/router/index.js +0 -4
- package/dist/src/router/index.js.map +0 -1
- package/dist/src/router/procedure.d.ts +0 -204
- package/dist/src/router/procedure.d.ts.map +0 -1
- package/dist/src/router/procedure.js +0 -122
- package/dist/src/router/procedure.js.map +0 -1
- package/dist/src/router/router.d.ts +0 -88
- package/dist/src/router/router.d.ts.map +0 -1
- package/dist/src/router/router.js +0 -88
- package/dist/src/router/router.js.map +0 -1
- package/dist/src/server/hash.d.ts +0 -12
- package/dist/src/server/hash.d.ts.map +0 -1
- package/dist/src/server/hash.js +0 -20
- package/dist/src/server/hash.js.map +0 -1
- package/dist/src/server/hash.test.d.ts +0 -2
- package/dist/src/server/hash.test.d.ts.map +0 -1
- package/dist/src/server/hash.test.js +0 -43
- package/dist/src/server/hash.test.js.map +0 -1
- package/dist/src/server/index.d.ts +0 -8
- package/dist/src/server/index.d.ts.map +0 -1
- package/dist/src/server/index.js +0 -7
- package/dist/src/server/index.js.map +0 -1
- package/dist/src/server/overlap-checker.d.ts +0 -18
- package/dist/src/server/overlap-checker.d.ts.map +0 -1
- package/dist/src/server/overlap-checker.js +0 -247
- package/dist/src/server/overlap-checker.js.map +0 -1
- package/dist/src/server/sub_hash.d.ts +0 -23
- package/dist/src/server/sub_hash.d.ts.map +0 -1
- package/dist/src/server/sub_hash.js +0 -38
- package/dist/src/server/sub_hash.js.map +0 -1
- package/dist/src/server/subscription-manager-client.d.ts +0 -120
- package/dist/src/server/subscription-manager-client.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-client.js +0 -207
- package/dist/src/server/subscription-manager-client.js.map +0 -1
- package/dist/src/server/subscription-manager-types.d.ts +0 -168
- package/dist/src/server/subscription-manager-types.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-types.js +0 -94
- package/dist/src/server/subscription-manager-types.js.map +0 -1
- package/dist/src/server/subscription-manager-worker-entry.d.ts +0 -2
- package/dist/src/server/subscription-manager-worker-entry.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-worker-entry.js +0 -127
- package/dist/src/server/subscription-manager-worker-entry.js.map +0 -1
- package/dist/src/server/subscription-manager-worker-protocol.d.ts +0 -40
- package/dist/src/server/subscription-manager-worker-protocol.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-worker-protocol.js +0 -20
- package/dist/src/server/subscription-manager-worker-protocol.js.map +0 -1
- package/dist/src/server/subscription-manager.d.ts +0 -32
- package/dist/src/server/subscription-manager.d.ts.map +0 -1
- package/dist/src/server/subscription-manager.js +0 -249
- package/dist/src/server/subscription-manager.js.map +0 -1
- package/dist/src/server/subscription-manager.test.d.ts +0 -2
- package/dist/src/server/subscription-manager.test.d.ts.map +0 -1
- package/dist/src/server/subscription-manager.test.js +0 -610
- package/dist/src/server/subscription-manager.test.js.map +0 -1
- package/dist/src/server/subscription-worker.d.ts +0 -32
- package/dist/src/server/subscription-worker.d.ts.map +0 -1
- package/dist/src/server/subscription-worker.js +0 -190
- package/dist/src/server/subscription-worker.js.map +0 -1
- package/dist/src/server/supalive-server.d.ts +0 -158
- package/dist/src/server/supalive-server.d.ts.map +0 -1
- package/dist/src/server/supalive-server.js +0 -1048
- package/dist/src/server/supalive-server.js.map +0 -1
- package/dist/src/server/types_server.d.ts +0 -96
- package/dist/src/server/types_server.d.ts.map +0 -1
- package/dist/src/server/types_server.js +0 -36
- package/dist/src/server/types_server.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1,3 +1,369 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { An as RegisterSubscriptionParams, Bn as UpdateSubscriptionReadSetResult, Dn as InvalidateWritesetParams, E as Context, En as AffectedSubscription, Fn as UnregisterSubscriptionResult, In as UnregisterSubscriptionsParams, Ln as UnregisterSubscriptionsResult, Mn as RegisterSubscriptionResult, Nn as UnregisterSubscriptionParams, On as InvalidateWritesetParamsSchema, Pn as UnregisterSubscriptionParamsSchema, Rn as UpdateSubscriptionReadSetParams, Tn as CacheLayer, jn as RegisterSubscriptionParamsSchema, kn as InvalidateWritesetResult, nt as Router, wt as SupaliveDb, zn as UpdateSubscriptionReadSetParamsSchema } from "../../index-CTyXKcq_.js";
|
|
2
|
+
import { t as MySqlDatabase } from "../../mysql-C8SN443m.js";
|
|
3
|
+
import { t as PgDatabase } from "../../postgres-D_gwCHx-.js";
|
|
4
|
+
import { _ as UpstashConfig, f as DatabaseConfig, g as SupaliveServerConfig, h as SubscriptionManagerConfig, u as SubId } from "../../types_server-Ch56y8L3.js";
|
|
5
|
+
import pino, { Level } from "pino";
|
|
6
|
+
import Redis$1 from "ioredis";
|
|
7
|
+
|
|
8
|
+
//#region src/server/supalive-server.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Supalive WebSocket Server
|
|
11
|
+
*/
|
|
12
|
+
declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
13
|
+
private config;
|
|
14
|
+
private instanceId;
|
|
15
|
+
private httpServer;
|
|
16
|
+
private wss;
|
|
17
|
+
private cache;
|
|
18
|
+
private redisSub;
|
|
19
|
+
private db;
|
|
20
|
+
private contextRegistry;
|
|
21
|
+
private router?;
|
|
22
|
+
private sessions;
|
|
23
|
+
private serverSubscriptions;
|
|
24
|
+
private subManagerClient;
|
|
25
|
+
private stats;
|
|
26
|
+
constructor(config: SupaliveServerConfig<TContext>);
|
|
27
|
+
/**
|
|
28
|
+
* Per-session heartbeat. Fires every `HEARTBEAT_INTERVAL_MS` and does
|
|
29
|
+
* both jobs on the same tick:
|
|
30
|
+
*
|
|
31
|
+
* 1. Inactivity check + ws-protocol ping (dead-TCP detection).
|
|
32
|
+
* 2. App-level `{type:"ping"}` if the channel has been idle for at
|
|
33
|
+
* least one heartbeat interval (client-watchdog refresh).
|
|
34
|
+
*
|
|
35
|
+
* The `lastSentAt` gate on (2) preserves the original "only ping when
|
|
36
|
+
* idle" semantics: a session producing sub:updates faster than the
|
|
37
|
+
* heartbeat interval never emits a redundant app-ping.
|
|
38
|
+
*/
|
|
39
|
+
private startSessionHeartbeat;
|
|
40
|
+
private clearSessionTimers;
|
|
41
|
+
registerRouter(router: Router<any, TContext>): void;
|
|
42
|
+
start(): Promise<void>;
|
|
43
|
+
stop(): Promise<void>;
|
|
44
|
+
getStats(): {
|
|
45
|
+
instanceId: string;
|
|
46
|
+
activeConnections: number;
|
|
47
|
+
totalConnections: number;
|
|
48
|
+
activeSubscriptions: number;
|
|
49
|
+
};
|
|
50
|
+
getInstanceId(): string;
|
|
51
|
+
private setupWebSocketHandlers;
|
|
52
|
+
private handleConnection;
|
|
53
|
+
private handleMessage;
|
|
54
|
+
private processMessage;
|
|
55
|
+
private handleAuth;
|
|
56
|
+
/**
|
|
57
|
+
* Park a mutation on this session's FIFO queue and resolve when it
|
|
58
|
+
* eventually drains. The drainer is fire-and-forget: it picks up any
|
|
59
|
+
* newly enqueued op as long as one drain loop is running on this
|
|
60
|
+
* session. Callers (handleCall) own the response/error for their own
|
|
61
|
+
* op via the returned promise.
|
|
62
|
+
*/
|
|
63
|
+
private enqueueMutation;
|
|
64
|
+
/**
|
|
65
|
+
* Drain the per-session mutation queue serially. Only one drain loop
|
|
66
|
+
* runs at a time per session — re-entrant calls bail immediately, the
|
|
67
|
+
* loop already in progress will pick up the new op before exiting.
|
|
68
|
+
*/
|
|
69
|
+
private drainMutationQueue;
|
|
70
|
+
private handleCall;
|
|
71
|
+
private handleSubscribe;
|
|
72
|
+
private handleUnsubscribe;
|
|
73
|
+
private handleDisconnect;
|
|
74
|
+
/**
|
|
75
|
+
* Drives recovery on a sub-manager reconnect. Iterates this app server's
|
|
76
|
+
* `serverSubscriptions`, reads each subId's registration record from
|
|
77
|
+
* Redis (`sl:reg:<subId>`), and re-registers it with the sub-manager.
|
|
78
|
+
*
|
|
79
|
+
* • If the Redis record is missing, another app-server instance fully
|
|
80
|
+
* unregistered the sub during our disconnect. We drop it locally and
|
|
81
|
+
* send `sub:gone` to every session that was holding it.
|
|
82
|
+
* • If the sub-manager reports `recompute: true` (cache-metadata + commit
|
|
83
|
+
* log replay detected staleness), we kick a reexec for that sub.
|
|
84
|
+
*
|
|
85
|
+
* Returns after all subs have been processed. Only then does the
|
|
86
|
+
* SubManagerClient flush its buffered invalidate writeSets.
|
|
87
|
+
*/
|
|
88
|
+
private runSubManagerRecovery;
|
|
89
|
+
private runAffectedHandler;
|
|
90
|
+
/**
|
|
91
|
+
* Removes a subscription from this app server's state and notifies every
|
|
92
|
+
* session that was holding it. Used during recovery when the central
|
|
93
|
+
* registration record is gone, or after a `tracked: false` reply from the
|
|
94
|
+
* sub-manager that we can't reconcile.
|
|
95
|
+
*/
|
|
96
|
+
private dropSubscriptionLocally;
|
|
97
|
+
private handleMutationCommit;
|
|
98
|
+
/**
|
|
99
|
+
* Route an affected sub to whichever instance can actually run the
|
|
100
|
+
* recompute:
|
|
101
|
+
* • If this instance has a local session for the sub, recompute here
|
|
102
|
+
* (fast path) and broadcast the result to every other instance.
|
|
103
|
+
* • Otherwise broadcast a `recompute-race` to every instance in
|
|
104
|
+
* `notifyInstances`. Each receiver tries to acquire a Redis lock
|
|
105
|
+
* keyed by (subId, commitTs); the winner recomputes and publishes
|
|
106
|
+
* an `update` via the normal broadcast path, losers no-op.
|
|
107
|
+
*
|
|
108
|
+
* If `notifyInstances` is empty (the sub has no live holders), we drop
|
|
109
|
+
* the message — the next subscribe will recompute fresh state.
|
|
110
|
+
*/
|
|
111
|
+
private dispatchAffected;
|
|
112
|
+
private hasLocalSessionFor;
|
|
113
|
+
private publishRecomputeRace;
|
|
114
|
+
private reexecuteAffectedQuery;
|
|
115
|
+
private executeLiveQuery;
|
|
116
|
+
/**
|
|
117
|
+
* Resolve the segmentation key used in the subId/cacheKey hash for a
|
|
118
|
+
* query subscription. Priority:
|
|
119
|
+
*
|
|
120
|
+
* 1. Procedure-level `queryIdentity` override:
|
|
121
|
+
* - `false` → identity = `ANONYMOUS_IDENTITY` (cache shared across users)
|
|
122
|
+
* - `string` → that literal
|
|
123
|
+
* - `function` → ctx + input → string | null | undefined
|
|
124
|
+
* 2. `config.getUserId(serverCtx)` → falls back to ANONYMOUS_IDENTITY if it
|
|
125
|
+
* returns null/undefined or isn't configured.
|
|
126
|
+
*/
|
|
127
|
+
private resolveQueryIdentity;
|
|
128
|
+
private sendMessage;
|
|
129
|
+
private sendMessageRaw;
|
|
130
|
+
private sendError;
|
|
131
|
+
private subscribeToInstanceChannel;
|
|
132
|
+
/**
|
|
133
|
+
* React to a `schema:reload` broadcast: invalidate the in-memory column
|
|
134
|
+
* type cache for the named tables (or all if omitted) and re-bootstrap
|
|
135
|
+
* from Postgres so subsequent batched writes see the fresh types. Skips
|
|
136
|
+
* messages published by this instance (we already have the new types).
|
|
137
|
+
*/
|
|
138
|
+
private handleSchemaReload;
|
|
139
|
+
/**
|
|
140
|
+
* Broadcast a schema-reload signal to every server instance (including
|
|
141
|
+
* this one — the handler skips self-originated messages, so calling
|
|
142
|
+
* after a local migration is safe). Pass `tables` to scope the reload;
|
|
143
|
+
* omit to flush everyone's cache.
|
|
144
|
+
*/
|
|
145
|
+
publishSchemaReload(tables?: string[]): Promise<void>;
|
|
146
|
+
private handleRemoteInstanceMessage;
|
|
147
|
+
private handleRemoteRecomputeRace;
|
|
148
|
+
private publishSubscriptionUpdate;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/logger.d.ts
|
|
152
|
+
declare const appInstanceId: string;
|
|
153
|
+
declare const isProduction: boolean;
|
|
154
|
+
declare const logger: pino.Logger<never, boolean>;
|
|
155
|
+
declare function logLevelOf(name: string): Level;
|
|
156
|
+
declare function serializeMapValue<K extends string | number | symbol, V>(map: Map<K, V>): Record<K, V>;
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region src/server/subscription-manager.d.ts
|
|
159
|
+
/**
|
|
160
|
+
* One process per deployment. Routes each subscription operation to one of N
|
|
161
|
+
* worker threads by hashing subId. Worker threads run in parallel on separate
|
|
162
|
+
* CPU cores; this dispatcher does no Zod parsing — it reads `subId` directly
|
|
163
|
+
* from the decoded payload (the internal channel is trusted) and forwards the
|
|
164
|
+
* raw payload. The worker validates and parses with Zod before executing.
|
|
165
|
+
*/
|
|
166
|
+
declare class SubscriptionManager {
|
|
167
|
+
private wss;
|
|
168
|
+
private port;
|
|
169
|
+
private workers;
|
|
170
|
+
private pruneInterval;
|
|
171
|
+
private static readonly PRUNE_INTERVAL_MS;
|
|
172
|
+
constructor(config: SubscriptionManagerConfig);
|
|
173
|
+
start(): Promise<void>;
|
|
174
|
+
stop(): Promise<void>;
|
|
175
|
+
private pruneCommitLogs;
|
|
176
|
+
workerCount(): number;
|
|
177
|
+
workerIndexFor(subId: string): number;
|
|
178
|
+
private workerFor;
|
|
179
|
+
private registerMethods;
|
|
180
|
+
private readSubId;
|
|
181
|
+
private registerSubscription;
|
|
182
|
+
private registerSubscriptionBatch;
|
|
183
|
+
private updateSubscriptionReadSet;
|
|
184
|
+
private unregisterSubscription;
|
|
185
|
+
private unregisterSubscriptions;
|
|
186
|
+
private invalidateWriteset;
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/server/subscription-manager-client.d.ts
|
|
190
|
+
/**
|
|
191
|
+
* Callback the app server registers to process invalidations that were
|
|
192
|
+
* deferred during a sub-manager outage. When the sub-manager reconnects and
|
|
193
|
+
* the buffered writeSets are flushed in one batched RPC, the resulting
|
|
194
|
+
* `affected[]` is handed to this callback — which is expected to do the
|
|
195
|
+
* same work as the normal per-mutation `reexecuteAffectedQuery` path.
|
|
196
|
+
*/
|
|
197
|
+
type AffectedHandler = (affected: AffectedSubscription[]) => Promise<void>;
|
|
198
|
+
/**
|
|
199
|
+
* Callback the app server registers to drive recovery on sub-manager
|
|
200
|
+
* reconnect. Iterates `serverSubscriptions`, reads `sl:reg:<subId>` from
|
|
201
|
+
* Redis, and re-registers each known sub. Resolves when complete; only then
|
|
202
|
+
* does the client's buffer flush and gated calls release.
|
|
203
|
+
*/
|
|
204
|
+
type RecoveryDriver = () => Promise<void>;
|
|
205
|
+
interface SubManagerClientOptions {
|
|
206
|
+
url: string;
|
|
207
|
+
/**
|
|
208
|
+
* Maximum number of buffered WriteEntry records held during an outage.
|
|
209
|
+
* If exceeded, the buffer is dropped — the commit-log replay path during
|
|
210
|
+
* the next register call will catch up any missed invalidations, at the
|
|
211
|
+
* cost of a brief recompute spike. Default 50_000 entries.
|
|
212
|
+
*/
|
|
213
|
+
invalidateBufferLimit?: number;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* RPC client for the (single) sub-manager process.
|
|
217
|
+
*
|
|
218
|
+
* Design (Convex-inspired):
|
|
219
|
+
* • The sub-manager is in-memory and ephemeral. There is no version
|
|
220
|
+
* protocol, no client-side registration registry, no OUT_OF_SYNC
|
|
221
|
+
* replay logic. All recovery is driven from the app server using
|
|
222
|
+
* state it already has (`serverSubscriptions`) plus registration
|
|
223
|
+
* records persisted to Redis at `sl:reg:<subId>`.
|
|
224
|
+
*
|
|
225
|
+
* • Out-of-order `updateSubscriptionReadSet` calls are filtered server
|
|
226
|
+
* side using `lastSnapshotTs` (monotonic DB commit timestamp).
|
|
227
|
+
*
|
|
228
|
+
* • On rpc-websockets reconnect, the client:
|
|
229
|
+
* 1. Transitions to `busy` (any in-flight `invalidateWriteset`
|
|
230
|
+
* buffers its writeSet).
|
|
231
|
+
* 2. Invokes the app server's `recoveryDriver` to re-register all
|
|
232
|
+
* known subs.
|
|
233
|
+
* 3. Flushes the buffer as one batched `invalidateWriteset` RPC and
|
|
234
|
+
* hands the resulting `affected[]` to `affectedHandler`.
|
|
235
|
+
* 4. Transitions to `ready`.
|
|
236
|
+
*
|
|
237
|
+
* • During an extended outage, the buffer is bounded; if exceeded, it
|
|
238
|
+
* is dropped and we rely on the commit-log replay built into
|
|
239
|
+
* `SubscriptionWorker.register()` to catch each sub up on the next
|
|
240
|
+
* re-register.
|
|
241
|
+
*/
|
|
242
|
+
declare class SubManagerClient {
|
|
243
|
+
private client;
|
|
244
|
+
private state;
|
|
245
|
+
private hasConnectedOnce;
|
|
246
|
+
/** Resolves whenever state transitions to 'ready'. Replaced on each busy→ready cycle. */
|
|
247
|
+
private readyPromise;
|
|
248
|
+
private resolveReady;
|
|
249
|
+
/** Writeset entries accumulated while state === 'busy'. Flushed as one RPC after recovery. */
|
|
250
|
+
private bufferedWriteSets;
|
|
251
|
+
private readonly bufferLimit;
|
|
252
|
+
private bufferDroppedDuringOutage;
|
|
253
|
+
private recoveryDriver?;
|
|
254
|
+
private affectedHandler?;
|
|
255
|
+
constructor(urlOrOptions: string | SubManagerClientOptions);
|
|
256
|
+
/**
|
|
257
|
+
* Wire up the app-server-driven recovery. Must be called before any
|
|
258
|
+
* disconnect/reconnect cycle for buffered writeSets to be flushed and
|
|
259
|
+
* subscriptions re-registered.
|
|
260
|
+
*/
|
|
261
|
+
setRecoveryDriver(driver: RecoveryDriver): void;
|
|
262
|
+
/**
|
|
263
|
+
* Wire up the handler invoked when batched invalidate results land
|
|
264
|
+
* after recovery. The handler is expected to drive
|
|
265
|
+
* `reexecuteAffectedQuery` for each entry.
|
|
266
|
+
*/
|
|
267
|
+
setAffectedHandler(handler: AffectedHandler): void;
|
|
268
|
+
registerSubscription(params: RegisterSubscriptionParams): Promise<RegisterSubscriptionResult>;
|
|
269
|
+
registerSubscriptionBatch(params: RegisterSubscriptionParams[]): Promise<RegisterSubscriptionResult[]>;
|
|
270
|
+
updateSubscriptionReadSet(params: UpdateSubscriptionReadSetParams): Promise<UpdateSubscriptionReadSetResult>;
|
|
271
|
+
unregisterSubscription(params: UnregisterSubscriptionParams): Promise<UnregisterSubscriptionResult>;
|
|
272
|
+
unregisterSubscriptions(params: UnregisterSubscriptionsParams): Promise<UnregisterSubscriptionsResult>;
|
|
273
|
+
/**
|
|
274
|
+
* Sends the writeSet to the sub-manager for invalidation, OR buffers it
|
|
275
|
+
* if the client is currently disconnected / recovering. Returns
|
|
276
|
+
* `{ affected: [] }` while buffering — the actual `affected` from the
|
|
277
|
+
* buffered batch is delivered via the registered `affectedHandler`
|
|
278
|
+
* after recovery completes.
|
|
279
|
+
*/
|
|
280
|
+
invalidateWriteset(params: InvalidateWritesetParams): Promise<InvalidateWritesetResult>;
|
|
281
|
+
/**
|
|
282
|
+
* Single point through which RPCs go. Throws on transport / server error.
|
|
283
|
+
* `registerSubscription`, `updateSubscriptionReadSet`, and
|
|
284
|
+
* `unregisterSubscription` are NOT gated on the ready state: during a
|
|
285
|
+
* disconnect they will fail at the socket layer, and during recovery
|
|
286
|
+
* (which itself uses these methods) gating would deadlock.
|
|
287
|
+
*/
|
|
288
|
+
private call;
|
|
289
|
+
private appendToBuffer;
|
|
290
|
+
private flushBuffer;
|
|
291
|
+
private markBusy;
|
|
292
|
+
private markReady;
|
|
293
|
+
private handleClose;
|
|
294
|
+
private handleOpen;
|
|
295
|
+
private runRecovery;
|
|
296
|
+
/**
|
|
297
|
+
* Test/inspection helpers.
|
|
298
|
+
*/
|
|
299
|
+
/** @internal */
|
|
300
|
+
isReady(): boolean;
|
|
301
|
+
/** @internal */
|
|
302
|
+
bufferSize(): number;
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/db/init_db.d.ts
|
|
306
|
+
/**
|
|
307
|
+
* Default and env override for the per-statement DB timeout. PG enforces
|
|
308
|
+
* this via `statement_timeout` (server cancels), MySQL via the per-query
|
|
309
|
+
* `timeout` option (driver issues KILL QUERY). Set 0 to disable.
|
|
310
|
+
*/
|
|
311
|
+
declare const DB_QUERY_TIMEOUT_MS: number;
|
|
312
|
+
type InitDbOptions = {
|
|
313
|
+
DbConfig: DatabaseConfig;
|
|
314
|
+
CacheLayer: CacheLayer;
|
|
315
|
+
forceBootstrapReload?: boolean;
|
|
316
|
+
workerId?: number;
|
|
317
|
+
};
|
|
318
|
+
declare function initDatabase(options: InitDbOptions): Promise<SupaliveDb>;
|
|
319
|
+
declare function createDatabase(config: DatabaseConfig, workerId?: number): PgDatabase | MySqlDatabase;
|
|
320
|
+
/**
|
|
321
|
+
* Eagerly load column types into the apply-path cache at server start.
|
|
322
|
+
* In production, the result is cached in Redis under
|
|
323
|
+
* `supalive:schema:types:${SUPALIVE_SCHEMA_VERSION ?? "v1"}` so other
|
|
324
|
+
* instances starting cold can skip the pg_attribute round-trip. In any
|
|
325
|
+
* other env we go straight to PG every time so local schema iteration
|
|
326
|
+
* is never blocked by stale Redis state. Migrations should publish a
|
|
327
|
+
* `schema:reload` message (see {@link publishSchemaReload}) after
|
|
328
|
+
* applying DDL — every instance picks that up and re-bootstraps.
|
|
329
|
+
*/
|
|
330
|
+
declare function bootstrapDbTypes(db: SupaliveDb, cache: CacheLayer, forceReload?: boolean): Promise<void>;
|
|
331
|
+
type InitCacheLayerOptions = {
|
|
332
|
+
upstash: UpstashConfig;
|
|
333
|
+
cacheTtlSeconds?: number;
|
|
334
|
+
connectionTimeout?: number;
|
|
335
|
+
commandMaxRetries?: number;
|
|
336
|
+
commandSubMaxRetries?: number;
|
|
337
|
+
createSubClient?: boolean;
|
|
338
|
+
};
|
|
339
|
+
declare function initCacheLayer(config: InitCacheLayerOptions): {
|
|
340
|
+
cacheLayer: CacheLayer;
|
|
341
|
+
redisSubClient?: Redis$1;
|
|
342
|
+
};
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/server/sub_hash.d.ts
|
|
345
|
+
/** Compute stable hash using json-stable-stringify and SHA1. */
|
|
346
|
+
declare function getHashOf(input: unknown): Promise<string>;
|
|
347
|
+
/**
|
|
348
|
+
* Default identity literal used when neither a procedure-level
|
|
349
|
+
* `queryIdentity` override nor a per-session user is available.
|
|
350
|
+
*/
|
|
351
|
+
declare const ANONYMOUS_IDENTITY = "anonymous";
|
|
352
|
+
/**
|
|
353
|
+
* Compute a subscription id from hash of procedure + input + queryIdentity.
|
|
354
|
+
*
|
|
355
|
+
* `queryIdentity` is the segmentation key for cache/subscriptions. By default
|
|
356
|
+
* it is the authenticated user's id (so two users get distinct subscriptions
|
|
357
|
+
* for the same query), but a procedure may override it to share cache/subs
|
|
358
|
+
* across users (e.g. for a public, user-independent query).
|
|
359
|
+
*/
|
|
360
|
+
declare function generateSubscriptionId(procedure: string, input: unknown | string, queryIdentity: string): Promise<string>;
|
|
361
|
+
/**
|
|
362
|
+
* Compute cache key from query name + args + queryIdentity. The identity
|
|
363
|
+
* participates so that user-specific results don't poison each other's
|
|
364
|
+
* cache when a procedure does authorize per-user.
|
|
365
|
+
*/
|
|
366
|
+
declare function generateCacheKey(queryName: string, input: unknown | string, queryIdentity: string): Promise<string>;
|
|
367
|
+
//#endregion
|
|
368
|
+
export { ANONYMOUS_IDENTITY, type AffectedSubscription, CacheLayer, DB_QUERY_TIMEOUT_MS, InitCacheLayerOptions, InitDbOptions, type InvalidateWritesetParams, InvalidateWritesetParamsSchema, type InvalidateWritesetResult, type RegisterSubscriptionParams, RegisterSubscriptionParamsSchema, type RegisterSubscriptionResult, type SubId, SubManagerClient, SubscriptionManager, SupaliveWebSocketServer, type UnregisterSubscriptionParams, UnregisterSubscriptionParamsSchema, type UnregisterSubscriptionResult, type UpdateSubscriptionReadSetParams, UpdateSubscriptionReadSetParamsSchema, type UpdateSubscriptionReadSetResult, appInstanceId, bootstrapDbTypes, createDatabase, generateCacheKey, generateSubscriptionId, getHashOf, initCacheLayer, initDatabase, isProduction, logLevelOf, logger, serializeMapValue };
|
|
3
369
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","
|
|
1
|
+
{"version":3,"file":"server.d.ts","names":[],"sources":["../../../src/server/supalive-server.ts","../../../src/logger.ts","../../../src/server/subscription-manager.ts","../../../src/server/subscription-manager-client.ts","../../../src/db/init_db.ts","../../../src/server/sub_hash.ts"],"mappings":"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"}
|