@syncular/server 0.0.1-98 → 0.0.2-126
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 +25 -0
- package/dist/blobs/adapters/filesystem.d.ts +31 -0
- package/dist/blobs/adapters/filesystem.d.ts.map +1 -0
- package/dist/blobs/adapters/filesystem.js +140 -0
- package/dist/blobs/adapters/filesystem.js.map +1 -0
- package/dist/blobs/adapters/s3.d.ts +3 -2
- package/dist/blobs/adapters/s3.d.ts.map +1 -1
- package/dist/blobs/adapters/s3.js +49 -0
- package/dist/blobs/adapters/s3.js.map +1 -1
- package/dist/blobs/index.d.ts +1 -0
- package/dist/blobs/index.d.ts.map +1 -1
- package/dist/blobs/index.js +1 -0
- package/dist/blobs/index.js.map +1 -1
- package/dist/compaction.d.ts +1 -1
- package/dist/compaction.js +1 -1
- package/dist/{shapes → handlers}/create-handler.d.ts +18 -5
- package/dist/handlers/create-handler.d.ts.map +1 -0
- package/dist/{shapes → handlers}/create-handler.js +54 -17
- package/dist/handlers/create-handler.js.map +1 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/registry.d.ts.map +1 -0
- package/dist/handlers/registry.js.map +1 -0
- package/dist/{shapes → handlers}/types.d.ts +7 -7
- package/dist/{shapes → handlers}/types.d.ts.map +1 -1
- package/dist/{shapes → handlers}/types.js.map +1 -1
- package/dist/helpers/conflict.d.ts +1 -1
- package/dist/helpers/conflict.d.ts.map +1 -1
- package/dist/helpers/emitted-change.d.ts +1 -1
- package/dist/helpers/emitted-change.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/notify.d.ts +47 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +85 -0
- package/dist/notify.js.map +1 -0
- package/dist/proxy/handler.d.ts +1 -1
- package/dist/proxy/handler.d.ts.map +1 -1
- package/dist/proxy/handler.js +7 -7
- package/dist/proxy/handler.js.map +1 -1
- package/dist/proxy/oplog.d.ts +1 -1
- package/dist/proxy/oplog.d.ts.map +1 -1
- package/dist/proxy/oplog.js +6 -6
- package/dist/proxy/oplog.js.map +1 -1
- package/dist/pull.d.ts +2 -2
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js +48 -9
- package/dist/pull.js.map +1 -1
- package/dist/push.d.ts +2 -2
- package/dist/push.d.ts.map +1 -1
- package/dist/push.js +1 -1
- package/dist/push.js.map +1 -1
- package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
- package/dist/snapshot-chunks/db-metadata.js +14 -3
- package/dist/snapshot-chunks/db-metadata.js.map +1 -1
- package/dist/snapshot-chunks/index.d.ts +0 -1
- package/dist/snapshot-chunks/index.d.ts.map +1 -1
- package/dist/snapshot-chunks/index.js +0 -1
- package/dist/snapshot-chunks/index.js.map +1 -1
- package/dist/subscriptions/resolve.d.ts +6 -6
- package/dist/subscriptions/resolve.d.ts.map +1 -1
- package/dist/subscriptions/resolve.js +53 -14
- package/dist/subscriptions/resolve.js.map +1 -1
- package/package.json +2 -2
- package/src/blobs/adapters/filesystem.test.ts +132 -0
- package/src/blobs/adapters/filesystem.ts +189 -0
- package/src/blobs/adapters/s3.test.ts +522 -0
- package/src/blobs/adapters/s3.ts +55 -2
- package/src/blobs/index.ts +1 -0
- package/src/compaction.ts +1 -1
- package/src/{shapes → handlers}/create-handler.ts +111 -21
- package/src/{shapes → handlers}/types.ts +10 -7
- package/src/helpers/conflict.ts +1 -1
- package/src/helpers/emitted-change.ts +1 -1
- package/src/index.ts +2 -1
- package/src/notify.test.ts +516 -0
- package/src/notify.ts +131 -0
- package/src/proxy/handler.test.ts +3 -3
- package/src/proxy/handler.ts +8 -8
- package/src/proxy/oplog.ts +7 -7
- package/src/pull.ts +66 -12
- package/src/push.ts +3 -3
- package/src/snapshot-chunks/db-metadata.test.ts +69 -0
- package/src/snapshot-chunks/db-metadata.ts +14 -3
- package/src/snapshot-chunks/index.ts +0 -1
- package/src/subscriptions/resolve.ts +73 -18
- package/dist/shapes/create-handler.d.ts.map +0 -1
- package/dist/shapes/create-handler.js.map +0 -1
- package/dist/shapes/index.d.ts.map +0 -1
- package/dist/shapes/index.js.map +0 -1
- package/dist/shapes/registry.d.ts.map +0 -1
- package/dist/shapes/registry.js.map +0 -1
- package/dist/snapshot-chunks/adapters/s3.d.ts +0 -74
- package/dist/snapshot-chunks/adapters/s3.d.ts.map +0 -1
- package/dist/snapshot-chunks/adapters/s3.js +0 -50
- package/dist/snapshot-chunks/adapters/s3.js.map +0 -1
- package/src/snapshot-chunks/adapters/s3.ts +0 -68
- /package/dist/{shapes → handlers}/index.d.ts +0 -0
- /package/dist/{shapes → handlers}/index.js +0 -0
- /package/dist/{shapes → handlers}/registry.d.ts +0 -0
- /package/dist/{shapes → handlers}/registry.js +0 -0
- /package/dist/{shapes → handlers}/types.js +0 -0
- /package/src/{shapes → handlers}/index.ts +0 -0
- /package/src/{shapes → handlers}/registry.ts +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ScopePattern, ScopeValues, StoredScopes, SyncOp, SyncOperation, SyncOperationResult } from '@syncular/core';
|
|
1
|
+
import type { ScopePattern, ScopeValues, ScopeValuesForKeys, StoredScopes, SyncOp, SyncOperation, SyncOperationResult } from '@syncular/core';
|
|
2
2
|
import type { ZodSchema, z } from 'zod';
|
|
3
3
|
import type { DbExecutor } from '../dialect/types';
|
|
4
4
|
import type { SyncCoreDb } from '../schema';
|
|
@@ -39,11 +39,11 @@ export interface ServerContext<DB extends SyncCoreDb = SyncCoreDb> {
|
|
|
39
39
|
/**
|
|
40
40
|
* Context passed to snapshot method.
|
|
41
41
|
*/
|
|
42
|
-
export interface ServerSnapshotContext<DB extends SyncCoreDb = SyncCoreDb> extends ServerContext<DB> {
|
|
42
|
+
export interface ServerSnapshotContext<DB extends SyncCoreDb = SyncCoreDb, ScopeKeys extends string = string> extends ServerContext<DB> {
|
|
43
43
|
/** Database executor for the snapshot */
|
|
44
44
|
db: DbExecutor<DB>;
|
|
45
45
|
/** Effective scope values for this subscription */
|
|
46
|
-
scopeValues:
|
|
46
|
+
scopeValues: ScopeValuesForKeys<ScopeKeys>;
|
|
47
47
|
/** Pagination cursor (row_id for keyset pagination) */
|
|
48
48
|
cursor: string | null;
|
|
49
49
|
/** Max rows to return */
|
|
@@ -95,11 +95,11 @@ interface ServerScopeConfig {
|
|
|
95
95
|
toFilter?: (vars: Record<string, string | undefined>, query: unknown) => unknown;
|
|
96
96
|
}
|
|
97
97
|
/**
|
|
98
|
-
* Server
|
|
98
|
+
* Server handler options - configuration for a table's sync behavior.
|
|
99
99
|
*/
|
|
100
|
-
export interface
|
|
100
|
+
export interface ServerHandlerOptions<DB extends SyncCoreDb = SyncCoreDb, Scopes extends Record<ScopePattern, Record<string, string>> = Record<ScopePattern, Record<string, string>>, TableName extends string = string, Params extends ZodSchema = ZodSchema> {
|
|
101
101
|
/**
|
|
102
|
-
* Scope patterns this
|
|
102
|
+
* Scope patterns this handler uses.
|
|
103
103
|
* Array of pattern keys from SharedScopes.
|
|
104
104
|
*/
|
|
105
105
|
scopes: (keyof Scopes)[];
|
|
@@ -170,7 +170,7 @@ export interface ServerShapeOptions<DB extends SyncCoreDb = SyncCoreDb, Scopes e
|
|
|
170
170
|
export interface ServerTableHandler<DB extends SyncCoreDb = SyncCoreDb> {
|
|
171
171
|
/** Table name */
|
|
172
172
|
table: string;
|
|
173
|
-
/** Scope patterns used by this
|
|
173
|
+
/** Scope patterns used by this handler */
|
|
174
174
|
scopePatterns: ScopePattern[];
|
|
175
175
|
/**
|
|
176
176
|
* Tables that must be bootstrapped before this one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":""}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Helper for building conflict results in server table handlers.
|
|
5
5
|
*/
|
|
6
|
-
import type { ApplyOperationResult } from '../
|
|
6
|
+
import type { ApplyOperationResult } from '../handlers/types';
|
|
7
7
|
export interface BuildConflictResultArgs {
|
|
8
8
|
/** Index of the operation in the batch */
|
|
9
9
|
opIndex: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/helpers/conflict.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/helpers/conflict.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,uBAAuB,GAC5B,oBAAoB,CAAC,QAAQ,CAAC,CAQhC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Helper for creating emitted changes in server table handlers.
|
|
5
5
|
*/
|
|
6
6
|
import type { StoredScopes } from '@syncular/core';
|
|
7
|
-
import type { EmittedChange } from '../
|
|
7
|
+
import type { EmittedChange } from '../handlers/types';
|
|
8
8
|
export interface CreateEmittedChangeArgs {
|
|
9
9
|
/** Table name */
|
|
10
10
|
table: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitted-change.d.ts","sourceRoot":"","sources":["../../src/helpers/emitted-change.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"emitted-change.d.ts","sourceRoot":"","sources":["../../src/helpers/emitted-change.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACxB,iCAAiC;IACjC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;OAGG;IACH,MAAM,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,uBAAuB,GAC5B,aAAa,CASf"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,15 +12,16 @@ export * from './blobs';
|
|
|
12
12
|
export * from './clients';
|
|
13
13
|
export * from './compaction';
|
|
14
14
|
export * from './dialect';
|
|
15
|
+
export * from './handlers';
|
|
15
16
|
export * from './helpers';
|
|
16
17
|
export * from './migrate';
|
|
18
|
+
export * from './notify';
|
|
17
19
|
export * from './proxy';
|
|
18
20
|
export * from './prune';
|
|
19
21
|
export * from './pull';
|
|
20
22
|
export * from './push';
|
|
21
23
|
export * from './realtime';
|
|
22
24
|
export * from './schema';
|
|
23
|
-
export * from './shapes';
|
|
24
25
|
export * from './snapshot-chunks';
|
|
25
26
|
export type { SnapshotChunkStorage } from './snapshot-chunks/types';
|
|
26
27
|
export * from './stats';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,15 +12,16 @@ export * from './blobs/index.js';
|
|
|
12
12
|
export * from './clients.js';
|
|
13
13
|
export * from './compaction.js';
|
|
14
14
|
export * from './dialect/index.js';
|
|
15
|
+
export * from './handlers/index.js';
|
|
15
16
|
export * from './helpers/index.js';
|
|
16
17
|
export * from './migrate.js';
|
|
18
|
+
export * from './notify.js';
|
|
17
19
|
export * from './proxy/index.js';
|
|
18
20
|
export * from './prune.js';
|
|
19
21
|
export * from './pull.js';
|
|
20
22
|
export * from './push.js';
|
|
21
23
|
export * from './realtime/index.js';
|
|
22
24
|
export * from './schema.js';
|
|
23
|
-
export * from './shapes/index.js';
|
|
24
25
|
export * from './snapshot-chunks.js';
|
|
25
26
|
export * from './stats.js';
|
|
26
27
|
export * from './subscriptions/index.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAElC,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
|
package/dist/notify.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - External data change notification
|
|
3
|
+
*
|
|
4
|
+
* Creates synthetic commits to notify the sync framework about data changes
|
|
5
|
+
* made outside the normal push flow (e.g., pipeline imports, direct DB writes).
|
|
6
|
+
*
|
|
7
|
+
* The synthetic commit forces affected subscriptions to re-bootstrap on next pull,
|
|
8
|
+
* ensuring clients receive the updated data.
|
|
9
|
+
*/
|
|
10
|
+
import type { Kysely } from 'kysely';
|
|
11
|
+
import type { ServerSyncDialect } from './dialect/types';
|
|
12
|
+
import type { SyncCoreDb } from './schema';
|
|
13
|
+
/**
|
|
14
|
+
* Well-known client_id for external/synthetic commits.
|
|
15
|
+
* Used by the pull handler to detect external data changes.
|
|
16
|
+
*/
|
|
17
|
+
export declare const EXTERNAL_CLIENT_ID = "__external__";
|
|
18
|
+
export interface NotifyExternalDataChangeArgs<DB extends SyncCoreDb> {
|
|
19
|
+
db: Kysely<DB>;
|
|
20
|
+
dialect: ServerSyncDialect;
|
|
21
|
+
/** Table names that were externally modified. */
|
|
22
|
+
tables: string[];
|
|
23
|
+
/** Partition key. Defaults to 'default'. */
|
|
24
|
+
partitionId?: string;
|
|
25
|
+
/** Actor identifier for the synthetic commit. Defaults to '__external__'. */
|
|
26
|
+
actorId?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface NotifyExternalDataChangeResult {
|
|
29
|
+
/** The commit_seq of the synthetic commit. */
|
|
30
|
+
commitSeq: number;
|
|
31
|
+
/** Tables that were notified. */
|
|
32
|
+
tables: string[];
|
|
33
|
+
/** Number of snapshot chunks deleted. */
|
|
34
|
+
deletedChunks: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Notify the sync framework about external data changes.
|
|
38
|
+
*
|
|
39
|
+
* Inserts a synthetic commit (client_id = '__external__'), clears cached
|
|
40
|
+
* snapshot chunks for the affected tables, and inserts sync_table_commits
|
|
41
|
+
* entries so the pull handler can detect the change.
|
|
42
|
+
*
|
|
43
|
+
* On next pull, subscriptions for affected tables will trigger a re-bootstrap
|
|
44
|
+
* instead of an incremental pull.
|
|
45
|
+
*/
|
|
46
|
+
export declare function notifyExternalDataChange<DB extends SyncCoreDb>(args: NotifyExternalDataChangeArgs<DB>): Promise<NotifyExternalDataChangeResult>;
|
|
47
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,MAAM,WAAW,4BAA4B,CAAC,EAAE,SAAS,UAAU;IACjE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,EAAE,iBAAiB,CAAC;IAC3B,iDAAiD;IACjD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAAC,EAAE,SAAS,UAAU,EAClE,IAAI,EAAE,4BAA4B,CAAC,EAAE,CAAC,GACrC,OAAO,CAAC,8BAA8B,CAAC,CA6EzC"}
|
package/dist/notify.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @syncular/server - External data change notification
|
|
3
|
+
*
|
|
4
|
+
* Creates synthetic commits to notify the sync framework about data changes
|
|
5
|
+
* made outside the normal push flow (e.g., pipeline imports, direct DB writes).
|
|
6
|
+
*
|
|
7
|
+
* The synthetic commit forces affected subscriptions to re-bootstrap on next pull,
|
|
8
|
+
* ensuring clients receive the updated data.
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
/**
|
|
12
|
+
* Well-known client_id for external/synthetic commits.
|
|
13
|
+
* Used by the pull handler to detect external data changes.
|
|
14
|
+
*/
|
|
15
|
+
export const EXTERNAL_CLIENT_ID = '__external__';
|
|
16
|
+
/**
|
|
17
|
+
* Notify the sync framework about external data changes.
|
|
18
|
+
*
|
|
19
|
+
* Inserts a synthetic commit (client_id = '__external__'), clears cached
|
|
20
|
+
* snapshot chunks for the affected tables, and inserts sync_table_commits
|
|
21
|
+
* entries so the pull handler can detect the change.
|
|
22
|
+
*
|
|
23
|
+
* On next pull, subscriptions for affected tables will trigger a re-bootstrap
|
|
24
|
+
* instead of an incremental pull.
|
|
25
|
+
*/
|
|
26
|
+
export async function notifyExternalDataChange(args) {
|
|
27
|
+
const { db, dialect, tables } = args;
|
|
28
|
+
const partitionId = args.partitionId ?? 'default';
|
|
29
|
+
const actorId = args.actorId ?? EXTERNAL_CLIENT_ID;
|
|
30
|
+
if (tables.length === 0) {
|
|
31
|
+
throw new Error('notifyExternalDataChange: tables must not be empty');
|
|
32
|
+
}
|
|
33
|
+
return dialect.executeInTransaction(db, async (trx) => {
|
|
34
|
+
const syncTrx = trx;
|
|
35
|
+
const clientCommitId = `ext_${Date.now()}_${randomUUID()}`;
|
|
36
|
+
// 1. Insert synthetic commit
|
|
37
|
+
const commitRow = {
|
|
38
|
+
partition_id: partitionId,
|
|
39
|
+
actor_id: actorId,
|
|
40
|
+
client_id: EXTERNAL_CLIENT_ID,
|
|
41
|
+
client_commit_id: clientCommitId,
|
|
42
|
+
meta: null,
|
|
43
|
+
result_json: { ok: true, status: 'applied' },
|
|
44
|
+
change_count: 0,
|
|
45
|
+
affected_tables: dialect.arrayToDb(tables),
|
|
46
|
+
};
|
|
47
|
+
await syncTrx.insertInto('sync_commits').values(commitRow).execute();
|
|
48
|
+
// Read back the assigned commit_seq
|
|
49
|
+
const inserted = await syncTrx
|
|
50
|
+
.selectFrom('sync_commits')
|
|
51
|
+
.select(['commit_seq'])
|
|
52
|
+
.where('partition_id', '=', partitionId)
|
|
53
|
+
.where('client_id', '=', EXTERNAL_CLIENT_ID)
|
|
54
|
+
.where('client_commit_id', '=', clientCommitId)
|
|
55
|
+
.executeTakeFirstOrThrow();
|
|
56
|
+
const commitSeq = Number(inserted.commit_seq);
|
|
57
|
+
// 2. Insert sync_table_commits entries for each affected table
|
|
58
|
+
const tableCommits = tables.map((table) => ({
|
|
59
|
+
partition_id: partitionId,
|
|
60
|
+
table,
|
|
61
|
+
commit_seq: commitSeq,
|
|
62
|
+
}));
|
|
63
|
+
await syncTrx
|
|
64
|
+
.insertInto('sync_table_commits')
|
|
65
|
+
.values(tableCommits)
|
|
66
|
+
.onConflict((oc) => oc.columns(['partition_id', 'table', 'commit_seq']).doNothing())
|
|
67
|
+
.execute();
|
|
68
|
+
// 3. Delete cached snapshot chunks for affected tables
|
|
69
|
+
let deletedChunks = 0;
|
|
70
|
+
for (const table of tables) {
|
|
71
|
+
const result = await syncTrx
|
|
72
|
+
.deleteFrom('sync_snapshot_chunks')
|
|
73
|
+
.where('partition_id', '=', partitionId)
|
|
74
|
+
.where('scope', '=', table)
|
|
75
|
+
.executeTakeFirst();
|
|
76
|
+
deletedChunks += Number(result?.numDeletedRows ?? 0);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
commitSeq,
|
|
80
|
+
tables,
|
|
81
|
+
deletedChunks,
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy/handler.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface ExecuteProxyQueryArgs<DB extends SyncCoreDb = SyncCoreDb> {
|
|
|
14
14
|
/** Server sync dialect */
|
|
15
15
|
dialect: ServerSyncDialect;
|
|
16
16
|
/** Proxy table registry for oplog generation */
|
|
17
|
-
|
|
17
|
+
handlers: ProxyTableRegistry;
|
|
18
18
|
/** Query context (actor/client IDs) */
|
|
19
19
|
ctx: ProxyQueryContext;
|
|
20
20
|
/** SQL query string */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/proxy/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,qBAAqB,CAAC,EAAE,SAAS,UAAU,GAAG,UAAU;IACvE,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,0BAA0B;IAC1B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gDAAgD;IAChD,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/proxy/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,qBAAqB,CAAC,EAAE,SAAS,UAAU,GAAG,UAAU;IACvE,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,0BAA0B;IAC1B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,uCAAuC;IACvC,GAAG,EAAE,iBAAiB,CAAC;IACvB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,UAAU,EAAE,SAAS,OAAO,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,kDAAkD;IAClD,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAiDD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,SAAS,UAAU,EAC3D,IAAI,EAAE,qBAAqB,CAAC,EAAE,CAAC,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAyDlC"}
|
package/dist/proxy/handler.js
CHANGED
|
@@ -53,17 +53,17 @@ function buildRawQuery(sqlQuery, parameters) {
|
|
|
53
53
|
* - Mutations: Append RETURNING *, execute, create oplog entries
|
|
54
54
|
*/
|
|
55
55
|
export async function executeProxyQuery(args) {
|
|
56
|
-
const { db, dialect,
|
|
56
|
+
const { db, dialect, handlers, ctx, sqlQuery, parameters } = args;
|
|
57
57
|
const mutation = detectMutation(sqlQuery);
|
|
58
58
|
if (!mutation) {
|
|
59
59
|
// Read query - execute directly
|
|
60
60
|
const result = await buildRawQuery(sqlQuery, parameters).execute(db);
|
|
61
61
|
return { rows: result.rows };
|
|
62
62
|
}
|
|
63
|
-
// Check if this table has a registered
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
66
|
-
// No
|
|
63
|
+
// Check if this table has a registered handler
|
|
64
|
+
const handler = handlers.get(mutation.tableName);
|
|
65
|
+
if (!handler) {
|
|
66
|
+
// No handler registered - execute without oplog
|
|
67
67
|
// This allows proxy operations on non-synced tables
|
|
68
68
|
const result = await buildRawQuery(sqlQuery, parameters).execute(db);
|
|
69
69
|
return {
|
|
@@ -71,7 +71,7 @@ export async function executeProxyQuery(args) {
|
|
|
71
71
|
rowCount: Number(result.numAffectedRows ?? 0),
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
// Mutation with registered
|
|
74
|
+
// Mutation with registered handler - append RETURNING * and create oplog
|
|
75
75
|
const hasReturning = hasReturningClause(sqlQuery);
|
|
76
76
|
if (hasReturning && !hasReturningWildcard(sqlQuery)) {
|
|
77
77
|
throw new Error(`Proxy mutation on synced table "${mutation.tableName}" must use RETURNING * (or omit RETURNING)`);
|
|
@@ -89,7 +89,7 @@ export async function executeProxyQuery(args) {
|
|
|
89
89
|
actorId: ctx.actorId,
|
|
90
90
|
clientId: ctx.clientId,
|
|
91
91
|
partitionId: ctx.partitionId,
|
|
92
|
-
|
|
92
|
+
handler,
|
|
93
93
|
operation: mutation.operation,
|
|
94
94
|
rows: affectedRows,
|
|
95
95
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/proxy/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA8B7C;;;;GAIG;AACH,SAAS,aAAa,CACpB,QAAgB,EAChB,UAA8B,EACT;IACrB,qCAAqC;IACrC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,mEAAmE;IACnE,qEAAqE;IACrE,MAAM,KAAK,GAA0B,EAAE,CAAC;IACxC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,UAAU,GAAG,UAAU,CAAC;IAC9B,IAAI,KAA6B,CAAC;IAElC,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACpD,oCAAoC;QACpC,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,iEAAiE;QACjE,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACtD,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;YACtD,qDAAqD;YACrD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,CAAC;IAED,yCAAyC;IACzC,IAAI,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,0BAA0B;IAC1B,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAAA,CACrC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAA+B,EACG;IAClC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/proxy/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy/oplog.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export declare function createOplogEntries<DB extends SyncCoreDb>(args: {
|
|
|
20
20
|
actorId: string;
|
|
21
21
|
clientId: string;
|
|
22
22
|
partitionId?: string;
|
|
23
|
-
|
|
23
|
+
handler: ProxyTableHandler;
|
|
24
24
|
operation: SyncOp;
|
|
25
25
|
rows: Record<string, unknown>[];
|
|
26
26
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oplog.d.ts","sourceRoot":"","sources":["../../src/proxy/oplog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,MAAM,EAAO,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AASjD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,SAAS,UAAU,EAAE,IAAI,EAAE;IACpE,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,
|
|
1
|
+
{"version":3,"file":"oplog.d.ts","sourceRoot":"","sources":["../../src/proxy/oplog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,KAAK,MAAM,EAAO,MAAM,QAAQ,CAAC;AAC1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AASjD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,SAAS,UAAU,EAAE,IAAI,EAAE;IACpE,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CACjC,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA8G3D"}
|
package/dist/proxy/oplog.js
CHANGED
|
@@ -18,13 +18,13 @@ function generateId() {
|
|
|
18
18
|
* making them visible to sync clients.
|
|
19
19
|
*/
|
|
20
20
|
export async function createOplogEntries(args) {
|
|
21
|
-
const { trx, dialect, actorId, clientId,
|
|
21
|
+
const { trx, dialect, actorId, clientId, handler, operation, rows } = args;
|
|
22
22
|
const partitionId = args.partitionId ?? 'default';
|
|
23
23
|
if (rows.length === 0) {
|
|
24
24
|
return { commitSeq: 0, affectedTables: [] };
|
|
25
25
|
}
|
|
26
|
-
const pk =
|
|
27
|
-
const versionCol =
|
|
26
|
+
const pk = handler.primaryKey ?? 'id';
|
|
27
|
+
const versionCol = handler.versionColumn ?? 'server_version';
|
|
28
28
|
// Create commit record
|
|
29
29
|
const commitResult = await sql `
|
|
30
30
|
insert into ${sql.table('sync_commits')} (
|
|
@@ -52,13 +52,13 @@ export async function createOplogEntries(args) {
|
|
|
52
52
|
const commitSeq = Number(commitRow.commit_seq);
|
|
53
53
|
// Compute scopes for all rows and collect changes
|
|
54
54
|
const affectedTablesSet = new Set();
|
|
55
|
-
affectedTablesSet.add(
|
|
55
|
+
affectedTablesSet.add(handler.table);
|
|
56
56
|
const changes = rows.map((row) => {
|
|
57
|
-
const scopes =
|
|
57
|
+
const scopes = handler.computeScopes(row);
|
|
58
58
|
return {
|
|
59
59
|
commit_seq: commitSeq,
|
|
60
60
|
partition_id: partitionId,
|
|
61
|
-
table:
|
|
61
|
+
table: handler.table,
|
|
62
62
|
row_id: String(row[pk]),
|
|
63
63
|
op: operation,
|
|
64
64
|
row_json: operation === 'delete' ? null : row,
|
package/dist/proxy/oplog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oplog.js","sourceRoot":"","sources":["../../src/proxy/oplog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAe,GAAG,EAAE,MAAM,QAAQ,CAAC;AAK1C;;GAEG;AACH,SAAS,UAAU,GAAW;IAC5B,OAAO,UAAU,EAAE,CAAC;AAAA,CACrB;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAwB,IAS/D,EAA4D;IAC3D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"oplog.js","sourceRoot":"","sources":["../../src/proxy/oplog.ts"],"names":[],"mappings":"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"}
|
package/dist/pull.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ScopeValues, type SyncPullRequest, type SyncPullResponse } from '@syncular/core';
|
|
2
2
|
import type { Kysely } from 'kysely';
|
|
3
3
|
import type { ServerSyncDialect } from './dialect/types';
|
|
4
|
+
import type { TableRegistry } from './handlers/registry';
|
|
4
5
|
import type { SyncCoreDb } from './schema';
|
|
5
|
-
import type { TableRegistry } from './shapes/registry';
|
|
6
6
|
import type { SnapshotChunkStorage } from './snapshot-chunks/types';
|
|
7
7
|
export interface PullResult {
|
|
8
8
|
response: SyncPullResponse;
|
|
@@ -17,7 +17,7 @@ export interface PullResult {
|
|
|
17
17
|
export declare function pull<DB extends SyncCoreDb>(args: {
|
|
18
18
|
db: Kysely<DB>;
|
|
19
19
|
dialect: ServerSyncDialect;
|
|
20
|
-
|
|
20
|
+
handlers: TableRegistry<DB>;
|
|
21
21
|
actorId: string;
|
|
22
22
|
partitionId?: string;
|
|
23
23
|
request: SyncPullRequest;
|
package/dist/pull.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../src/pull.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAMhB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAItB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../src/pull.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,WAAW,EAMhB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EAItB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAK3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAiFpE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;;;OAGG;IACH,eAAe,EAAE,WAAW,CAAC;IAC7B,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;CACtB;AAqLD,wBAAsB,IAAI,CAAC,EAAE,SAAS,UAAU,EAAE,IAAI,EAAE;IACtD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,GAAG,OAAO,CAAC,UAAU,CAAC,CAqlBtB"}
|
package/dist/pull.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import { gzip, gzipSync } from 'node:zlib';
|
|
4
4
|
import { captureSyncException, countSyncMetric, distributionSyncMetric, encodeSnapshotRowFrames, encodeSnapshotRows, SYNC_SNAPSHOT_CHUNK_COMPRESSION, SYNC_SNAPSHOT_CHUNK_ENCODING, startSyncSpan, } from '@syncular/core';
|
|
5
|
+
import { EXTERNAL_CLIENT_ID } from './notify.js';
|
|
5
6
|
import { insertSnapshotChunk, readSnapshotChunkRefByPageKey, } from './snapshot-chunks.js';
|
|
6
7
|
import { resolveEffectiveScopesForSubscriptions } from './subscriptions/resolve.js';
|
|
7
8
|
const gzipAsync = promisify(gzip);
|
|
@@ -167,6 +168,25 @@ function recordPullMetrics(args) {
|
|
|
167
168
|
});
|
|
168
169
|
distributionSyncMetric('sync.server.pull.snapshot_pages', stats.snapshotPageCount, { attributes });
|
|
169
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Read synthetic commits created by notifyExternalDataChange() after a given cursor.
|
|
173
|
+
* Returns commit_seq and affected tables for each external change commit.
|
|
174
|
+
*/
|
|
175
|
+
async function readExternalDataChanges(trx, dialect, args) {
|
|
176
|
+
const executor = trx;
|
|
177
|
+
const rows = await executor
|
|
178
|
+
.selectFrom('sync_commits')
|
|
179
|
+
.select(['commit_seq', 'affected_tables'])
|
|
180
|
+
.where('partition_id', '=', args.partitionId)
|
|
181
|
+
.where('client_id', '=', EXTERNAL_CLIENT_ID)
|
|
182
|
+
.where('commit_seq', '>', args.afterCursor)
|
|
183
|
+
.orderBy('commit_seq', 'asc')
|
|
184
|
+
.execute();
|
|
185
|
+
return rows.map((row) => ({
|
|
186
|
+
commitSeq: Number(row.commit_seq),
|
|
187
|
+
tables: dialect.dbToArray(row.affected_tables),
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
170
190
|
export async function pull(args) {
|
|
171
191
|
const { request, dialect } = args;
|
|
172
192
|
const db = args.db;
|
|
@@ -194,7 +214,7 @@ export async function pull(args) {
|
|
|
194
214
|
db,
|
|
195
215
|
actorId: args.actorId,
|
|
196
216
|
subscriptions: request.subscriptions ?? [],
|
|
197
|
-
|
|
217
|
+
handlers: args.handlers,
|
|
198
218
|
});
|
|
199
219
|
const result = await dialect.executeInTransaction(db, async (trx) => {
|
|
200
220
|
await dialect.setRepeatableRead(trx);
|
|
@@ -207,10 +227,28 @@ export async function pull(args) {
|
|
|
207
227
|
const subResponses = [];
|
|
208
228
|
const activeSubscriptions = [];
|
|
209
229
|
const nextCursors = [];
|
|
230
|
+
// Detect external data changes (synthetic commits from notifyExternalDataChange)
|
|
231
|
+
// Compute minimum cursor across all active subscriptions to scope the query.
|
|
232
|
+
let minSubCursor = Number.MAX_SAFE_INTEGER;
|
|
233
|
+
for (const sub of resolved) {
|
|
234
|
+
if (sub.status === 'revoked' ||
|
|
235
|
+
Object.keys(sub.scopes).length === 0)
|
|
236
|
+
continue;
|
|
237
|
+
const cursor = Math.max(-1, sub.cursor ?? -1);
|
|
238
|
+
if (cursor >= 0 && cursor < minSubCursor) {
|
|
239
|
+
minSubCursor = cursor;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const externalDataChanges = minSubCursor < Number.MAX_SAFE_INTEGER && minSubCursor >= 0
|
|
243
|
+
? await readExternalDataChanges(trx, dialect, {
|
|
244
|
+
partitionId,
|
|
245
|
+
afterCursor: minSubCursor,
|
|
246
|
+
})
|
|
247
|
+
: [];
|
|
210
248
|
for (const sub of resolved) {
|
|
211
249
|
const cursor = Math.max(-1, sub.cursor ?? -1);
|
|
212
|
-
// Validate
|
|
213
|
-
args.
|
|
250
|
+
// Validate table handler exists (throws if not registered)
|
|
251
|
+
args.handlers.getOrThrow(sub.table);
|
|
214
252
|
if (sub.status === 'revoked' ||
|
|
215
253
|
Object.keys(sub.scopes).length === 0) {
|
|
216
254
|
subResponses.push({
|
|
@@ -228,10 +266,11 @@ export async function pull(args) {
|
|
|
228
266
|
const needsBootstrap = sub.bootstrapState != null ||
|
|
229
267
|
cursor < 0 ||
|
|
230
268
|
cursor > maxCommitSeq ||
|
|
231
|
-
(minCommitSeq > 0 && cursor < minCommitSeq - 1)
|
|
269
|
+
(minCommitSeq > 0 && cursor < minCommitSeq - 1) ||
|
|
270
|
+
externalDataChanges.some((c) => c.commitSeq > cursor && c.tables.includes(sub.table));
|
|
232
271
|
if (needsBootstrap) {
|
|
233
|
-
const tables = args.
|
|
234
|
-
.getBootstrapOrderFor(sub.
|
|
272
|
+
const tables = args.handlers
|
|
273
|
+
.getBootstrapOrderFor(sub.table)
|
|
235
274
|
.map((handler) => handler.table);
|
|
236
275
|
const initState = {
|
|
237
276
|
asOfCommitSeq: maxCommitSeq,
|
|
@@ -361,7 +400,7 @@ export async function pull(args) {
|
|
|
361
400
|
nextState = null;
|
|
362
401
|
break;
|
|
363
402
|
}
|
|
364
|
-
const tableHandler = args.
|
|
403
|
+
const tableHandler = args.handlers.getOrThrow(nextTableName);
|
|
365
404
|
if (!activeBundle || activeBundle.table !== nextTableName) {
|
|
366
405
|
if (activeBundle) {
|
|
367
406
|
await flushSnapshotBundle(activeBundle);
|
|
@@ -432,7 +471,7 @@ export async function pull(args) {
|
|
|
432
471
|
partitionId,
|
|
433
472
|
cursor,
|
|
434
473
|
limitCommits,
|
|
435
|
-
tables: [sub.
|
|
474
|
+
tables: [sub.table],
|
|
436
475
|
});
|
|
437
476
|
const maxScannedCommitSeq = scannedCommitSeqs.length > 0
|
|
438
477
|
? scannedCommitSeqs[scannedCommitSeqs.length - 1]
|
|
@@ -442,7 +481,7 @@ export async function pull(args) {
|
|
|
442
481
|
let nextCursor = cursor;
|
|
443
482
|
for await (const row of dialect.iterateIncrementalPullRows(trx, {
|
|
444
483
|
partitionId,
|
|
445
|
-
table: sub.
|
|
484
|
+
table: sub.table,
|
|
446
485
|
scopes: effectiveScopes,
|
|
447
486
|
cursor,
|
|
448
487
|
limitCommits,
|