@powersync/service-module-mongodb-storage 0.0.0-dev-20260313100403 → 0.0.0-dev-20260515144844
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 +96 -8
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +1 -1
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +3 -3
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1770213298299-storage-version.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +5 -3
- package/dist/storage/MongoBucketStorage.js +50 -36
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/MongoReportStorage.d.ts +3 -3
- package/dist/storage/MongoReportStorage.js +5 -5
- package/dist/storage/MongoReportStorage.js.map +1 -1
- package/dist/storage/implementation/BucketDefinitionMapping.d.ts +17 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js +58 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
- package/dist/storage/implementation/MongoBucketBatch.d.ts +16 -14
- package/dist/storage/implementation/MongoBucketBatch.js +80 -115
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatchShared.d.ts +5 -0
- package/dist/storage/implementation/MongoBucketBatchShared.js +8 -0
- package/dist/storage/implementation/MongoBucketBatchShared.js.map +1 -0
- package/dist/storage/implementation/MongoChecksums.d.ts +28 -17
- package/dist/storage/implementation/MongoChecksums.js +13 -72
- package/dist/storage/implementation/MongoChecksums.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +98 -52
- package/dist/storage/implementation/MongoCompactor.js +256 -295
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +11 -6
- package/dist/storage/implementation/MongoParameterCompactor.js +24 -9
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +14 -0
- package/dist/storage/implementation/MongoPersistedSyncRules.js +64 -0
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +3 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +9 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/implementation/MongoStorageProvider.js +1 -1
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +49 -30
- package/dist/storage/implementation/MongoSyncBucketStorage.js +100 -456
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +5 -3
- package/dist/storage/implementation/MongoSyncRulesLock.js +12 -10
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/OperationBatch.js +1 -1
- package/dist/storage/implementation/common/BucketDataDoc.d.ts +35 -0
- package/dist/storage/implementation/common/BucketDataDoc.js +2 -0
- package/dist/storage/implementation/common/BucketDataDoc.js.map +1 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +13 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +2 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +108 -0
- package/dist/storage/implementation/common/PersistedBatch.js +237 -0
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -0
- package/dist/storage/implementation/common/SingleBucketStore.d.ts +54 -0
- package/dist/storage/implementation/common/SingleBucketStore.js +3 -0
- package/dist/storage/implementation/common/SingleBucketStore.js.map +1 -0
- package/dist/storage/implementation/common/SourceRecordStore.d.ts +36 -0
- package/dist/storage/implementation/common/SourceRecordStore.js +2 -0
- package/dist/storage/implementation/common/SourceRecordStore.js.map +1 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +27 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +57 -0
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +7 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.js +9 -0
- package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -0
- package/dist/storage/implementation/db.d.ts +34 -34
- package/dist/storage/implementation/db.js +78 -98
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +65 -36
- package/dist/storage/implementation/models.js +21 -2
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +13 -0
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +22 -0
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.d.ts +12 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.js +56 -0
- package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +23 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.js +52 -0
- package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.d.ts +9 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js +20 -0
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js.map +1 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +41 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +283 -0
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +26 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.js +183 -0
- package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +18 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js +57 -0
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +19 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js +105 -0
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +12 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +20 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -0
- package/dist/storage/implementation/v1/models.d.ts +34 -0
- package/dist/storage/implementation/v1/models.js +37 -0
- package/dist/storage/implementation/v1/models.js.map +1 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +13 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +34 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +15 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.js +84 -0
- package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +23 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js +68 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +9 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +18 -0
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +5 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js +9 -0
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +1 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +41 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +407 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +29 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.js +259 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +18 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js +48 -0
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +1 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +22 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +164 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +21 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +71 -0
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -0
- package/dist/storage/implementation/v3/models.d.ts +43 -0
- package/dist/storage/implementation/v3/models.js +34 -0
- package/dist/storage/implementation/v3/models.js.map +1 -0
- package/dist/storage/storage-index.d.ts +8 -5
- package/dist/storage/storage-index.js +8 -5
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/utils/util.d.ts +11 -4
- package/dist/utils/util.js +25 -4
- package/dist/utils/util.js.map +1 -1
- package/package.json +9 -9
- package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +1 -1
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -7
- package/src/migrations/db/migrations/1770213298299-storage-version.ts +1 -1
- package/src/storage/MongoBucketStorage.ts +97 -62
- package/src/storage/MongoReportStorage.ts +7 -7
- package/src/storage/implementation/BucketDefinitionMapping.ts +72 -0
- package/src/storage/implementation/MongoBucketBatch.ts +110 -144
- package/src/storage/implementation/MongoBucketBatchShared.ts +11 -0
- package/src/storage/implementation/MongoChecksums.ts +53 -76
- package/src/storage/implementation/MongoCompactor.ts +401 -403
- package/src/storage/implementation/MongoParameterCompactor.ts +51 -25
- package/src/storage/implementation/MongoPersistedSyncRules.ts +76 -0
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +18 -1
- package/src/storage/implementation/MongoStorageProvider.ts +1 -1
- package/src/storage/implementation/MongoSyncBucketStorage.ts +190 -457
- package/src/storage/implementation/MongoSyncRulesLock.ts +12 -14
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +4 -2
- package/src/storage/implementation/OperationBatch.ts +1 -1
- package/src/storage/implementation/common/BucketDataDoc.ts +37 -0
- package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +15 -0
- package/src/storage/implementation/common/PersistedBatch.ts +364 -0
- package/src/storage/implementation/common/SingleBucketStore.ts +63 -0
- package/src/storage/implementation/common/SourceRecordStore.ts +49 -0
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +80 -0
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +25 -0
- package/src/storage/implementation/db.ts +107 -128
- package/src/storage/implementation/models.ts +86 -40
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +32 -0
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +75 -0
- package/src/storage/implementation/v1/MongoCompactorV1.ts +93 -0
- package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +26 -0
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +448 -0
- package/src/storage/implementation/v1/PersistedBatchV1.ts +230 -0
- package/src/storage/implementation/v1/SingleBucketStoreV1.ts +74 -0
- package/src/storage/implementation/v1/SourceRecordStoreV1.ts +156 -0
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +28 -0
- package/src/storage/implementation/v1/models.ts +84 -0
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +44 -0
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +120 -0
- package/src/storage/implementation/v3/MongoCompactorV3.ts +107 -0
- package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +24 -0
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +12 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +550 -0
- package/src/storage/implementation/v3/PersistedBatchV3.ts +318 -0
- package/src/storage/implementation/v3/SingleBucketStoreV3.ts +68 -0
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +226 -0
- package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +112 -0
- package/src/storage/implementation/v3/models.ts +96 -0
- package/src/storage/storage-index.ts +8 -5
- package/src/utils/util.ts +36 -7
- package/test/src/__snapshots__/{client-connections-storage.test.ts.snap → connection-report-storage.test.ts.snap} +68 -68
- package/test/src/__snapshots__/storage_sync.test.ts.snap +282 -0
- package/test/src/{client-connections-storage.test.ts → connection-report-storage.test.ts} +4 -4
- package/test/src/setup.ts +1 -1
- package/test/src/storage.test.ts +2 -2
- package/test/src/storage_compacting.test.ts +94 -3
- package/test/src/storage_sync.test.ts +351 -5
- package/test/tsconfig.json +0 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/implementation/PersistedBatch.d.ts +0 -71
- package/dist/storage/implementation/PersistedBatch.js +0 -354
- package/dist/storage/implementation/PersistedBatch.js.map +0 -1
- package/src/storage/implementation/PersistedBatch.ts +0 -432
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { HydratedSyncRules, SqlEventDescriptor } from '@powersync/service-sync-rules';
|
|
3
3
|
import { BaseObserver, Logger } from '@powersync/lib-services-framework';
|
|
4
|
-
import { BucketStorageMarkRecordUnavailable, CheckpointResult, InternalOpId, storage } from '@powersync/service-core';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export declare const MAX_ROW_SIZE: number;
|
|
11
|
-
export declare const EMPTY_DATA: mongo.Binary;
|
|
4
|
+
import { BucketStorageMarkRecordUnavailable, CheckpointResult, InternalOpId, PerformanceTracer, storage } from '@powersync/service-core';
|
|
5
|
+
import { BucketDefinitionMapping } from './BucketDefinitionMapping.js';
|
|
6
|
+
import { PersistedBatch } from './common/PersistedBatch.js';
|
|
7
|
+
import { SourceRecordStore } from './common/SourceRecordStore.js';
|
|
8
|
+
import type { VersionedPowerSyncMongo } from './db.js';
|
|
12
9
|
export interface MongoBucketBatchOptions {
|
|
13
10
|
db: VersionedPowerSyncMongo;
|
|
14
11
|
syncRules: HydratedSyncRules;
|
|
@@ -18,27 +15,31 @@ export interface MongoBucketBatchOptions {
|
|
|
18
15
|
keepaliveOp: InternalOpId | null;
|
|
19
16
|
resumeFromLsn: string | null;
|
|
20
17
|
storeCurrentData: boolean;
|
|
18
|
+
mapping: BucketDefinitionMapping;
|
|
21
19
|
/**
|
|
22
20
|
* Set to true for initial replication.
|
|
23
21
|
*/
|
|
24
22
|
skipExistingRows: boolean;
|
|
25
23
|
markRecordUnavailable: BucketStorageMarkRecordUnavailable | undefined;
|
|
26
|
-
logger
|
|
24
|
+
logger: Logger;
|
|
25
|
+
tracer?: PerformanceTracer<'storage' | 'evaluate'>;
|
|
27
26
|
}
|
|
28
|
-
export declare class MongoBucketBatch extends BaseObserver<storage.BucketBatchStorageListener> implements storage.BucketStorageBatch {
|
|
29
|
-
|
|
27
|
+
export declare abstract class MongoBucketBatch extends BaseObserver<storage.BucketBatchStorageListener> implements storage.BucketStorageBatch {
|
|
28
|
+
protected logger: Logger;
|
|
30
29
|
private readonly client;
|
|
31
30
|
readonly db: VersionedPowerSyncMongo;
|
|
32
31
|
readonly session: mongo.ClientSession;
|
|
33
32
|
private readonly sync_rules;
|
|
34
|
-
|
|
33
|
+
protected readonly group_id: number;
|
|
35
34
|
private readonly slot_name;
|
|
36
35
|
private readonly storeCurrentData;
|
|
37
36
|
private readonly skipExistingRows;
|
|
37
|
+
protected readonly mapping: BucketDefinitionMapping;
|
|
38
38
|
private batch;
|
|
39
39
|
private write_checkpoint_batch;
|
|
40
40
|
private markRecordUnavailable;
|
|
41
41
|
private clearedError;
|
|
42
|
+
private tracer;
|
|
42
43
|
/**
|
|
43
44
|
* Last LSN received associated with a checkpoint.
|
|
44
45
|
*
|
|
@@ -67,6 +68,9 @@ export declare class MongoBucketBatch extends BaseObserver<storage.BucketBatchSt
|
|
|
67
68
|
constructor(options: MongoBucketBatchOptions);
|
|
68
69
|
addCustomWriteCheckpoint(checkpoint: storage.BatchedCustomWriteCheckpointOptions): void;
|
|
69
70
|
get lastCheckpointLsn(): string | null;
|
|
71
|
+
protected abstract createPersistedBatch(writtenSize: number): PersistedBatch;
|
|
72
|
+
protected abstract get sourceRecordStore(): SourceRecordStore;
|
|
73
|
+
protected abstract cleanupDroppedSourceTables(sourceTables: storage.SourceTable[]): Promise<void>;
|
|
70
74
|
flush(options?: storage.BatchBucketFlushOptions): Promise<storage.FlushedResult | null>;
|
|
71
75
|
private flushInner;
|
|
72
76
|
private replicateBatch;
|
|
@@ -77,7 +81,6 @@ export declare class MongoBucketBatch extends BaseObserver<storage.BucketBatchSt
|
|
|
77
81
|
dispose(): Promise<void>;
|
|
78
82
|
private lastWaitingLogThottled;
|
|
79
83
|
commit(lsn: string, options?: storage.BucketBatchCommitOptions): Promise<CheckpointResult>;
|
|
80
|
-
private cleanupCurrentData;
|
|
81
84
|
/**
|
|
82
85
|
* Switch from processing -> active if relevant.
|
|
83
86
|
*
|
|
@@ -103,4 +106,3 @@ export declare class MongoBucketBatch extends BaseObserver<storage.BucketBatchSt
|
|
|
103
106
|
*/
|
|
104
107
|
protected getTableEvents(table: storage.SourceTable): SqlEventDescriptor[];
|
|
105
108
|
}
|
|
106
|
-
export declare function currentBucketKey(b: CurrentBucket): string;
|
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import * as bson from 'bson';
|
|
3
|
-
import { BaseObserver, container,
|
|
4
|
-
import { deserializeBson, isCompleteRow, SaveOperationTag, storage, SyncRuleState, utils } from '@powersync/service-core';
|
|
3
|
+
import { BaseObserver, container, ErrorCode, errors, ReplicationAssertionError, ServiceError } from '@powersync/lib-services-framework';
|
|
4
|
+
import { deserializeBson, isCompleteRow, PerformanceTracer, SaveOperationTag, storage, SyncRuleState, utils } from '@powersync/service-core';
|
|
5
5
|
import * as timers from 'node:timers/promises';
|
|
6
|
-
import {
|
|
6
|
+
import { mongoTableId } from '../../utils/util.js';
|
|
7
|
+
import { MAX_ROW_SIZE } from './MongoBucketBatchShared.js';
|
|
7
8
|
import { MongoIdSequence } from './MongoIdSequence.js';
|
|
8
9
|
import { batchCreateCustomWriteCheckpoints } from './MongoWriteCheckpointAPI.js';
|
|
9
|
-
import {
|
|
10
|
-
import { PersistedBatch } from './PersistedBatch.js';
|
|
11
|
-
/**
|
|
12
|
-
* 15MB
|
|
13
|
-
*/
|
|
14
|
-
export const MAX_ROW_SIZE = 15 * 1024 * 1024;
|
|
10
|
+
import { OperationBatch, RecordOperation } from './OperationBatch.js';
|
|
15
11
|
// Currently, we can only have a single flush() at a time, since it locks the op_id sequence.
|
|
16
12
|
// While the MongoDB transaction retry mechanism handles this okay, using an in-process Mutex
|
|
17
13
|
// makes it more fair and has less overhead.
|
|
18
14
|
//
|
|
19
15
|
// In the future, we can investigate allowing multiple replication streams operating independently.
|
|
20
16
|
const replicationMutex = new utils.Mutex();
|
|
21
|
-
export const EMPTY_DATA = new bson.Binary(bson.serialize({}));
|
|
22
17
|
export class MongoBucketBatch extends BaseObserver {
|
|
23
18
|
logger;
|
|
24
19
|
client;
|
|
@@ -29,10 +24,12 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
29
24
|
slot_name;
|
|
30
25
|
storeCurrentData;
|
|
31
26
|
skipExistingRows;
|
|
27
|
+
mapping;
|
|
32
28
|
batch = null;
|
|
33
29
|
write_checkpoint_batch = [];
|
|
34
30
|
markRecordUnavailable;
|
|
35
31
|
clearedError = false;
|
|
32
|
+
tracer;
|
|
36
33
|
/**
|
|
37
34
|
* Last LSN received associated with a checkpoint.
|
|
38
35
|
*
|
|
@@ -60,7 +57,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
60
57
|
needsActivation = true;
|
|
61
58
|
constructor(options) {
|
|
62
59
|
super();
|
|
63
|
-
this.logger = options.logger
|
|
60
|
+
this.logger = options.logger;
|
|
64
61
|
this.client = options.db.client;
|
|
65
62
|
this.db = options.db;
|
|
66
63
|
this.group_id = options.groupId;
|
|
@@ -70,10 +67,12 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
70
67
|
this.slot_name = options.slotName;
|
|
71
68
|
this.sync_rules = options.syncRules;
|
|
72
69
|
this.storeCurrentData = options.storeCurrentData;
|
|
70
|
+
this.mapping = options.mapping;
|
|
73
71
|
this.skipExistingRows = options.skipExistingRows;
|
|
74
72
|
this.markRecordUnavailable = options.markRecordUnavailable;
|
|
75
73
|
this.batch = new OperationBatch();
|
|
76
74
|
this.persisted_op = options.keepaliveOp ?? null;
|
|
75
|
+
this.tracer = options.tracer ?? new PerformanceTracer('MongoDB storage');
|
|
77
76
|
}
|
|
78
77
|
addCustomWriteCheckpoint(checkpoint) {
|
|
79
78
|
this.write_checkpoint_batch.push({
|
|
@@ -100,6 +99,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
100
99
|
const batch = this.batch;
|
|
101
100
|
let last_op = null;
|
|
102
101
|
let resumeBatch = null;
|
|
102
|
+
using _ = this.tracer.span('storage', 'flush');
|
|
103
103
|
await this.withReplicationTransaction(`Flushing ${batch?.length ?? 0} ops`, async (session, opSeq) => {
|
|
104
104
|
if (batch != null) {
|
|
105
105
|
resumeBatch = await this.replicateBatch(session, batch, opSeq, options);
|
|
@@ -122,6 +122,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
122
122
|
}
|
|
123
123
|
async replicateBatch(session, batch, op_seq, options) {
|
|
124
124
|
let sizes = undefined;
|
|
125
|
+
using _ = this.tracer.span('storage', 'replicate_batch');
|
|
125
126
|
if (this.storeCurrentData && !this.skipExistingRows) {
|
|
126
127
|
// We skip this step if we don't store current_data, since the sizes will
|
|
127
128
|
// always be small in that case.
|
|
@@ -134,27 +135,11 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
134
135
|
// (automatically limited to 48MB(?) per batch by MongoDB). The issue is that it changes
|
|
135
136
|
// the order of processing, which then becomes really tricky to manage.
|
|
136
137
|
// This now takes 2+ queries, but doesn't have any issues with order of operations.
|
|
137
|
-
const sizeLookups = batch.batch.map((r) => {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
{
|
|
143
|
-
$match: {
|
|
144
|
-
_id: { $in: sizeLookups }
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
$project: {
|
|
149
|
-
_id: 1,
|
|
150
|
-
size: { $bsonSize: '$$ROOT' }
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
], { session });
|
|
154
|
-
for await (let doc of sizeCursor.stream()) {
|
|
155
|
-
const key = cacheKey(doc._id.t, doc._id.k);
|
|
156
|
-
sizes.set(key, doc.size);
|
|
157
|
-
}
|
|
138
|
+
const sizeLookups = batch.batch.map((r) => ({
|
|
139
|
+
sourceTableId: mongoTableId(r.record.sourceTable.id),
|
|
140
|
+
replicaId: r.beforeId
|
|
141
|
+
}));
|
|
142
|
+
sizes = await this.sourceRecordStore.loadSizes(session, sizeLookups);
|
|
158
143
|
}
|
|
159
144
|
// If set, we need to start a new transaction with this batch.
|
|
160
145
|
let resumeBatch = null;
|
|
@@ -169,40 +154,38 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
169
154
|
}
|
|
170
155
|
continue;
|
|
171
156
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
let persistedBatch = new PersistedBatch(this.db, this.group_id, transactionSize, {
|
|
185
|
-
logger: this.logger
|
|
186
|
-
});
|
|
157
|
+
using lookupSpan = this.tracer.span('storage', 'lookup');
|
|
158
|
+
const lookups = b.map((r) => ({
|
|
159
|
+
sourceTableId: mongoTableId(r.record.sourceTable.id),
|
|
160
|
+
replicaId: r.beforeId
|
|
161
|
+
}));
|
|
162
|
+
let sourceRecordLookup = await this.sourceRecordStore.loadDocuments(session, lookups, this.skipExistingRows);
|
|
163
|
+
lookupSpan.end();
|
|
164
|
+
let persistedBatch = this.createPersistedBatch(transactionSize);
|
|
165
|
+
// The current code structure makes it tricky to cleanly split this span from the one
|
|
166
|
+
// where fluhsing. So we manually end and re-create this span whenever we flush.
|
|
167
|
+
let evalSpan = this.tracer.span('evaluate');
|
|
187
168
|
for (let op of b) {
|
|
188
169
|
if (resumeBatch) {
|
|
189
170
|
resumeBatch.push(op);
|
|
190
171
|
continue;
|
|
191
172
|
}
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
173
|
+
const sourceRecord = sourceRecordLookup.get(op.internalBeforeKey) ?? null;
|
|
174
|
+
if (sourceRecord != null) {
|
|
194
175
|
// If it will be used again later, it will be set again using nextData below
|
|
195
|
-
|
|
176
|
+
sourceRecordLookup.delete(op.internalBeforeKey);
|
|
196
177
|
}
|
|
197
|
-
const nextData = this.saveOperation(persistedBatch, op,
|
|
178
|
+
const nextData = this.saveOperation(persistedBatch, op, sourceRecord, op_seq);
|
|
198
179
|
if (nextData != null) {
|
|
199
180
|
// Update our current_data and size cache
|
|
200
|
-
|
|
201
|
-
sizes?.set(op.internalAfterKey, nextData.data
|
|
181
|
+
sourceRecordLookup.set(op.internalAfterKey, nextData);
|
|
182
|
+
sizes?.set(op.internalAfterKey, nextData.data?.length() ?? 0);
|
|
202
183
|
}
|
|
203
184
|
if (persistedBatch.shouldFlushTransaction()) {
|
|
185
|
+
evalSpan.end();
|
|
204
186
|
// Transaction is getting big.
|
|
205
187
|
// Flush, and resume in a new transaction.
|
|
188
|
+
using persistSpan = this.tracer.span('storage', 'persist_flush');
|
|
206
189
|
const { flushedAny } = await persistedBatch.flush(this.session, options);
|
|
207
190
|
didFlush ||= flushedAny;
|
|
208
191
|
persistedBatch = null;
|
|
@@ -210,20 +193,25 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
210
193
|
// we're stopping in the middle of a batch.
|
|
211
194
|
// We create a new batch, and push any remaining operations to it.
|
|
212
195
|
resumeBatch = new OperationBatch();
|
|
196
|
+
persistSpan.end();
|
|
197
|
+
evalSpan = this.tracer.span('evaluate');
|
|
213
198
|
}
|
|
214
199
|
}
|
|
200
|
+
evalSpan.end();
|
|
215
201
|
if (persistedBatch) {
|
|
216
202
|
transactionSize = persistedBatch.currentSize;
|
|
203
|
+
using _ = this.tracer.span('storage', 'persist_flush');
|
|
217
204
|
const { flushedAny } = await persistedBatch.flush(this.session, options);
|
|
218
205
|
didFlush ||= flushedAny;
|
|
219
206
|
}
|
|
220
207
|
}
|
|
221
208
|
if (didFlush) {
|
|
209
|
+
using _ = this.tracer.span('storage', 'clear_error');
|
|
222
210
|
await this.clearError();
|
|
223
211
|
}
|
|
224
212
|
return resumeBatch?.hasData() ? resumeBatch : null;
|
|
225
213
|
}
|
|
226
|
-
saveOperation(batch, operation,
|
|
214
|
+
saveOperation(batch, operation, sourceRecord, opSeq) {
|
|
227
215
|
const record = operation.record;
|
|
228
216
|
const beforeId = operation.beforeId;
|
|
229
217
|
const afterId = operation.afterId;
|
|
@@ -233,10 +221,10 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
233
221
|
let new_buckets = [];
|
|
234
222
|
let existing_lookups = [];
|
|
235
223
|
let new_lookups = [];
|
|
236
|
-
const
|
|
224
|
+
const sourceTableId = mongoTableId(record.sourceTable.id);
|
|
237
225
|
if (this.skipExistingRows) {
|
|
238
226
|
if (record.tag == SaveOperationTag.INSERT) {
|
|
239
|
-
if (
|
|
227
|
+
if (sourceRecord != null) {
|
|
240
228
|
// Initial replication, and we already have the record.
|
|
241
229
|
// This may be a different version of the record, but streaming replication
|
|
242
230
|
// will take care of that.
|
|
@@ -249,7 +237,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
249
237
|
}
|
|
250
238
|
}
|
|
251
239
|
if (record.tag == SaveOperationTag.UPDATE) {
|
|
252
|
-
const result =
|
|
240
|
+
const result = sourceRecord;
|
|
253
241
|
if (result == null) {
|
|
254
242
|
// Not an error if we re-apply a transaction
|
|
255
243
|
existing_buckets = [];
|
|
@@ -270,14 +258,14 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
270
258
|
else {
|
|
271
259
|
existing_buckets = result.buckets;
|
|
272
260
|
existing_lookups = result.lookups;
|
|
273
|
-
if (this.storeCurrentData) {
|
|
261
|
+
if (this.storeCurrentData && result.data != null) {
|
|
274
262
|
const data = deserializeBson(result.data.buffer);
|
|
275
263
|
after = storage.mergeToast(after, data);
|
|
276
264
|
}
|
|
277
265
|
}
|
|
278
266
|
}
|
|
279
267
|
else if (record.tag == SaveOperationTag.DELETE) {
|
|
280
|
-
const result =
|
|
268
|
+
const result = sourceRecord;
|
|
281
269
|
if (result == null) {
|
|
282
270
|
// Not an error if we re-apply a transaction
|
|
283
271
|
existing_buckets = [];
|
|
@@ -292,9 +280,9 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
292
280
|
existing_lookups = result.lookups;
|
|
293
281
|
}
|
|
294
282
|
}
|
|
295
|
-
let afterData;
|
|
283
|
+
let afterData = null;
|
|
296
284
|
if (afterId != null && !this.storeCurrentData) {
|
|
297
|
-
afterData =
|
|
285
|
+
afterData = null;
|
|
298
286
|
}
|
|
299
287
|
else if (afterId != null) {
|
|
300
288
|
try {
|
|
@@ -378,13 +366,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
378
366
|
table: sourceTable,
|
|
379
367
|
before_buckets: existing_buckets
|
|
380
368
|
});
|
|
381
|
-
new_buckets =
|
|
382
|
-
return {
|
|
383
|
-
bucket: e.bucket,
|
|
384
|
-
table: e.table,
|
|
385
|
-
id: e.id
|
|
386
|
-
};
|
|
387
|
-
});
|
|
369
|
+
new_buckets = this.sourceRecordStore.mapEvaluatedBuckets(evaluated);
|
|
388
370
|
}
|
|
389
371
|
if (sourceTable.syncParameters) {
|
|
390
372
|
// Parameters
|
|
@@ -406,26 +388,27 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
406
388
|
evaluated: paramEvaluated,
|
|
407
389
|
existing_lookups
|
|
408
390
|
});
|
|
409
|
-
new_lookups =
|
|
410
|
-
return storage.serializeLookup(p.lookup);
|
|
411
|
-
});
|
|
391
|
+
new_lookups = this.sourceRecordStore.mapParameterLookups(paramEvaluated);
|
|
412
392
|
}
|
|
413
393
|
}
|
|
414
394
|
let result = null;
|
|
415
395
|
// 5. TOAST: Update current data and bucket list.
|
|
416
396
|
if (afterId) {
|
|
417
397
|
// Insert or update
|
|
418
|
-
|
|
419
|
-
|
|
398
|
+
batch.upsertCurrentData({
|
|
399
|
+
sourceTableId,
|
|
400
|
+
replicaId: afterId,
|
|
420
401
|
data: afterData,
|
|
421
402
|
buckets: new_buckets,
|
|
422
403
|
lookups: new_lookups
|
|
423
404
|
});
|
|
424
405
|
result = {
|
|
425
|
-
|
|
406
|
+
sourceTableId,
|
|
407
|
+
replicaId: afterId,
|
|
426
408
|
data: afterData,
|
|
427
409
|
buckets: new_buckets,
|
|
428
|
-
lookups: new_lookups
|
|
410
|
+
lookups: new_lookups,
|
|
411
|
+
cacheKey: operation.internalAfterKey
|
|
429
412
|
};
|
|
430
413
|
}
|
|
431
414
|
if (afterId == null || !storage.replicaIdEquals(beforeId, afterId)) {
|
|
@@ -433,12 +416,14 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
433
416
|
// Note that this is a soft delete.
|
|
434
417
|
// We don't specifically need a new or unique op_id here, but it must be greater than the
|
|
435
418
|
// last checkpoint, so we use next().
|
|
436
|
-
batch.softDeleteCurrentData(
|
|
419
|
+
batch.softDeleteCurrentData(sourceTableId, beforeId, opSeq.next());
|
|
437
420
|
}
|
|
438
421
|
return result;
|
|
439
422
|
}
|
|
440
423
|
async withTransaction(cb) {
|
|
424
|
+
using lockSpan = this.tracer.span('storage', 'internal_lock');
|
|
441
425
|
await replicationMutex.exclusiveLock(async () => {
|
|
426
|
+
lockSpan.end();
|
|
442
427
|
await this.session.withTransaction(async () => {
|
|
443
428
|
try {
|
|
444
429
|
await cb();
|
|
@@ -450,7 +435,9 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
450
435
|
else {
|
|
451
436
|
this.logger.warn('Transaction error', e);
|
|
452
437
|
}
|
|
453
|
-
|
|
438
|
+
const delay = Math.random() * 50;
|
|
439
|
+
using _ = this.tracer.span('storage', 'retry_delay');
|
|
440
|
+
await timers.setTimeout(delay);
|
|
454
441
|
throw e;
|
|
455
442
|
}
|
|
456
443
|
}, { maxCommitTimeMS: 10000 });
|
|
@@ -656,21 +643,12 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
656
643
|
await this.db.notifyCheckpoint();
|
|
657
644
|
this.persisted_op = null;
|
|
658
645
|
this.last_checkpoint_lsn = lsn;
|
|
659
|
-
if (
|
|
660
|
-
await this.
|
|
646
|
+
if (newLastCheckpoint != null) {
|
|
647
|
+
await this.sourceRecordStore.postCommitCleanup(newLastCheckpoint, this.logger);
|
|
661
648
|
}
|
|
662
649
|
}
|
|
663
650
|
return { checkpointBlocked, checkpointCreated };
|
|
664
651
|
}
|
|
665
|
-
async cleanupCurrentData(lastCheckpoint) {
|
|
666
|
-
const result = await this.db.v3_current_data.deleteMany({
|
|
667
|
-
'_id.g': this.group_id,
|
|
668
|
-
pending_delete: { $exists: true, $lte: lastCheckpoint }
|
|
669
|
-
});
|
|
670
|
-
if (result.deletedCount > 0) {
|
|
671
|
-
this.logger.info(`Cleaned up ${result.deletedCount} pending delete current_data records for checkpoint ${lastCheckpoint}`);
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
652
|
/**
|
|
675
653
|
* Switch from processing -> active if relevant.
|
|
676
654
|
*
|
|
@@ -709,7 +687,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
709
687
|
}
|
|
710
688
|
});
|
|
711
689
|
if (activated) {
|
|
712
|
-
this.logger.info(`Activated new
|
|
690
|
+
this.logger.info(`Activated new replication stream at ${lsn}`);
|
|
713
691
|
await this.db.notifyCheckpoint();
|
|
714
692
|
this.needsActivation = false;
|
|
715
693
|
}
|
|
@@ -766,9 +744,10 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
766
744
|
const result = await this.flush();
|
|
767
745
|
await this.withTransaction(async () => {
|
|
768
746
|
for (let table of sourceTables) {
|
|
769
|
-
await this.db.
|
|
747
|
+
await this.db.commonSourceTables(this.group_id).deleteOne({ _id: mongoTableId(table.id) });
|
|
770
748
|
}
|
|
771
749
|
});
|
|
750
|
+
await this.cleanupDroppedSourceTables(sourceTables);
|
|
772
751
|
return result;
|
|
773
752
|
}
|
|
774
753
|
async truncate(sourceTables) {
|
|
@@ -795,41 +774,30 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
795
774
|
let lastBatchCount = BATCH_LIMIT;
|
|
796
775
|
while (lastBatchCount == BATCH_LIMIT) {
|
|
797
776
|
await this.withReplicationTransaction(`Truncate ${sourceTable.qualifiedName}`, async (session, opSeq) => {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
pending_delete: { $exists: false }
|
|
803
|
-
};
|
|
804
|
-
const cursor = this.db.common_current_data.find(current_data_filter, {
|
|
805
|
-
projection: {
|
|
806
|
-
_id: 1,
|
|
807
|
-
buckets: 1,
|
|
808
|
-
lookups: 1
|
|
809
|
-
},
|
|
810
|
-
limit: BATCH_LIMIT,
|
|
811
|
-
session: session
|
|
812
|
-
});
|
|
813
|
-
const batch = await cursor.toArray();
|
|
814
|
-
const persistedBatch = new PersistedBatch(this.db, this.group_id, 0, { logger: this.logger });
|
|
777
|
+
using evalSpan = this.tracer.span('evaluate');
|
|
778
|
+
const sourceTableId = mongoTableId(sourceTable.id);
|
|
779
|
+
const batch = await this.sourceRecordStore.loadTruncateBatch(session, sourceTableId, BATCH_LIMIT);
|
|
780
|
+
const persistedBatch = this.createPersistedBatch(0);
|
|
815
781
|
for (let value of batch) {
|
|
816
782
|
persistedBatch.saveBucketData({
|
|
817
783
|
op_seq: opSeq,
|
|
818
784
|
before_buckets: value.buckets,
|
|
819
785
|
evaluated: [],
|
|
820
786
|
table: sourceTable,
|
|
821
|
-
sourceKey: value.
|
|
787
|
+
sourceKey: value.replicaId
|
|
822
788
|
});
|
|
823
789
|
persistedBatch.saveParameterData({
|
|
824
790
|
op_seq: opSeq,
|
|
825
791
|
existing_lookups: value.lookups,
|
|
826
792
|
evaluated: [],
|
|
827
793
|
sourceTable: sourceTable,
|
|
828
|
-
sourceKey: value.
|
|
794
|
+
sourceKey: value.replicaId
|
|
829
795
|
});
|
|
830
796
|
// Since this is not from streaming replication, we can do a hard delete
|
|
831
|
-
persistedBatch.hardDeleteCurrentData(value.
|
|
797
|
+
persistedBatch.hardDeleteCurrentData(sourceTableId, value.replicaId);
|
|
832
798
|
}
|
|
799
|
+
evalSpan.end();
|
|
800
|
+
using _ = this.tracer.span('storage', 'persist_flush');
|
|
833
801
|
await persistedBatch.flush(session);
|
|
834
802
|
lastBatchCount = batch.length;
|
|
835
803
|
last_op = opSeq.last();
|
|
@@ -846,7 +814,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
846
814
|
};
|
|
847
815
|
copy.snapshotStatus = snapshotStatus;
|
|
848
816
|
await this.withTransaction(async () => {
|
|
849
|
-
await this.db.
|
|
817
|
+
await this.db.commonSourceTables(this.group_id).updateOne({ _id: mongoTableId(table.id) }, {
|
|
850
818
|
$set: {
|
|
851
819
|
snapshot_status: {
|
|
852
820
|
last_key: snapshotStatus.lastKey == null ? null : new bson.Binary(snapshotStatus.lastKey),
|
|
@@ -884,7 +852,7 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
884
852
|
const session = this.session;
|
|
885
853
|
const ids = tables.map((table) => mongoTableId(table.id));
|
|
886
854
|
await this.withTransaction(async () => {
|
|
887
|
-
await this.db.
|
|
855
|
+
await this.db.commonSourceTables(this.group_id).updateMany({ _id: { $in: ids } }, {
|
|
888
856
|
$set: {
|
|
889
857
|
snapshot_done: true
|
|
890
858
|
},
|
|
@@ -933,7 +901,4 @@ export class MongoBucketBatch extends BaseObserver {
|
|
|
933
901
|
return this.sync_rules.eventDescriptors.filter((evt) => [...evt.getSourceTables()].some((sourceTable) => sourceTable.matches(table)));
|
|
934
902
|
}
|
|
935
903
|
}
|
|
936
|
-
export function currentBucketKey(b) {
|
|
937
|
-
return `${b.bucket}/${b.table}/${b.id}`;
|
|
938
|
-
}
|
|
939
904
|
//# sourceMappingURL=MongoBucketBatch.js.map
|