@powersync/service-module-mongodb-storage 0.0.0-dev-20251202102946 → 0.0.0-dev-20251208145829

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@powersync/service-module-mongodb-storage",
3
3
  "repository": "https://github.com/powersync-ja/powersync-service",
4
4
  "types": "dist/index.d.ts",
5
- "version": "0.0.0-dev-20251202102946",
5
+ "version": "0.0.0-dev-20251208145829",
6
6
  "main": "dist/index.js",
7
7
  "license": "FSL-1.1-ALv2",
8
8
  "type": "module",
@@ -27,15 +27,15 @@
27
27
  "lru-cache": "^10.2.2",
28
28
  "ts-codec": "^1.3.0",
29
29
  "uuid": "^11.1.0",
30
- "@powersync/lib-service-mongodb": "0.0.0-dev-20251202102946",
31
- "@powersync/lib-services-framework": "0.0.0-dev-20251202102946",
32
- "@powersync/service-core": "0.0.0-dev-20251202102946",
30
+ "@powersync/lib-service-mongodb": "0.0.0-dev-20251208145829",
31
+ "@powersync/lib-services-framework": "0.0.0-dev-20251208145829",
32
+ "@powersync/service-core": "0.0.0-dev-20251208145829",
33
33
  "@powersync/service-jsonbig": "0.17.12",
34
- "@powersync/service-sync-rules": "0.0.0-dev-20251202102946",
35
- "@powersync/service-types": "0.0.0-dev-20251202102946"
34
+ "@powersync/service-sync-rules": "0.0.0-dev-20251208145829",
35
+ "@powersync/service-types": "0.13.3"
36
36
  },
37
37
  "devDependencies": {
38
- "@powersync/service-core-tests": "0.0.0-dev-20251202102946"
38
+ "@powersync/service-core-tests": "0.0.0-dev-20251208145829"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b",
@@ -218,6 +218,7 @@ export class MongoBucketStorage
218
218
  slot_name: slot_name,
219
219
  last_checkpoint_ts: null,
220
220
  last_fatal_error: null,
221
+ last_fatal_error_ts: null,
221
222
  last_keepalive_ts: null
222
223
  };
223
224
  await this.db.sync_rules.insertOne(doc);
@@ -82,6 +82,7 @@ export class MongoBucketBatch
82
82
  private batch: OperationBatch | null = null;
83
83
  private write_checkpoint_batch: storage.CustomWriteCheckpointOptions[] = [];
84
84
  private markRecordUnavailable: BucketStorageMarkRecordUnavailable | undefined;
85
+ private clearedError = false;
85
86
 
86
87
  /**
87
88
  * Last LSN received associated with a checkpoint.
@@ -247,6 +248,8 @@ export class MongoBucketBatch
247
248
  let resumeBatch: OperationBatch | null = null;
248
249
  let transactionSize = 0;
249
250
 
251
+ let didFlush = false;
252
+
250
253
  // Now batch according to the sizes
251
254
  // This is a single batch if storeCurrentData == false
252
255
  for await (let b of batch.batched(sizes)) {
@@ -296,7 +299,8 @@ export class MongoBucketBatch
296
299
  if (persistedBatch!.shouldFlushTransaction()) {
297
300
  // Transaction is getting big.
298
301
  // Flush, and resume in a new transaction.
299
- await persistedBatch!.flush(this.db, this.session, options);
302
+ const { flushedAny } = await persistedBatch!.flush(this.db, this.session, options);
303
+ didFlush ||= flushedAny;
300
304
  persistedBatch = null;
301
305
  // Computing our current progress is a little tricky here, since
302
306
  // we're stopping in the middle of a batch.
@@ -307,10 +311,15 @@ export class MongoBucketBatch
307
311
 
308
312
  if (persistedBatch) {
309
313
  transactionSize = persistedBatch.currentSize;
310
- await persistedBatch.flush(this.db, this.session, options);
314
+ const { flushedAny } = await persistedBatch.flush(this.db, this.session, options);
315
+ didFlush ||= flushedAny;
311
316
  }
312
317
  }
313
318
 
319
+ if (didFlush) {
320
+ await this.clearError();
321
+ }
322
+
314
323
  return resumeBatch?.hasData() ? resumeBatch : null;
315
324
  }
316
325
 
@@ -718,6 +727,7 @@ export class MongoBucketBatch
718
727
  last_keepalive_ts: now,
719
728
  snapshot_done: true,
720
729
  last_fatal_error: null,
730
+ last_fatal_error_ts: null,
721
731
  keepalive_op: null
722
732
  };
723
733
 
@@ -852,6 +862,7 @@ export class MongoBucketBatch
852
862
  last_checkpoint_lsn: lsn,
853
863
  snapshot_done: true,
854
864
  last_fatal_error: null,
865
+ last_fatal_error_ts: null,
855
866
  last_keepalive_ts: new Date()
856
867
  },
857
868
  $unset: { snapshot_lsn: 1 }
@@ -1079,6 +1090,26 @@ export class MongoBucketBatch
1079
1090
  });
1080
1091
  }
1081
1092
 
1093
+ protected async clearError(): Promise<void> {
1094
+ // No need to clear an error more than once per batch, since an error would always result in restarting the batch.
1095
+ if (this.clearedError) {
1096
+ return;
1097
+ }
1098
+
1099
+ await this.db.sync_rules.updateOne(
1100
+ {
1101
+ _id: this.group_id
1102
+ },
1103
+ {
1104
+ $set: {
1105
+ last_fatal_error: null,
1106
+ last_fatal_error_ts: null
1107
+ }
1108
+ }
1109
+ );
1110
+ this.clearedError = true;
1111
+ }
1112
+
1082
1113
  /**
1083
1114
  * Gets relevant {@link SqlEventDescriptor}s for the given {@link SourceTable}
1084
1115
  */
@@ -13,6 +13,7 @@ export class MongoPersistedSyncRulesContent implements storage.PersistedSyncRule
13
13
  public readonly sync_rules_content: string;
14
14
  public readonly last_checkpoint_lsn: string | null;
15
15
  public readonly last_fatal_error: string | null;
16
+ public readonly last_fatal_error_ts: Date | null;
16
17
  public readonly last_keepalive_ts: Date | null;
17
18
  public readonly last_checkpoint_ts: Date | null;
18
19
  public readonly active: boolean;
@@ -29,6 +30,7 @@ export class MongoPersistedSyncRulesContent implements storage.PersistedSyncRule
29
30
  // Handle legacy values
30
31
  this.slot_name = doc.slot_name ?? `powersync_${this.id}`;
31
32
  this.last_fatal_error = doc.last_fatal_error;
33
+ this.last_fatal_error_ts = doc.last_fatal_error_ts;
32
34
  this.last_checkpoint_ts = doc.last_checkpoint_ts;
33
35
  this.last_keepalive_ts = doc.last_keepalive_ts;
34
36
  this.active = doc.state == 'ACTIVE';
@@ -39,7 +39,6 @@ import { MongoParameterCompactor } from './MongoParameterCompactor.js';
39
39
  import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
40
40
  import { idPrefixFilter, mapOpEntry, readSingleBatch, setSessionSnapshotTime } from '../../utils/util.js';
41
41
 
42
-
43
42
  export interface MongoSyncBucketStorageOptions {
44
43
  checksumOptions?: MongoChecksumOptions;
45
44
  }
@@ -648,11 +647,11 @@ export class MongoSyncBucketStorage
648
647
  },
649
648
  {
650
649
  $set: {
651
- last_fatal_error: message
650
+ last_fatal_error: message,
651
+ last_fatal_error_ts: new Date()
652
652
  }
653
653
  }
654
654
  );
655
- await this.db.notifyCheckpoint();
656
655
  }
657
656
 
658
657
  async compact(options?: storage.CompactOptions) {
@@ -351,12 +351,21 @@ export class PersistedBatch {
351
351
  }
352
352
  }
353
353
 
354
+ const stats = {
355
+ bucketDataCount: this.bucketData.length,
356
+ parameterDataCount: this.bucketParameters.length,
357
+ currentDataCount: this.currentData.length,
358
+ flushedAny: flushedSomething
359
+ };
360
+
354
361
  this.bucketData = [];
355
362
  this.bucketParameters = [];
356
363
  this.currentData = [];
357
364
  this.bucketStates.clear();
358
365
  this.currentSize = 0;
359
366
  this.debugLastOpId = null;
367
+
368
+ return stats;
360
369
  }
361
370
 
362
371
  private getBucketStateUpdates(): mongo.AnyBulkWriteOperation<BucketStateDocument>[] {
@@ -196,6 +196,8 @@ export interface SyncRuleDocument {
196
196
  */
197
197
  last_fatal_error: string | null;
198
198
 
199
+ last_fatal_error_ts: Date | null;
200
+
199
201
  content: string;
200
202
 
201
203
  lock?: {