@powersync/service-module-mongodb 0.18.1 → 0.19.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/api/MongoRouteAPIAdapter.d.ts +2 -0
  3. package/dist/api/MongoRouteAPIAdapter.js +23 -32
  4. package/dist/api/MongoRouteAPIAdapter.js.map +1 -1
  5. package/dist/common/SentinelLSN.d.ts +37 -0
  6. package/dist/common/SentinelLSN.js +59 -0
  7. package/dist/common/SentinelLSN.js.map +1 -0
  8. package/dist/replication/ChangeStream.d.ts +15 -0
  9. package/dist/replication/ChangeStream.js +105 -44
  10. package/dist/replication/ChangeStream.js.map +1 -1
  11. package/dist/replication/MongoRelation.d.ts +36 -1
  12. package/dist/replication/MongoRelation.js +102 -6
  13. package/dist/replication/MongoRelation.js.map +1 -1
  14. package/dist/replication/MongoSnapshotter.d.ts +9 -0
  15. package/dist/replication/MongoSnapshotter.js +108 -42
  16. package/dist/replication/MongoSnapshotter.js.map +1 -1
  17. package/dist/replication/RawChangeStream.d.ts +12 -1
  18. package/dist/replication/RawChangeStream.js +30 -7
  19. package/dist/replication/RawChangeStream.js.map +1 -1
  20. package/dist/replication/checkpoints/CheckpointImplementation.d.ts +132 -0
  21. package/dist/replication/checkpoints/CheckpointImplementation.js +22 -0
  22. package/dist/replication/checkpoints/CheckpointImplementation.js.map +1 -0
  23. package/dist/replication/checkpoints/SentinelCheckpointImplementation.d.ts +55 -0
  24. package/dist/replication/checkpoints/SentinelCheckpointImplementation.js +222 -0
  25. package/dist/replication/checkpoints/SentinelCheckpointImplementation.js.map +1 -0
  26. package/dist/replication/checkpoints/TimestampCheckpointImplementation.d.ts +24 -0
  27. package/dist/replication/checkpoints/TimestampCheckpointImplementation.js +113 -0
  28. package/dist/replication/checkpoints/TimestampCheckpointImplementation.js.map +1 -0
  29. package/dist/replication/checkpoints/create-checkpoint-implementation.d.ts +6 -0
  30. package/dist/replication/checkpoints/create-checkpoint-implementation.js +10 -0
  31. package/dist/replication/checkpoints/create-checkpoint-implementation.js.map +1 -0
  32. package/dist/replication/replication-utils.d.ts +6 -0
  33. package/dist/replication/replication-utils.js +19 -2
  34. package/dist/replication/replication-utils.js.map +1 -1
  35. package/package.json +9 -9
  36. package/src/api/MongoRouteAPIAdapter.ts +26 -37
  37. package/src/common/SentinelLSN.ts +78 -0
  38. package/src/replication/ChangeStream.ts +118 -50
  39. package/src/replication/MongoRelation.ts +124 -14
  40. package/src/replication/MongoSnapshotter.ts +122 -47
  41. package/src/replication/RawChangeStream.ts +64 -28
  42. package/src/replication/checkpoints/CheckpointImplementation.ts +167 -0
  43. package/src/replication/checkpoints/SentinelCheckpointImplementation.ts +267 -0
  44. package/src/replication/checkpoints/TimestampCheckpointImplementation.ts +142 -0
  45. package/src/replication/checkpoints/create-checkpoint-implementation.ts +14 -0
  46. package/src/replication/replication-utils.ts +23 -2
  47. package/test/DOCUMENTDB_TESTING.md +115 -0
  48. package/test/src/DatabaseType.ts +25 -0
  49. package/test/src/change_stream.test.ts +103 -68
  50. package/test/src/change_stream_utils.ts +85 -9
  51. package/test/src/checkpoint_retry.test.ts +5 -2
  52. package/test/src/documentdb_helpers.test.ts +124 -0
  53. package/test/src/documentdb_mode.test.ts +1040 -0
  54. package/test/src/mongo_test.test.ts +15 -5
  55. package/test/src/raw_change_stream.test.ts +209 -125
  56. package/test/src/resume_token.test.ts +30 -0
  57. package/test/src/slow_tests.test.ts +4 -1
  58. package/test/src/test-timeouts.ts +23 -0
  59. package/test/src/util.ts +1 -2
  60. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @powersync/service-module-mongodb
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d99c31f: Add experimental Azure DocumentDB (formerly Cosmos DB for MongoDB vCore) support.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [ea71bf3]
12
+ - Updated dependencies [ea31f64]
13
+ - Updated dependencies [edc6ed4]
14
+ - @powersync/service-sync-rules@0.39.0
15
+ - @powersync/service-core@1.23.3
16
+ - @powersync/lib-services-framework@0.9.8
17
+ - @powersync/lib-service-mongodb@0.6.29
18
+
19
+ ## 0.18.2
20
+
21
+ ### Patch Changes
22
+
23
+ - e4f683d: [MongoDB Storage] Add experimental option to allow reading data from secondaries.
24
+ - df9ab1e: Batch concurrent write checkpoint requests and increase request limits to improve throughput.
25
+ - Updated dependencies [71d4a0a]
26
+ - Updated dependencies [e4f683d]
27
+ - Updated dependencies [71d4a0a]
28
+ - Updated dependencies [a6ae678]
29
+ - Updated dependencies [c2edf86]
30
+ - Updated dependencies [df9ab1e]
31
+ - @powersync/service-core@1.23.2
32
+ - @powersync/lib-service-mongodb@0.6.28
33
+ - @powersync/service-sync-rules@0.38.1
34
+ - @powersync/service-types@0.16.1
35
+ - @powersync/lib-services-framework@0.9.7
36
+
3
37
  ## 0.18.1
4
38
 
5
39
  ### Patch Changes
@@ -9,6 +9,7 @@ export declare class MongoRouteAPIAdapter implements api.RouteAPI {
9
9
  db: mongo.Db;
10
10
  connectionTag: string;
11
11
  defaultSchema: string;
12
+ private checkpointImplementation;
12
13
  constructor(config: types.ResolvedConnectionConfig);
13
14
  getParseSyncRulesOptions(): ParseSyncConfigOptions;
14
15
  shutdown(): Promise<void>;
@@ -19,6 +20,7 @@ export declare class MongoRouteAPIAdapter implements api.RouteAPI {
19
20
  getDebugTablesInfo(tablePatterns: sync_rules.TablePattern[], sqlSyncRules: sync_rules.SyncConfig): Promise<api.PatternResult[]>;
20
21
  getReplicationLagBytes(options: api.ReplicationLagOptions): Promise<number | undefined>;
21
22
  createReplicationHead<T>(callback: ReplicationHeadCallback<T>): Promise<T>;
23
+ private getCheckpointImplementation;
22
24
  getConnectionSchema(): Promise<service_types.DatabaseSchema[]>;
23
25
  private getColumnsFromDocuments;
24
26
  private getBsonType;
@@ -2,11 +2,11 @@ import * as lib_mongo from '@powersync/lib-service-mongodb';
2
2
  import { mongo } from '@powersync/lib-service-mongodb';
3
3
  import * as sync_rules from '@powersync/service-sync-rules';
4
4
  import * as service_types from '@powersync/service-types';
5
- import { ServiceAssertionError } from '@powersync/lib-services-framework';
6
- import { MongoLSN } from '../common/MongoLSN.js';
5
+ import { logger } from '@powersync/lib-services-framework';
6
+ import { createCheckpointImplementation } from '../replication/checkpoints/create-checkpoint-implementation.js';
7
7
  import { MongoManager } from '../replication/MongoManager.js';
8
- import { constructAfterRecord, STANDALONE_CHECKPOINT_ID } from '../replication/MongoRelation.js';
9
- import { CHECKPOINTS_COLLECTION } from '../replication/replication-utils.js';
8
+ import { constructAfterRecord } from '../replication/MongoRelation.js';
9
+ import { CHECKPOINTS_COLLECTION, detectDocumentDb } from '../replication/replication-utils.js';
10
10
  import * as types from '../types/types.js';
11
11
  import { escapeRegExp } from '../utils.js';
12
12
  export class MongoRouteAPIAdapter {
@@ -15,6 +15,7 @@ export class MongoRouteAPIAdapter {
15
15
  db;
16
16
  connectionTag;
17
17
  defaultSchema;
18
+ checkpointImplementation = null;
18
19
  constructor(config) {
19
20
  this.config = config;
20
21
  const manager = new MongoManager(config);
@@ -180,36 +181,26 @@ export class MongoRouteAPIAdapter {
180
181
  return undefined;
181
182
  }
182
183
  async createReplicationHead(callback) {
183
- const session = this.client.startSession();
184
- try {
185
- await this.db.command({ hello: 1 }, { session });
186
- const head = session.clusterTime?.clusterTime;
187
- if (head == null) {
188
- throw new ServiceAssertionError(`clusterTime not available for write checkpoint`);
189
- }
190
- const r = await callback(new MongoLSN({ timestamp: head }).comparable);
191
- // Trigger a change on the changestream.
192
- await this.db.collection(CHECKPOINTS_COLLECTION).findOneAndUpdate({
193
- _id: STANDALONE_CHECKPOINT_ID
194
- }, {
195
- $inc: { i: 1 }
196
- }, {
197
- upsert: true,
198
- returnDocument: 'after',
199
- session
184
+ const checkpointImplementation = await this.getCheckpointImplementation();
185
+ return checkpointImplementation.createReplicationHead(callback);
186
+ }
187
+ async getCheckpointImplementation() {
188
+ if (this.checkpointImplementation == null) {
189
+ const isDocumentDb = await detectDocumentDb(this.db);
190
+ this.checkpointImplementation = createCheckpointImplementation(isDocumentDb, {
191
+ client: this.client,
192
+ db: this.db,
193
+ // The adapter never streams, so it has no real barrier document. This
194
+ // random id is only safe because the adapter only ever calls
195
+ // createReplicationHead, which produces a standalone (stream_id = null)
196
+ // head that every real ChangeStream observes. It must NOT be used for a
197
+ // batch barrier (createBatchCheckpoint stamps this id), or the head would
198
+ // become an own-barrier of a phantom stream that nothing resolves.
199
+ checkpointStreamId: new mongo.ObjectId(),
200
+ logger
200
201
  });
201
- const time = session.operationTime;
202
- if (time == null) {
203
- throw new ServiceAssertionError(`operationTime not available for write checkpoint`);
204
- }
205
- else if (time.lt(head)) {
206
- throw new ServiceAssertionError(`operationTime must be > clusterTime`);
207
- }
208
- return r;
209
- }
210
- finally {
211
- await session.endSession();
212
202
  }
203
+ return this.checkpointImplementation;
213
204
  }
214
205
  async getConnectionSchema() {
215
206
  const sampleSize = 50;
@@ -1 +1 @@
1
- {"version":3,"file":"MongoRouteAPIAdapter.js","sourceRoot":"","sources":["../../src/api/MongoRouteAPIAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MongoRouteAPIAdapter.js","sourceRoot":"","sources":["../../src/api/MongoRouteAPIAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { mongo } from '@powersync/lib-service-mongodb';
2
+ export type SentinelLSNSpecification = {
3
+ sentinel: bigint;
4
+ /**
5
+ * Resume tokens are opaque on sentinel-based sources (e.g. DocumentDB). The
6
+ * sentinel component is the comparable position; this token is only used to
7
+ * resume the change stream.
8
+ */
9
+ resume_token?: mongo.ResumeToken | null;
10
+ };
11
+ /**
12
+ * LSN for sentinel-based checkpointing (sources without a usable clusterTime,
13
+ * e.g. DocumentDB). The ordered coordinate is a monotonic sentinel counter; the
14
+ * opaque resume token is carried alongside it only for `resumeAfter`.
15
+ *
16
+ * The coordinate is serialized as a 16-hex-char value with the **same shape as
17
+ * a MongoDB timestamp LSN** ({@link MongoLSN}): the high 32 bits resemble epoch
18
+ * seconds and the low 32 bits an increment. This is deliberate — it makes
19
+ * sentinel LSNs directly string-comparable with timestamp LSNs, so a sentinel
20
+ * coordinate (seeded at the current epoch seconds; see createSentinelCheckpointLsn)
21
+ * always sorts **above** any real-timestamp LSN issued in the past.
22
+ *
23
+ * It only *resembles* a timestamp. The value is a synthetic monotonic counter,
24
+ * not a real cluster time, and must never be used as one (e.g. it is never fed
25
+ * to `startAtOperationTime`; the sentinel implementation resumes purely via the
26
+ * resume token).
27
+ */
28
+ export declare class SentinelLSN {
29
+ protected options: SentinelLSNSpecification;
30
+ static ZERO: SentinelLSN;
31
+ static fromSerialized(comparable: string): SentinelLSN;
32
+ constructor(options: SentinelLSNSpecification);
33
+ get sentinel(): bigint;
34
+ get resumeToken(): unknown;
35
+ get comparable(): string;
36
+ toString(): string;
37
+ }
@@ -0,0 +1,59 @@
1
+ import { storage } from '@powersync/service-core';
2
+ const DELIMINATOR = '|';
3
+ /**
4
+ * Width of the sentinel coordinate, matching a MongoDB cluster timestamp
5
+ * (64-bit → 16 hex chars). The sentinel counter is a 64-bit `Long`, so this is
6
+ * sufficient and never truncates.
7
+ */
8
+ const SENTINEL_HEX_LENGTH = 16;
9
+ /**
10
+ * LSN for sentinel-based checkpointing (sources without a usable clusterTime,
11
+ * e.g. DocumentDB). The ordered coordinate is a monotonic sentinel counter; the
12
+ * opaque resume token is carried alongside it only for `resumeAfter`.
13
+ *
14
+ * The coordinate is serialized as a 16-hex-char value with the **same shape as
15
+ * a MongoDB timestamp LSN** ({@link MongoLSN}): the high 32 bits resemble epoch
16
+ * seconds and the low 32 bits an increment. This is deliberate — it makes
17
+ * sentinel LSNs directly string-comparable with timestamp LSNs, so a sentinel
18
+ * coordinate (seeded at the current epoch seconds; see createSentinelCheckpointLsn)
19
+ * always sorts **above** any real-timestamp LSN issued in the past.
20
+ *
21
+ * It only *resembles* a timestamp. The value is a synthetic monotonic counter,
22
+ * not a real cluster time, and must never be used as one (e.g. it is never fed
23
+ * to `startAtOperationTime`; the sentinel implementation resumes purely via the
24
+ * resume token).
25
+ */
26
+ export class SentinelLSN {
27
+ options;
28
+ static ZERO = new SentinelLSN({ sentinel: 0n });
29
+ static fromSerialized(comparable) {
30
+ const [sentinelString, resumeString] = comparable.split(DELIMINATOR);
31
+ return new SentinelLSN({
32
+ sentinel: BigInt(`0x${sentinelString}`),
33
+ resume_token: resumeString ? storage.deserializeBson(Buffer.from(resumeString, 'base64')).resumeToken : null
34
+ });
35
+ }
36
+ constructor(options) {
37
+ this.options = options;
38
+ }
39
+ get sentinel() {
40
+ return this.options.sentinel;
41
+ }
42
+ get resumeToken() {
43
+ return this.options.resume_token;
44
+ }
45
+ get comparable() {
46
+ // padStart(16) of the combined 64-bit value yields the identical string to
47
+ // MongoLSN's high(8)+low(8) formatting, keeping the two formats comparable.
48
+ const sentinel = this.sentinel.toString(16).padStart(SENTINEL_HEX_LENGTH, '0');
49
+ const segments = [sentinel];
50
+ if (this.resumeToken) {
51
+ segments.push(storage.serializeBson({ resumeToken: this.resumeToken }).toString('base64'));
52
+ }
53
+ return segments.join(DELIMINATOR);
54
+ }
55
+ toString() {
56
+ return this.comparable;
57
+ }
58
+ }
59
+ //# sourceMappingURL=SentinelLSN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SentinelLSN.js","sourceRoot":"","sources":["../../src/common/SentinelLSN.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAYlD,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,WAAW;IAYA;IAXtB,MAAM,CAAC,IAAI,GAAG,IAAI,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IAEhD,MAAM,CAAC,cAAc,CAAC,UAAkB;QACtC,MAAM,CAAC,cAAc,EAAE,YAAY,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAErE,OAAO,IAAI,WAAW,CAAC;YACrB,QAAQ,EAAE,MAAM,CAAC,KAAK,cAAc,EAAE,CAAC;YACvC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;SAC7G,CAAC,CAAC;IACL,CAAC;IAED,YAAsB,OAAiC;QAAjC,YAAO,GAAP,OAAO,CAA0B;IAAG,CAAC;IAE3D,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;IACnC,CAAC;IAED,IAAI,UAAU;QACZ,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE5B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7F,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC"}
@@ -21,6 +21,10 @@ export interface ChangeStreamOptions {
21
21
  * Override snapshotChunkLength for testing.
22
22
  */
23
23
  snapshotChunkLength?: number;
24
+ /**
25
+ * Override keepalive interval for testing (defaults to 60_000ms).
26
+ */
27
+ keepaliveIntervalMs?: number;
24
28
  storageHooks?: storage.StorageHooks;
25
29
  snapshotHooks?: MongoSnapshotterHooks;
26
30
  logger?: Logger;
@@ -61,10 +65,21 @@ export declare class ChangeStream {
61
65
  private changeStreamTimeout;
62
66
  private storageHooks;
63
67
  private readonly sourceRowConverter;
68
+ private keepaliveIntervalMs;
69
+ private isDocumentDb;
70
+ private _checkpointImplementation;
64
71
  constructor(options: ChangeStreamOptions);
65
72
  get stopped(): boolean;
66
73
  private get usePostImages();
67
74
  private get configurePostImages();
75
+ /** The active checkpoint strategy. Only valid after ensureDetected(). */
76
+ private get checkpointImplementation();
77
+ /**
78
+ * Detect DocumentDB and select the checkpoint implementation for the streaming
79
+ * loop. Idempotent. The snapshotter detects independently; the two coordinate
80
+ * through stored LSNs, not shared in-memory state.
81
+ */
82
+ private ensureDetected;
68
83
  private getSourceNamespaceFilters;
69
84
  private getRelations;
70
85
  private getCollectionInfo;
@@ -3,13 +3,13 @@ import { container, DatabaseConnectionError, ErrorCode, ReplicationAbortedError,
3
3
  import { PerformanceTracer, RelationCache, ReplicationLagTracker, SaveOperationTag } from '@powersync/service-core';
4
4
  import { ReplicationMetric } from '@powersync/service-types';
5
5
  import { performance } from 'node:perf_hooks';
6
- import { MongoLSN } from '../common/MongoLSN.js';
7
6
  import { PostImagesOption } from '../types/types.js';
8
7
  import { escapeRegExp } from '../utils.js';
9
- import { createCheckpoint, getCacheIdentifier, getMongoRelation, STANDALONE_CHECKPOINT_ID } from './MongoRelation.js';
8
+ import { createCheckpointImplementation } from './checkpoints/create-checkpoint-implementation.js';
9
+ import { getCacheIdentifier, getMongoRelation } from './MongoRelation.js';
10
10
  import { MongoSnapshotter } from './MongoSnapshotter.js';
11
11
  import { parseChangeDocument, rawChangeStream } from './RawChangeStream.js';
12
- import { CHECKPOINTS_COLLECTION, timestampToDate } from './replication-utils.js';
12
+ import { CHECKPOINTS_COLLECTION, detectDocumentDb, timestampToDate } from './replication-utils.js';
13
13
  import { DirectSourceRowConverter } from './SourceRowConverter.js';
14
14
  /**
15
15
  * Thrown when the change stream is not valid anymore, and replication
@@ -49,6 +49,9 @@ export class ChangeStream {
49
49
  changeStreamTimeout;
50
50
  storageHooks;
51
51
  sourceRowConverter;
52
+ keepaliveIntervalMs;
53
+ isDocumentDb = false;
54
+ _checkpointImplementation = null;
52
55
  constructor(options) {
53
56
  this.storage = options.storage;
54
57
  this.metrics = options.metrics;
@@ -56,6 +59,7 @@ export class ChangeStream {
56
59
  this.connections = options.connections;
57
60
  this.maxAwaitTimeMS = options.maxAwaitTimeMS ?? 10_000;
58
61
  this.snapshotChunkLength = options.snapshotChunkLength ?? 6_000;
62
+ this.keepaliveIntervalMs = options.keepaliveIntervalMs ?? 60_000;
59
63
  this.storageHooks = options.storageHooks;
60
64
  this.client = this.connections.client;
61
65
  this.defaultDb = this.connections.db;
@@ -93,6 +97,33 @@ export class ChangeStream {
93
97
  get configurePostImages() {
94
98
  return this.connections.options.postImages == PostImagesOption.AUTO_CONFIGURE;
95
99
  }
100
+ /** The active checkpoint strategy. Only valid after ensureDetected(). */
101
+ get checkpointImplementation() {
102
+ if (this._checkpointImplementation == null) {
103
+ throw new ReplicationAssertionError('Checkpoint implementation not initialized - call ensureDetected() first');
104
+ }
105
+ return this._checkpointImplementation;
106
+ }
107
+ /**
108
+ * Detect DocumentDB and select the checkpoint implementation for the streaming
109
+ * loop. Idempotent. The snapshotter detects independently; the two coordinate
110
+ * through stored LSNs, not shared in-memory state.
111
+ */
112
+ async ensureDetected() {
113
+ if (this._checkpointImplementation != null) {
114
+ return;
115
+ }
116
+ this.isDocumentDb = await detectDocumentDb(this.defaultDb);
117
+ if (this.isDocumentDb) {
118
+ this.logger.warn('Azure DocumentDB support is experimental. APIs and behavior may change, and long-term stability is not yet guaranteed.');
119
+ }
120
+ this._checkpointImplementation = createCheckpointImplementation(this.isDocumentDb, {
121
+ client: this.client,
122
+ db: this.defaultDb,
123
+ checkpointStreamId: this.checkpointStreamId,
124
+ logger: this.logger
125
+ });
126
+ }
96
127
  getSourceNamespaceFilters() {
97
128
  const sourceTables = this.sync_rules.getSourceTables();
98
129
  let $inFilters = [
@@ -130,7 +161,15 @@ export class ChangeStream {
130
161
  // For details, see:
131
162
  // https://github.com/powersync-ja/powersync-service/pull/417
132
163
  // https://jira.mongodb.org/browse/SERVER-114532
133
- const nsFilter = multipleDatabases
164
+ //
165
+ // DocumentDB always opens a cluster-level change stream (admin +
166
+ // allChangesForCluster), even in single-database mode. A coll-only filter
167
+ // would then match same-named collections (including _powersync_checkpoints)
168
+ // in other databases of the cluster, letting a foreign standalone-checkpoint
169
+ // event advance/resolve checkpoints against the wrong source database. So we
170
+ // must filter on the full namespace whenever the stream is cluster-scoped.
171
+ const useFullNamespaceFilter = this.isDocumentDb || multipleDatabases;
172
+ const nsFilter = useFullNamespaceFilter
134
173
  ? // cluster-level: filter on the entire namespace
135
174
  { ns: { $in: $inFilters } }
136
175
  : // collection-level: filter on coll only
@@ -345,12 +384,16 @@ export class ChangeStream {
345
384
  }
346
385
  }
347
386
  rawChangeStreamBatches(options) {
348
- const lastLsn = options.lsn ? MongoLSN.fromSerialized(options.lsn) : null;
349
- const startAfter = lastLsn?.timestamp;
350
- const resumeAfter = lastLsn?.resumeToken;
387
+ const position = options.lsn ? this.checkpointImplementation.parseResumePosition(options.lsn) : null;
388
+ const startAfter = position?.startAfter ?? undefined;
389
+ const resumeAfter = position?.resumeAfter ?? undefined;
351
390
  const filters = options.filters;
352
391
  let fullDocument;
353
- if (this.usePostImages) {
392
+ if (this.isDocumentDb) {
393
+ // DocumentDB does not support changeStreamPreAndPostImages, so 'required' won't work.
394
+ fullDocument = 'updateLookup';
395
+ }
396
+ else if (this.usePostImages) {
354
397
  // 'read_only' or 'auto_configure'
355
398
  // Configuration happens during snapshot, or when we see new
356
399
  // collections.
@@ -360,41 +403,54 @@ export class ChangeStream {
360
403
  fullDocument = 'updateLookup';
361
404
  }
362
405
  const streamOptions = {
363
- showExpandedEvents: true,
364
406
  fullDocument: fullDocument
365
407
  };
408
+ if (!this.isDocumentDb) {
409
+ // DocumentDB does not support showExpandedEvents.
410
+ streamOptions.showExpandedEvents = true;
411
+ }
366
412
  const pipeline = [
367
413
  {
368
414
  $changeStream: streamOptions
369
415
  },
370
416
  {
371
417
  $match: filters.$match
372
- },
373
- { $changeStreamSplitLargeEvent: {} }
418
+ }
374
419
  ];
420
+ if (!this.isDocumentDb) {
421
+ // DocumentDB does not support $changeStreamSplitLargeEvent.
422
+ pipeline.push({ $changeStreamSplitLargeEvent: {} });
423
+ }
375
424
  /**
376
425
  * Only one of these options can be supplied at a time.
377
426
  */
378
427
  if (resumeAfter) {
379
428
  streamOptions.resumeAfter = resumeAfter;
380
429
  }
381
- else {
430
+ else if (startAfter != null) {
382
431
  // Legacy: We don't persist lsns without resumeTokens anymore, but we do still handle the
383
432
  // case if we have an old one.
384
433
  // This is also relevant for getSnapshotLSN().
434
+ // The sentinel implementation never produces a startAfter, and a fresh DocumentDB stream
435
+ // opens from "now" with neither option set.
385
436
  streamOptions.startAtOperationTime = startAfter;
386
437
  }
387
438
  let watchDb;
388
- if (filters.multipleDatabases) {
439
+ if (this.isDocumentDb || filters.multipleDatabases) {
440
+ // DocumentDB only supports cluster-level change streams.
389
441
  watchDb = this.client.db('admin');
390
442
  streamOptions.allChangesForCluster = true;
391
443
  }
392
444
  else {
393
445
  watchDb = this.defaultDb;
394
446
  }
447
+ const maxAwaitTimeMS = options.maxAwaitTimeMS ?? this.maxAwaitTimeMS;
395
448
  return rawChangeStream(watchDb, pipeline, {
396
449
  batchSize: options.batchSize ?? this.snapshotChunkLength,
397
- maxAwaitTimeMS: options.maxAwaitTimeMS ?? this.maxAwaitTimeMS,
450
+ maxAwaitTimeMS,
451
+ // maxAwaitTimeMS can be 0 for probe-style streams that do not want an idle wait.
452
+ // In that case there is no client-side wait to emulate for DocumentDB.
453
+ clientSideMaxAwaitTimeMS: this.isDocumentDb && maxAwaitTimeMS > 0,
398
454
  maxTimeMS: this.changeStreamTimeout,
399
455
  signal: options.signal,
400
456
  logger: this.logger,
@@ -405,13 +461,14 @@ export class ChangeStream {
405
461
  return this.sourceRowConverter.rawToSqliteRow(row);
406
462
  }
407
463
  async streamChangesInternal() {
464
+ await this.ensureDetected();
408
465
  const transactionsReplicatedMetric = this.metrics.getCounter(ReplicationMetric.TRANSACTIONS_REPLICATED);
409
466
  const bytesReplicatedMetric = this.metrics.getCounter(ReplicationMetric.DATA_REPLICATED_BYTES);
410
467
  const chunksReplicatedMetric = this.metrics.getCounter(ReplicationMetric.CHUNKS_REPLICATED);
411
468
  const tracer = new PerformanceTracer('MongoDB streaming replication');
412
469
  await this.storage.startBatch({
413
470
  logger: this.logger,
414
- zeroLSN: MongoLSN.ZERO.comparable,
471
+ zeroLSN: this.checkpointImplementation.zeroLsn,
415
472
  defaultSchema: this.defaultDb.databaseName,
416
473
  // We get a complete postimage for every change, so we don't need to store the current data.
417
474
  storeCurrentData: false,
@@ -422,13 +479,13 @@ export class ChangeStream {
422
479
  if (resumeFromLsn == null) {
423
480
  throw new ReplicationAssertionError(`No LSN found to resume from`);
424
481
  }
425
- const lastLsn = MongoLSN.fromSerialized(resumeFromLsn);
426
- const startAfter = lastLsn?.timestamp;
482
+ // Seed the implementation's coordinate state from the stored LSN, and parse
483
+ // the legacy startAfter timestamp (timestamp implementation only) for the
484
+ // resume-boundary dedupe guard below.
485
+ this.checkpointImplementation.seedPosition(resumeFromLsn);
486
+ const { startAfter } = this.checkpointImplementation.parseResumePosition(resumeFromLsn);
427
487
  let outerSpan = tracer.span('batch');
428
- // It is normal for this to be a minute or two old when there is a low volume
429
- // of ChangeStream events.
430
- const tokenAgeSeconds = Math.round((Date.now() - timestampToDate(startAfter).getTime()) / 1000);
431
- this.logger.info(`Resume streaming at ${startAfter?.inspect()} / ${lastLsn} | Token age: ${tokenAgeSeconds}s`);
488
+ this.checkpointImplementation.logResume(resumeFromLsn);
432
489
  const filters = this.getSourceNamespaceFilters();
433
490
  // This is closed when the for loop below returns/breaks/throws
434
491
  const batchStream = this.rawChangeStreamBatches({
@@ -440,7 +497,7 @@ export class ChangeStream {
440
497
  // Always start with a checkpoint.
441
498
  // This helps us to clear errors when restarting, even if there is
442
499
  // no data to replicate.
443
- let waitForCheckpointLsn = await createCheckpoint(this.client, this.defaultDb, this.checkpointStreamId);
500
+ let waitForCheckpointLsn = await this.checkpointImplementation.createBatchCheckpoint();
444
501
  let splitDocument = null;
445
502
  let flexDbNameWorkaroundLogged = false;
446
503
  let lastEmptyResume = performance.now();
@@ -459,19 +516,18 @@ export class ChangeStream {
459
516
  // We do this by persisting a keepalive checkpoint.
460
517
  // If we don't update it on empty events, we do keep consistency, but resuming the stream
461
518
  // with old tokens may cause connection timeouts.
462
- if (waitForCheckpointLsn == null && performance.now() - lastEmptyResume > 60_000) {
463
- const { comparable: lsn, timestamp } = MongoLSN.fromResumeToken(resumeToken);
464
- await batch.keepalive(lsn);
519
+ if (waitForCheckpointLsn == null && performance.now() - lastEmptyResume > this.keepaliveIntervalMs) {
520
+ // The implementation persists a keepalive (timestamp) or bumps the
521
+ // sentinel so a later event commits (sentinel). Logging is handled
522
+ // inside the implementation.
523
+ await this.checkpointImplementation.keepalive(batch, resumeToken);
465
524
  this.touch();
466
525
  lastEmptyResume = performance.now();
467
- // Log the token update. This helps as a general "replication is still active" message in the logs.
468
- // This token would typically be around 10s behind.
469
- this.logger.info(`Idle change stream. Persisted resumeToken for ${timestampToDate(timestamp).toISOString()}`);
470
526
  this.replicationLag.markStarted();
471
527
  }
472
528
  // If we have no changes, we can just persist the keepalive.
473
- // This is throttled to once per minute.
474
- if (performance.now() - lastEmptyResume < 60_000) {
529
+ // This is throttled to once per interval.
530
+ if (performance.now() - lastEmptyResume < this.keepaliveIntervalMs) {
475
531
  continue;
476
532
  }
477
533
  }
@@ -558,8 +614,12 @@ export class ChangeStream {
558
614
  //
559
615
  // It may be useful to also throttle commits due to standalone checkpoints in the future.
560
616
  // However, these typically have a much lower rate than batch checkpoints, so we don't do that for now.
561
- const checkpointId = changeDocument.documentKey._id;
562
- if (checkpointId == STANDALONE_CHECKPOINT_ID) {
617
+ const kind = this.checkpointImplementation.event.observe(changeDocument);
618
+ if (kind == 'foreign') {
619
+ // Another stream's barrier - ignore.
620
+ continue;
621
+ }
622
+ else if (kind == 'standalone') {
563
623
  // Standalone / write checkpoint received.
564
624
  // When we are caught up, commit immediately to keep write checkpoint latency low.
565
625
  // Once there is already a batch checkpoint pending, or the driver has buffered more
@@ -569,7 +629,7 @@ export class ChangeStream {
569
629
  if (hasBufferedChanges && waitForCheckpointLsn == null) {
570
630
  // Buffered changes - create a new batch checkpoint to rate limit commits
571
631
  using _ = tracer.span('source_checkpoint');
572
- waitForCheckpointLsn = await createCheckpoint(this.client, this.defaultDb, this.checkpointStreamId);
632
+ waitForCheckpointLsn = await this.checkpointImplementation.createBatchCheckpoint();
573
633
  continue;
574
634
  }
575
635
  else if (waitForCheckpointLsn != null) {
@@ -580,14 +640,10 @@ export class ChangeStream {
580
640
  // No buffered changes, and no batch checkpoint pending - commit immediately.
581
641
  }
582
642
  }
583
- else if (!this.checkpointStreamId.equals(checkpointId)) {
584
- continue;
585
- }
586
- const { comparable: lsn } = new MongoLSN({
587
- timestamp: changeDocument.clusterTime,
588
- resume_token: changeDocument._id
589
- });
590
- if (waitForCheckpointLsn != null && lsn >= waitForCheckpointLsn) {
643
+ // kind == 'own-barrier' falls through to commit.
644
+ const lsn = this.checkpointImplementation.event.lsn(changeDocument);
645
+ if (waitForCheckpointLsn != null &&
646
+ this.checkpointImplementation.event.resolvesBarrier(waitForCheckpointLsn, changeDocument)) {
591
647
  waitForCheckpointLsn = null;
592
648
  }
593
649
  const { checkpointBlocked, checkpointCreated } = await batch.commit(lsn, {
@@ -603,7 +659,7 @@ export class ChangeStream {
603
659
  changeDocument.operationType == 'delete') {
604
660
  if (waitForCheckpointLsn == null) {
605
661
  using _ = tracer.span('source_checkpoint');
606
- waitForCheckpointLsn = await createCheckpoint(this.client, this.defaultDb, this.checkpointStreamId);
662
+ waitForCheckpointLsn = await this.checkpointImplementation.createBatchCheckpoint();
607
663
  }
608
664
  const rel = getMongoRelation(changeDocument.ns, this.connections.connectionTag);
609
665
  const tables = await this.getRelations(batch, rel, {
@@ -615,7 +671,12 @@ export class ChangeStream {
615
671
  });
616
672
  const tablesToReplicate = tables.filter((table) => table.syncAny);
617
673
  if (tablesToReplicate.length > 0) {
618
- this.replicationLag.trackUncommittedChange(changeDocument.clusterTime == null ? null : timestampToDate(changeDocument.clusterTime));
674
+ this.replicationLag.trackUncommittedChange(
675
+ // Standard MongoDB uses clusterTime, unchanged. DocumentDB has no
676
+ // clusterTime, so fall back to wallTime there for the lag metric.
677
+ changeDocument.clusterTime != null
678
+ ? timestampToDate(changeDocument.clusterTime)
679
+ : (changeDocument.wallTime ?? null));
619
680
  const transactionKeyValue = transactionKey(changeDocument);
620
681
  if (transactionKeyValue == null || lastTxnKey != transactionKeyValue) {
621
682
  // Very crude metric for counting transactions replicated.
@@ -667,7 +728,7 @@ export class ChangeStream {
667
728
  // Batches are generally large (64MB or 6000 events, whichever comes first),
668
729
  // so this is a good natural point to flush and mark progress.
669
730
  // We avoid this when splitDocument is set, since we cannot resume in the middle of a split event.
670
- const { comparable: lsn } = MongoLSN.fromResumeToken(resumeToken);
731
+ const lsn = this.checkpointImplementation.lsnFromResumeToken(resumeToken);
671
732
  await batch.flush({ oldestUncommittedChange: this.replicationLag.oldestUncommittedChange });
672
733
  // TODO: We should consider making this standard behavior of flush().
673
734
  await batch.setResumeLsn(lsn);