@powersync/service-module-mongodb-storage 0.23.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/LICENSE +201 -67
- package/dist/storage/MongoBucketStorage.d.ts +1 -0
- package/dist/storage/MongoBucketStorage.js +3 -0
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +60 -39
- package/dist/storage/implementation/MongoBucketBatch.js +123 -296
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoOpIdAllocator.d.ts +6 -1
- package/dist/storage/implementation/MongoOpIdAllocator.js +12 -5
- package/dist/storage/implementation/MongoOpIdAllocator.js.map +1 -1
- package/dist/storage/implementation/MongoParsedSyncConfigSet.d.ts +7 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js +28 -2
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js.map +1 -1
- package/dist/storage/implementation/MongoReplicationOptions.d.ts +27 -0
- package/dist/storage/implementation/MongoReplicationOptions.js +26 -0
- package/dist/storage/implementation/MongoReplicationOptions.js.map +1 -0
- package/dist/storage/implementation/MongoSyncBucketStorage.js +2 -3
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +15 -2
- package/dist/storage/implementation/MongoSyncRulesLock.js +36 -14
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/common/BatchOperationBuffer.d.ts +79 -0
- package/dist/storage/implementation/common/BatchOperationBuffer.js +286 -0
- package/dist/storage/implementation/common/BatchOperationBuffer.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +10 -103
- package/dist/storage/implementation/common/PersistedBatch.js +1 -291
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/common/PreparedPublication.d.ts +43 -0
- package/dist/storage/implementation/common/PreparedPublication.js +2 -0
- package/dist/storage/implementation/common/PreparedPublication.js.map +1 -0
- package/dist/storage/implementation/common/SourceRecordStore.d.ts +0 -2
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +17 -13
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +259 -18
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +21 -15
- package/dist/storage/implementation/v1/PersistedBatchV1.js +58 -24
- package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +0 -2
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js +0 -3
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +25 -14
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +350 -23
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +1 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js +10 -4
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +39 -28
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +46 -24
- package/dist/storage/implementation/v3/PersistedBatchV3.js +159 -83
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +12 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +41 -13
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -1
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.d.ts +4 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js +4 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js.map +1 -1
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.d.ts +27 -2
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js +61 -5
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js.map +1 -1
- package/package.json +9 -10
- package/src/storage/MongoBucketStorage.ts +4 -0
- package/src/storage/implementation/MongoBucketBatch.ts +185 -392
- package/src/storage/implementation/MongoOpIdAllocator.ts +12 -5
- package/src/storage/implementation/MongoParsedSyncConfigSet.ts +40 -1
- package/src/storage/implementation/MongoReplicationOptions.ts +28 -0
- package/src/storage/implementation/MongoSyncBucketStorage.ts +2 -3
- package/src/storage/implementation/MongoSyncRulesLock.ts +39 -17
- package/src/storage/implementation/common/BatchOperationBuffer.ts +353 -0
- package/src/storage/implementation/common/PersistedBatch.ts +12 -390
- package/src/storage/implementation/common/PreparedPublication.ts +49 -0
- package/src/storage/implementation/common/SourceRecordStore.ts +0 -2
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +339 -27
- package/src/storage/implementation/v1/PersistedBatchV1.ts +74 -32
- package/src/storage/implementation/v1/SourceRecordStoreV1.ts +0 -5
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +430 -32
- package/src/storage/implementation/v3/MongoCompactorV3.ts +13 -4
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +43 -29
- package/src/storage/implementation/v3/PersistedBatchV3.ts +209 -108
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +45 -15
- package/src/storage/implementation/v3/object-storage/BucketDataObjectStorage.ts +9 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorageLifecycle.ts +79 -5
- package/test/src/checkpoint_cleanup.test.ts +75 -0
- package/test/src/concurrent_writers.test.ts +127 -53
- package/test/src/helpers/PublicationCommandMonitor.ts +119 -0
- package/test/src/helpers/concurrentWriter.mjs +2 -2
- package/test/src/invalid_sync_config.test.ts +9 -0
- package/test/src/object_storage_lifecycle.test.ts +72 -2
- package/test/src/prepared_publication.test.ts +388 -0
- package/test/src/replication_preparation.test.ts +829 -0
- package/test/src/replication_publication_baseline.test.ts +203 -0
- package/test/src/replication_publication_batching.test.ts +212 -0
- package/test/src/replication_uploads.test.ts +393 -0
- package/test/src/source_table_config.test.ts +4 -4
- package/test/src/storage_object_storage_inline_threshold.test.ts +1 -1
- package/test/src/storage_s3_compaction_lifecycle.test.ts +93 -1
- package/test/src/storage_sync.test.ts +83 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -4,18 +4,19 @@ import * as bson from 'bson';
|
|
|
4
4
|
import { BaseObserver, Logger } from '@powersync/lib-services-framework';
|
|
5
5
|
import { BucketDefinitionMapping, BucketStorageMarkRecordUnavailable, InternalOpId, PerformanceTracer, storage } from '@powersync/service-core';
|
|
6
6
|
import { PersistedBatch } from './common/PersistedBatch.js';
|
|
7
|
-
import { SourceRecordStore } from './common/SourceRecordStore.js';
|
|
7
|
+
import { LoadedSourceRecord, SourceRecordStore } from './common/SourceRecordStore.js';
|
|
8
8
|
import type { VersionedPowerSyncMongo } from './db.js';
|
|
9
9
|
import { SyncRuleDocumentBase } from './models.js';
|
|
10
|
+
import { MongoIdSequence } from './MongoIdSequence.js';
|
|
10
11
|
import { MongoOpIdAllocator } from './MongoOpIdAllocator.js';
|
|
11
12
|
import { MongoParsedSyncConfigSet } from './MongoParsedSyncConfigSet.js';
|
|
12
13
|
import { MongoSyncRulesLock } from './MongoSyncRulesLock.js';
|
|
13
14
|
import { MongoWriteBatch } from './MongoWriteBatch.js';
|
|
15
|
+
import { OperationBatch, RecordOperation } from './OperationBatch.js';
|
|
14
16
|
import { ObjectStorage } from './v3/object-storage/ObjectStorage.js';
|
|
15
17
|
export interface MongoBucketBatchOptions {
|
|
16
18
|
replicationLock: MongoSyncRulesLock;
|
|
17
19
|
opIdAllocator: MongoOpIdAllocator;
|
|
18
|
-
db: VersionedPowerSyncMongo;
|
|
19
20
|
/**
|
|
20
21
|
* The parsed sync config set for this batch.
|
|
21
22
|
*
|
|
@@ -53,8 +54,8 @@ export interface MongoBucketBatchOptions {
|
|
|
53
54
|
export declare abstract class MongoBucketBatch extends BaseObserver<storage.BucketBatchStorageListener> implements storage.BucketStorageBatch {
|
|
54
55
|
protected readonly options: MongoBucketBatchOptions;
|
|
55
56
|
protected logger: Logger;
|
|
56
|
-
private readonly client;
|
|
57
57
|
readonly db: VersionedPowerSyncMongo;
|
|
58
|
+
/** Shared by this lease's writers; only use inside a serialized public operation. */
|
|
58
59
|
readonly session: mongo.ClientSession;
|
|
59
60
|
protected readonly sync_rules: HydratedSyncConfig;
|
|
60
61
|
protected readonly replicationStreamId: number;
|
|
@@ -68,15 +69,15 @@ export declare abstract class MongoBucketBatch extends BaseObserver<storage.Buck
|
|
|
68
69
|
* via SourceTable.storeCurrentData. The effective per-record value is the conjunction of
|
|
69
70
|
* the two.
|
|
70
71
|
*/
|
|
71
|
-
|
|
72
|
+
protected readonly storeCurrentData: boolean;
|
|
72
73
|
readonly skipExistingRows: boolean;
|
|
73
74
|
protected readonly mapping: BucketDefinitionMapping;
|
|
74
75
|
protected readonly objectStorageUsageWriterId: string;
|
|
75
|
-
|
|
76
|
+
protected batch: OperationBatch | null;
|
|
76
77
|
protected write_checkpoint_batch: storage.CustomWriteCheckpointOptions[];
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
protected readonly markRecordUnavailable: BucketStorageMarkRecordUnavailable | undefined;
|
|
79
|
+
protected hooks: storage.StorageHooks | undefined;
|
|
80
|
+
protected clearedError: boolean;
|
|
80
81
|
protected tracer: PerformanceTracer<'storage' | 'evaluate'>;
|
|
81
82
|
/**
|
|
82
83
|
* Last written op, if any. This may not reflect a consistent checkpoint.
|
|
@@ -95,56 +96,73 @@ export declare abstract class MongoBucketBatch extends BaseObserver<storage.Buck
|
|
|
95
96
|
resumeFromLsn: string | null;
|
|
96
97
|
constructor(options: MongoBucketBatchOptions);
|
|
97
98
|
addCustomWriteCheckpoint(checkpoint: storage.BatchedCustomWriteCheckpointOptions): void;
|
|
98
|
-
|
|
99
|
+
resolveTables(options: storage.ResolveTablesOptions): Promise<storage.ResolveTablesResult>;
|
|
100
|
+
protected abstract resolveTablesInternal(options: storage.ResolveTablesOptions): Promise<storage.ResolveTablesResult>;
|
|
99
101
|
protected abstract createPersistedBatch(writtenSize: number): PersistedBatch;
|
|
100
102
|
protected abstract get sourceRecordStore(): SourceRecordStore;
|
|
101
103
|
protected abstract cleanupDroppedSourceTables(sourceTables: storage.SourceTable[]): Promise<void>;
|
|
102
|
-
|
|
103
|
-
abstract
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
abstract
|
|
107
|
-
|
|
104
|
+
commit(lsn: string, options?: storage.BucketBatchCommitOptions): Promise<storage.CheckpointResult>;
|
|
105
|
+
protected abstract commitInternal(lsn: string, options?: storage.BucketBatchCommitOptions): Promise<storage.CheckpointResult>;
|
|
106
|
+
keepalive(lsn: string): Promise<storage.CheckpointResult>;
|
|
107
|
+
setResumeLsn(lsn: string): Promise<void>;
|
|
108
|
+
protected abstract setResumeLsnInternal(lsn: string): Promise<void>;
|
|
109
|
+
getSourceTableStatus(table: storage.SourceTable): Promise<storage.SourceTable | null>;
|
|
110
|
+
protected abstract getSourceTableStatusInternal(table: storage.SourceTable): Promise<storage.SourceTable | null>;
|
|
111
|
+
markAllSnapshotDone(no_checkpoint_before_lsn: string): Promise<void>;
|
|
112
|
+
protected abstract markAllSnapshotDoneInternal(no_checkpoint_before_lsn: string): Promise<void>;
|
|
113
|
+
markSnapshotDone(no_checkpoint_before_lsn: string, options?: {
|
|
108
114
|
throwOnConflict?: boolean;
|
|
109
115
|
}): Promise<void>;
|
|
110
|
-
abstract
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
protected abstract markSnapshotDoneInternal(no_checkpoint_before_lsn: string, options?: {
|
|
117
|
+
throwOnConflict?: boolean;
|
|
118
|
+
}): Promise<void>;
|
|
119
|
+
markTableSnapshotRequired(table: storage.SourceTable): Promise<void>;
|
|
120
|
+
protected abstract markTableSnapshotRequiredInternal(table: storage.SourceTable): Promise<void>;
|
|
121
|
+
markTableSnapshotDone(tables: storage.SourceTable[], no_checkpoint_before_lsn?: string): Promise<storage.SourceTable[]>;
|
|
122
|
+
protected abstract markTableSnapshotDoneInternal(tables: storage.SourceTable[], no_checkpoint_before_lsn?: string): Promise<storage.SourceTable[]>;
|
|
113
123
|
/** Perform any version-specific setup required before writing custom checkpoints. */
|
|
114
124
|
protected prepareCustomWriteCheckpoints(): Promise<void>;
|
|
115
125
|
flush(options?: storage.BatchBucketFlushOptions): Promise<storage.FlushedResult | null>;
|
|
126
|
+
/** Internal helpers require the public operation to hold the writer mutex. */
|
|
127
|
+
protected flushInternal(options?: storage.BatchBucketFlushOptions): Promise<storage.FlushedResult | null>;
|
|
116
128
|
/** Publish the checkpoint in the final flush transaction, or use the empty-commit path. */
|
|
117
|
-
protected flushAndCommit<T>(checkpoint: (stream: SyncRuleDocumentBase, lastOp: InternalOpId) => Promise<T>, commitWithoutFlush: () => Promise<T>, options?: storage.BatchBucketFlushOptions, projection?: mongo.Document): Promise<T>;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
protected flushAndCommit<T>(checkpoint: (stream: SyncRuleDocumentBase, lastOp: InternalOpId, writes?: MongoWriteBatch) => Promise<T>, commitWithoutFlush: () => Promise<T>, options?: storage.BatchBucketFlushOptions, projection?: mongo.Document): Promise<T>;
|
|
130
|
+
protected abstract flushInner(options?: storage.BatchBucketFlushOptions, checkpoint?: (stream: SyncRuleDocumentBase, lastOp: InternalOpId, writes?: MongoWriteBatch) => Promise<void>, projection?: mongo.Document): Promise<storage.FlushedResult | null>;
|
|
131
|
+
/**
|
|
132
|
+
* Evaluate one source operation and append its storage writes to batch.
|
|
133
|
+
*
|
|
134
|
+
* Diagnostics run during evaluation. V1 calls markRecordUnavailable immediately;
|
|
135
|
+
* v3/v4 supply a collector and deliver repair notifications only after a
|
|
136
|
+
* confirmed publication. A failed row attempt may have registered a repair,
|
|
137
|
+
* so its caller must discard that row's collected notification on failure.
|
|
138
|
+
*/
|
|
139
|
+
protected saveOperation(batch: PersistedBatch, operation: RecordOperation, sourceRecord: LoadedSourceRecord | null, opSeq: MongoIdSequence, onRecordUnavailable: BucketStorageMarkRecordUnavailable | undefined): LoadedSourceRecord | null;
|
|
121
140
|
protected fence(session?: mongo.ClientSession, projection?: mongo.Document): Promise<mongo.WithId<SyncRuleDocumentBase>>;
|
|
122
141
|
protected withTransaction<T>(cb: (stream: SyncRuleDocumentBase) => Promise<T>, session?: mongo.ClientSession): Promise<T>;
|
|
123
|
-
/**
|
|
124
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Internal transaction helper: the public writer operation already holds the
|
|
144
|
+
* mutex. The first operation must modify the stream document conditional on
|
|
145
|
+
* lease ownership. This database fence is required on every retry even though
|
|
146
|
+
* local writers are serialized; another process may have taken over the lease.
|
|
147
|
+
*/
|
|
148
|
+
protected withFencedTransaction<S, T>(acquireFence: () => Promise<S>, cb: (stream: S) => Promise<T>, session?: mongo.ClientSession, description?: string): Promise<T>;
|
|
149
|
+
/**
|
|
150
|
+
* Public database operations acquire the lease's mutex once, then call only
|
|
151
|
+
* internal helpers until they finish. Those helpers must never call a public
|
|
152
|
+
* database operation or reacquire this mutex. All session use, including reads,
|
|
153
|
+
* belongs inside this boundary so it cannot join another writer's transaction.
|
|
154
|
+
* Transaction helpers still fence database ownership on every attempt.
|
|
155
|
+
*/
|
|
125
156
|
private withWriterLock;
|
|
126
|
-
/**
|
|
157
|
+
/** Internal single-document update; the public operation already holds the mutex. */
|
|
127
158
|
protected updateStreamMetadata(set: mongo.Document, filter?: mongo.Document, writeConcern?: mongo.WriteConcernSettings): Promise<void>;
|
|
128
159
|
/** Caller must already be inside a fenced transaction holding the writer mutex. */
|
|
129
160
|
protected updateStreamMetadataInTransaction(set: mongo.Document, filter?: mongo.Document): Promise<void>;
|
|
130
161
|
private writeStreamMetadata;
|
|
131
|
-
private withReplicationTransaction;
|
|
132
162
|
/** Highest durably persisted operation, including operations not yet checkpointed. */
|
|
133
163
|
protected abstract persistedOpHead(stream: SyncRuleDocumentBase): InternalOpId;
|
|
134
164
|
/** Advance the persisted head in the same transaction as the operations. */
|
|
135
165
|
protected abstract onReplicationTransactionFlush(writes: MongoWriteBatch, lastOp: InternalOpId): void;
|
|
136
|
-
/**
|
|
137
|
-
* Called after a replication transaction has successfully committed, with the last persisted op id.
|
|
138
|
-
*
|
|
139
|
-
* v1 storage tracks this in memory to fold into the next checkpoint. v3 storage does not need it:
|
|
140
|
-
* the stream-level `last_persisted_op` is already advanced durably by
|
|
141
|
-
* {@link onReplicationTransactionFlush} or the combined checkpoint update within the same
|
|
142
|
-
* transaction, and empty commits read it from the document.
|
|
143
|
-
*
|
|
144
|
-
* Keep calls to this adjacent to {@link withReplicationTransaction} usage - both must observe
|
|
145
|
-
* every path that persists ops.
|
|
146
|
-
*/
|
|
147
|
-
protected recordPersistedOp(_lastOp: InternalOpId): void;
|
|
148
166
|
[Symbol.asyncDispose](): Promise<void>;
|
|
149
167
|
dispose(): Promise<void>;
|
|
150
168
|
save(record: storage.SaveOptions): Promise<storage.FlushedResult | null>;
|
|
@@ -152,10 +170,13 @@ export declare abstract class MongoBucketBatch extends BaseObserver<storage.Buck
|
|
|
152
170
|
* Drop is equivalent to TRUNCATE, plus removing our record of the table.
|
|
153
171
|
*/
|
|
154
172
|
drop(sourceTables: storage.SourceTable[]): Promise<storage.FlushedResult | null>;
|
|
173
|
+
protected dropInternal(sourceTables: storage.SourceTable[]): Promise<storage.FlushedResult | null>;
|
|
155
174
|
truncate(sourceTables: storage.SourceTable[]): Promise<storage.FlushedResult | null>;
|
|
175
|
+
protected truncateInternal(sourceTables: storage.SourceTable[]): Promise<storage.FlushedResult | null>;
|
|
156
176
|
truncateSingle(sourceTable: storage.SourceTable): Promise<InternalOpId>;
|
|
177
|
+
protected abstract truncateSingleInternal(sourceTable: storage.SourceTable): Promise<InternalOpId>;
|
|
157
178
|
updateTableProgress(table: storage.SourceTable, progress: Partial<storage.TableSnapshotStatus>): Promise<storage.SourceTable>;
|
|
158
|
-
|
|
179
|
+
private updateTableProgressInternal;
|
|
159
180
|
/**
|
|
160
181
|
* Gets relevant {@link HydratedEventDescriptor}s for the given {@link SourceTable}
|
|
161
182
|
*/
|