@powersync/service-module-mongodb-storage 0.16.0 → 0.18.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 +53 -0
- package/dist/storage/MongoBucketStorage.d.ts +35 -15
- package/dist/storage/MongoBucketStorage.js +309 -86
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/CheckpointState.d.ts +20 -0
- package/dist/storage/implementation/CheckpointState.js +31 -0
- package/dist/storage/implementation/CheckpointState.js.map +1 -0
- package/dist/storage/implementation/MongoBucketBatch.d.ts +69 -39
- package/dist/storage/implementation/MongoBucketBatch.js +104 -313
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoChecksums.d.ts +11 -9
- package/dist/storage/implementation/MongoChecksums.js +3 -111
- package/dist/storage/implementation/MongoChecksums.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +3 -1
- package/dist/storage/implementation/MongoCompactor.js +18 -9
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoHydrationState.d.ts +11 -0
- package/dist/storage/implementation/MongoHydrationState.js +49 -0
- package/dist/storage/implementation/MongoHydrationState.js.map +1 -0
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +6 -5
- package/dist/storage/implementation/MongoParameterCompactor.js +24 -1
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParsedSyncConfigSet.d.ts +13 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js +64 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.d.ts +36 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.js +90 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.d.ts +25 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.js +121 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.js.map +1 -0
- package/dist/storage/implementation/MongoStorageProvider.js +5 -2
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +50 -21
- package/dist/storage/implementation/MongoSyncBucketStorage.js +62 -199
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +5 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js +9 -5
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/SyncRuleStateUpdate.d.ts +14 -0
- package/dist/storage/implementation/SyncRuleStateUpdate.js +36 -0
- package/dist/storage/implementation/SyncRuleStateUpdate.js.map +1 -0
- package/dist/storage/implementation/common/BucketDataDoc.d.ts +1 -1
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.d.ts +6 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.js +2 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +2 -3
- package/dist/storage/implementation/common/PersistedBatch.js +5 -0
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/common/SourceRecordStore.d.ts +1 -2
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.d.ts +1 -1
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +1 -1
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -1
- package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +2 -2
- package/dist/storage/implementation/createMongoSyncBucketStorage.js +4 -4
- package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/db.d.ts +10 -2
- package/dist/storage/implementation/db.js +9 -14
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +25 -50
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +23 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +403 -2
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoChecksumsV1.js +114 -3
- package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +1 -1
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +22 -15
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +100 -27
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -1
- package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +1 -2
- package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +2 -1
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +3 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -1
- package/dist/storage/implementation/v1/models.d.ts +21 -1
- package/dist/storage/implementation/v1/models.js.map +1 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +21 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +459 -3
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +27 -7
- package/dist/storage/implementation/v3/MongoChecksumsV3.js +202 -18
- package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +20 -3
- package/dist/storage/implementation/v3/MongoCompactorV3.js +511 -22
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.d.ts +62 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js +350 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js.map +1 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +50 -16
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +292 -75
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +2 -3
- package/dist/storage/implementation/v3/PersistedBatchV3.js +43 -20
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js +52 -16
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +1 -1
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +3 -3
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +13 -11
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -1
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +16 -14
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +32 -27
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -1
- package/dist/storage/implementation/v3/bucket-format.d.ts +4 -0
- package/dist/storage/implementation/v3/bucket-format.js +58 -0
- package/dist/storage/implementation/v3/bucket-format.js.map +1 -0
- package/dist/storage/implementation/v3/chunking.d.ts +10 -0
- package/dist/storage/implementation/v3/chunking.js +28 -0
- package/dist/storage/implementation/v3/chunking.js.map +1 -0
- package/dist/storage/implementation/v3/models.d.ts +111 -10
- package/dist/storage/implementation/v3/models.js +11 -28
- package/dist/storage/implementation/v3/models.js.map +1 -1
- package/dist/storage/implementation/v3/source-table-utils.d.ts +55 -0
- package/dist/storage/implementation/v3/source-table-utils.js +214 -0
- package/dist/storage/implementation/v3/source-table-utils.js.map +1 -0
- package/dist/storage/storage-index.d.ts +4 -4
- package/dist/storage/storage-index.js +4 -4
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/types/types.d.ts +2 -2
- package/dist/utils/test-utils.d.ts +1 -2
- package/dist/utils/test-utils.js +5 -1
- package/dist/utils/test-utils.js.map +1 -1
- package/dist/utils/util.d.ts +1 -1
- package/dist/utils/util.js +3 -2
- package/dist/utils/util.js.map +1 -1
- package/package.json +9 -19
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +1 -1
- package/src/storage/MongoBucketStorage.ts +464 -95
- package/src/storage/implementation/CheckpointState.ts +59 -0
- package/src/storage/implementation/MongoBucketBatch.ts +159 -405
- package/src/storage/implementation/MongoChecksums.ts +7 -138
- package/src/storage/implementation/MongoCompactor.ts +20 -10
- package/src/storage/implementation/MongoHydrationState.ts +61 -0
- package/src/storage/implementation/MongoParameterCompactor.ts +24 -5
- package/src/storage/implementation/MongoParsedSyncConfigSet.ts +88 -0
- package/src/storage/implementation/MongoPersistedReplicationStream.ts +118 -0
- package/src/storage/implementation/MongoPersistedSyncConfigContent.ts +152 -0
- package/src/storage/implementation/MongoStorageProvider.ts +5 -2
- package/src/storage/implementation/MongoSyncBucketStorage.ts +89 -250
- package/src/storage/implementation/MongoSyncRulesLock.ts +14 -5
- package/src/storage/implementation/SyncRuleStateUpdate.ts +38 -0
- package/src/storage/implementation/common/BucketDataDoc.ts +1 -1
- package/src/storage/implementation/common/MongoSyncBucketStorageCheckpoint.ts +7 -0
- package/src/storage/implementation/common/PersistedBatch.ts +8 -4
- package/src/storage/implementation/common/SourceRecordStore.ts +1 -2
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +1 -1
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +21 -7
- package/src/storage/implementation/db.ts +16 -21
- package/src/storage/implementation/models.ts +28 -61
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +503 -5
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +137 -4
- package/src/storage/implementation/v1/MongoCompactorV1.ts +1 -1
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +150 -49
- package/src/storage/implementation/v1/PersistedBatchV1.ts +1 -2
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +11 -1
- package/src/storage/implementation/v1/models.ts +25 -0
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +611 -4
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +262 -26
- package/src/storage/implementation/v3/MongoCompactorV3.ts +647 -30
- package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +480 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +397 -111
- package/src/storage/implementation/v3/PersistedBatchV3.ts +63 -38
- package/src/storage/implementation/v3/SingleBucketStoreV3.ts +59 -19
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +12 -12
- package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +48 -38
- package/src/storage/implementation/v3/bucket-format.ts +70 -0
- package/src/storage/implementation/v3/chunking.ts +38 -0
- package/src/storage/implementation/v3/models.ts +150 -44
- package/src/storage/implementation/v3/source-table-utils.ts +392 -0
- package/src/storage/storage-index.ts +12 -4
- package/src/utils/test-utils.ts +6 -3
- package/src/utils/util.ts +3 -2
- package/test/src/__snapshots__/storage.test.ts.snap +0 -75
- package/test/src/__snapshots__/storage_sync.test.ts.snap +48 -48
- package/test/src/cleanup-stopped-sync-configs.test.ts +648 -0
- package/test/src/storage.test.ts +11 -11
- package/test/src/storage_compacting.test.ts +1956 -6
- package/test/src/storage_sync.test.ts +1429 -42
- package/test/src/storeCurrentData.test.ts +221 -0
- package/test/src/util.ts +2 -1
- package/tsconfig.json +1 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/implementation/BucketDefinitionMapping.d.ts +0 -17
- package/dist/storage/implementation/BucketDefinitionMapping.js +0 -58
- package/dist/storage/implementation/BucketDefinitionMapping.js.map +0 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +0 -14
- package/dist/storage/implementation/MongoPersistedSyncRules.js +0 -64
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +0 -1
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +0 -15
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +0 -42
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +0 -1
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +0 -13
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +0 -2
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +0 -1
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +0 -9
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +0 -18
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +0 -1
- package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +0 -5
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js +0 -9
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +0 -1
- package/src/storage/implementation/BucketDefinitionMapping.ts +0 -72
- package/src/storage/implementation/MongoPersistedSyncRules.ts +0 -76
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +0 -56
- package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +0 -15
- package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +0 -24
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +0 -12
|
@@ -1,70 +1,79 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { ReplicationAssertionError } from '@powersync/lib-services-framework';
|
|
3
3
|
import { InternalOpId, storage } from '@powersync/service-core';
|
|
4
|
-
import { BucketDataSource } from '@powersync/service-sync-rules';
|
|
4
|
+
import { BucketDataSource, BucketDefinitionId } from '@powersync/service-sync-rules';
|
|
5
5
|
import * as bson from 'bson';
|
|
6
6
|
import { mongoTableId } from '../../../utils/util.js';
|
|
7
|
-
import {
|
|
7
|
+
import { BucketDataDoc } from '../common/BucketDataDoc.js';
|
|
8
8
|
import {
|
|
9
9
|
BucketStateUpdate,
|
|
10
10
|
PersistedBatch,
|
|
11
11
|
SaveParameterDataOptions,
|
|
12
12
|
UpsertCurrentDataOptions
|
|
13
13
|
} from '../common/PersistedBatch.js';
|
|
14
|
-
import {
|
|
14
|
+
import { SourceRecordLookupState } from '../common/SourceRecordStore.js';
|
|
15
|
+
import { serializeBucketData } from './bucket-format.js';
|
|
16
|
+
import { chunkBucketData } from './chunking.js';
|
|
15
17
|
import {
|
|
16
|
-
|
|
18
|
+
BucketDataDocumentV3,
|
|
17
19
|
BucketStateDocumentV3,
|
|
18
20
|
CurrentDataDocumentV3,
|
|
19
|
-
|
|
21
|
+
serializeParameterLookup,
|
|
20
22
|
SourceTableDocumentV3,
|
|
21
|
-
|
|
23
|
+
taggedBucketParameterDocumentToTagged
|
|
22
24
|
} from './models.js';
|
|
23
|
-
import { serializeParameterLookupV3 } from './MongoParameterLookupV3.js';
|
|
24
25
|
import { VersionedPowerSyncMongoV3 } from './VersionedPowerSyncMongoV3.js';
|
|
25
26
|
|
|
26
27
|
export class PersistedBatchV3 extends PersistedBatch {
|
|
27
|
-
declare protected readonly db: VersionedPowerSyncMongoV3;
|
|
28
|
-
|
|
29
28
|
currentData: { sourceTableId: bson.ObjectId; operation: mongo.AnyBulkWriteOperation<CurrentDataDocumentV3> }[] = [];
|
|
30
29
|
sourceTablePendingDeletes = new Map<string, InternalOpId>();
|
|
31
30
|
|
|
32
|
-
protected
|
|
31
|
+
declare protected readonly db: VersionedPowerSyncMongoV3;
|
|
32
|
+
|
|
33
|
+
// Abstract override from PersistedBatch (V3-specific error message)
|
|
34
|
+
|
|
35
|
+
protected override checkDefinitionId(definitionId: BucketDefinitionId | null): BucketDefinitionId {
|
|
33
36
|
if (definitionId == null) {
|
|
34
|
-
// This is required for V3 storage.
|
|
35
37
|
throw new ReplicationAssertionError('Expected v3 bucket when incrementalReprocessing is enabled');
|
|
36
38
|
}
|
|
37
39
|
return definitionId;
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
// Concrete implementations from PersistedBatchShared
|
|
43
|
+
|
|
40
44
|
protected getBucketDefinitionId(bucketSource: BucketDataSource): BucketDefinitionId {
|
|
41
45
|
return this.mapping.bucketSourceId(bucketSource);
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
saveParameterData(data: SaveParameterDataOptions) {
|
|
45
49
|
const { sourceTable, sourceKey, evaluated } = data;
|
|
46
|
-
const remaining_lookups = new Map<string,
|
|
50
|
+
const remaining_lookups = new Map<string, SourceRecordLookupState>();
|
|
47
51
|
|
|
48
52
|
for (let lookup of data.existing_lookups) {
|
|
49
53
|
if (lookup.indexId == null) {
|
|
50
|
-
throw new ReplicationAssertionError('Expected
|
|
54
|
+
throw new ReplicationAssertionError('Expected lookup when incrementalReprocessing is enabled');
|
|
55
|
+
}
|
|
56
|
+
if (sourceTable.parameterLookupSourceIds != null && !sourceTable.parameterLookupSourceIds.has(lookup.indexId)) {
|
|
57
|
+
// The parameter index is not active anymore.
|
|
58
|
+
// We don't cleanup these references upfront, but do need to ignore them after the definition is removed.
|
|
59
|
+
continue;
|
|
51
60
|
}
|
|
52
61
|
remaining_lookups.set(`${lookup.indexId}.${lookup.lookup.toString('base64')}`, lookup);
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
for (let result of evaluated) {
|
|
56
65
|
const sourceDefinitionId = this.mapping.parameterLookupId(result.lookup.source);
|
|
57
|
-
const binLookup =
|
|
66
|
+
const binLookup = serializeParameterLookup(result.lookup);
|
|
58
67
|
remaining_lookups.delete(`${sourceDefinitionId}.${binLookup.toString('base64')}`);
|
|
59
68
|
|
|
60
69
|
const op_id = data.op_seq.next();
|
|
61
70
|
this.debugLastOpId = op_id;
|
|
62
|
-
const values
|
|
71
|
+
const values = {
|
|
63
72
|
_id: op_id,
|
|
64
73
|
key: {
|
|
65
74
|
t: mongoTableId(sourceTable.id),
|
|
66
75
|
k: sourceKey
|
|
67
|
-
}
|
|
76
|
+
},
|
|
68
77
|
lookup: binLookup,
|
|
69
78
|
bucket_parameters: result.bucketParameters
|
|
70
79
|
};
|
|
@@ -81,14 +90,14 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
81
90
|
this.debugLastOpId = op_id;
|
|
82
91
|
const indexId = lookup.indexId;
|
|
83
92
|
if (indexId == null) {
|
|
84
|
-
throw new ReplicationAssertionError('Expected
|
|
93
|
+
throw new ReplicationAssertionError('Expected lookup when incrementalReprocessing is enabled');
|
|
85
94
|
}
|
|
86
|
-
const values
|
|
95
|
+
const values = {
|
|
87
96
|
_id: op_id,
|
|
88
97
|
key: {
|
|
89
98
|
t: mongoTableId(sourceTable.id),
|
|
90
99
|
k: sourceKey
|
|
91
|
-
}
|
|
100
|
+
},
|
|
92
101
|
lookup: lookup.lookup,
|
|
93
102
|
bucket_parameters: []
|
|
94
103
|
};
|
|
@@ -126,8 +135,8 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
126
135
|
update: {
|
|
127
136
|
$set: {
|
|
128
137
|
data: null,
|
|
129
|
-
buckets: []
|
|
130
|
-
lookups: []
|
|
138
|
+
buckets: [],
|
|
139
|
+
lookups: [],
|
|
131
140
|
pending_delete: checkpointGreaterThan
|
|
132
141
|
}
|
|
133
142
|
},
|
|
@@ -147,7 +156,7 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
147
156
|
upsertCurrentData(values: UpsertCurrentDataOptions) {
|
|
148
157
|
const buckets = values.buckets.map((bucket) => {
|
|
149
158
|
if (bucket.definitionId == null) {
|
|
150
|
-
throw new ReplicationAssertionError('Expected
|
|
159
|
+
throw new ReplicationAssertionError('Expected bucket when incrementalReprocessing is enabled');
|
|
151
160
|
}
|
|
152
161
|
return {
|
|
153
162
|
def: bucket.definitionId,
|
|
@@ -158,7 +167,7 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
158
167
|
});
|
|
159
168
|
const lookups = values.lookups.map((lookup) => {
|
|
160
169
|
if (lookup.indexId == null) {
|
|
161
|
-
throw new ReplicationAssertionError('Expected
|
|
170
|
+
throw new ReplicationAssertionError('Expected lookup when incrementalReprocessing is enabled');
|
|
162
171
|
}
|
|
163
172
|
return {
|
|
164
173
|
i: lookup.indexId,
|
|
@@ -190,8 +199,10 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
190
199
|
return this.currentData.length;
|
|
191
200
|
}
|
|
192
201
|
|
|
202
|
+
// Flush methods
|
|
203
|
+
|
|
193
204
|
protected async flushBucketData(session: mongo.ClientSession) {
|
|
194
|
-
const operationsByDefinition = new Map<BucketDefinitionId,
|
|
205
|
+
const operationsByDefinition = new Map<BucketDefinitionId, BucketDataDoc[]>();
|
|
195
206
|
for (const document of this.bucketData) {
|
|
196
207
|
const existing = operationsByDefinition.get(document.bucketKey.definitionId) ?? [];
|
|
197
208
|
existing.push(document);
|
|
@@ -199,17 +210,31 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
for (const [definitionId, documents] of operationsByDefinition.entries()) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
213
|
+
const operationsByBucket = new Map<string, BucketDataDoc[]>();
|
|
214
|
+
for (const document of documents) {
|
|
215
|
+
const existing = operationsByBucket.get(document.bucketKey.bucket) ?? [];
|
|
216
|
+
existing.push(document);
|
|
217
|
+
operationsByBucket.set(document.bucketKey.bucket, existing);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const inserts: mongo.AnyBulkWriteOperation<BucketDataDocumentV3>[] = [];
|
|
221
|
+
for (const [bucket, ops] of operationsByBucket.entries()) {
|
|
222
|
+
const chunks = chunkBucketData(ops);
|
|
223
|
+
for (const chunk of chunks) {
|
|
224
|
+
inserts.push({
|
|
225
|
+
insertOne: {
|
|
226
|
+
document: serializeBucketData(bucket, chunk)
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (inserts.length > 0) {
|
|
233
|
+
await this.db.bucketData(this.group_id, definitionId).bulkWrite(inserts, {
|
|
209
234
|
session,
|
|
210
235
|
ordered: false
|
|
211
|
-
}
|
|
212
|
-
|
|
236
|
+
});
|
|
237
|
+
}
|
|
213
238
|
}
|
|
214
239
|
}
|
|
215
240
|
|
|
@@ -222,10 +247,10 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
222
247
|
}
|
|
223
248
|
|
|
224
249
|
for (const [indexId, documents] of operationsByIndex.entries()) {
|
|
225
|
-
await this.db.
|
|
250
|
+
await this.db.parameterIndex(this.group_id, indexId).bulkWrite(
|
|
226
251
|
documents.map((document) => ({
|
|
227
252
|
insertOne: {
|
|
228
|
-
document:
|
|
253
|
+
document: taggedBucketParameterDocumentToTagged(document)
|
|
229
254
|
}
|
|
230
255
|
})),
|
|
231
256
|
{
|
|
@@ -261,12 +286,12 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
261
286
|
});
|
|
262
287
|
|
|
263
288
|
if (sourceTableUpdates.length > 0) {
|
|
264
|
-
await this.db.
|
|
289
|
+
await this.db.sourceTables(this.group_id).bulkWrite(sourceTableUpdates, { session, ordered: false });
|
|
265
290
|
}
|
|
266
291
|
|
|
267
292
|
for (const operations of operationsBySourceTable.values()) {
|
|
268
293
|
const sourceTableId = operations[0]!.sourceTableId;
|
|
269
|
-
await this.db.
|
|
294
|
+
await this.db.sourceRecords(this.group_id, sourceTableId).bulkWrite(
|
|
270
295
|
operations.map((entry) => entry.operation),
|
|
271
296
|
{
|
|
272
297
|
session,
|
|
@@ -277,7 +302,7 @@ export class PersistedBatchV3 extends PersistedBatch {
|
|
|
277
302
|
}
|
|
278
303
|
|
|
279
304
|
protected async flushBucketStates(session: mongo.ClientSession) {
|
|
280
|
-
await this.db.
|
|
305
|
+
await this.db.bucketState(this.group_id).bulkWrite(this.getBucketStateUpdates(), {
|
|
281
306
|
session,
|
|
282
307
|
ordered: false
|
|
283
308
|
});
|
|
@@ -6,9 +6,38 @@ import {
|
|
|
6
6
|
BucketDataDocumentGenericId,
|
|
7
7
|
SingleBucketStore
|
|
8
8
|
} from '../common/SingleBucketStore.js';
|
|
9
|
-
import { BucketDataProperties } from '../models.js';
|
|
9
|
+
import { BucketDataKey, BucketDataProperties } from '../models.js';
|
|
10
|
+
import { loadBucketDataDocument, serializeBucketData } from './bucket-format.js';
|
|
11
|
+
import { BucketDataDocumentV3 } from './models.js';
|
|
10
12
|
import { VersionedPowerSyncMongoV3 } from './VersionedPowerSyncMongoV3.js';
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
function extractPartialDocumentFields(doc: unknown): { _id: { o: bigint }; [key: string]: unknown } {
|
|
15
|
+
if (typeof doc !== 'object' || doc === null) {
|
|
16
|
+
throw new Error('Invalid partial document: expected object');
|
|
17
|
+
}
|
|
18
|
+
const d = doc as Record<string, unknown>;
|
|
19
|
+
const id = d._id;
|
|
20
|
+
if (typeof id !== 'object' || id === null || !('o' in id)) {
|
|
21
|
+
throw new Error('Invalid partial document: missing _id.o');
|
|
22
|
+
}
|
|
23
|
+
return d as { _id: { o: bigint }; [key: string]: unknown };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MongoDB's MinKey/MaxKey are special sentinel values that don't match the bigint type
|
|
27
|
+
// for _id.o in BucketDataDocumentGenericId, so we need an explicit cast.
|
|
28
|
+
function minKeyForBucket(bucket: string): BucketDataDocumentGenericId {
|
|
29
|
+
return {
|
|
30
|
+
b: bucket,
|
|
31
|
+
o: new mongo.MinKey()
|
|
32
|
+
} as unknown as BucketDataDocumentGenericId;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function maxKeyForBucket(bucket: string): BucketDataDocumentGenericId {
|
|
36
|
+
return {
|
|
37
|
+
b: bucket,
|
|
38
|
+
o: new mongo.MaxKey()
|
|
39
|
+
} as unknown as BucketDataDocumentGenericId;
|
|
40
|
+
}
|
|
12
41
|
|
|
13
42
|
export class SingleBucketStoreV3 implements SingleBucketStore {
|
|
14
43
|
public readonly collection: mongo.Collection<BucketDataDocumentGeneric>;
|
|
@@ -17,52 +46,63 @@ export class SingleBucketStoreV3 implements SingleBucketStore {
|
|
|
17
46
|
private db: VersionedPowerSyncMongoV3,
|
|
18
47
|
public readonly key: BucketKey
|
|
19
48
|
) {
|
|
20
|
-
|
|
49
|
+
// Cast from the version-specific collection type to the generic interface
|
|
50
|
+
// used across storage versions.
|
|
51
|
+
this.collection = db.bucketData(
|
|
21
52
|
key.replicationStreamId,
|
|
22
53
|
key.definitionId
|
|
23
54
|
) as unknown as mongo.Collection<BucketDataDocumentGeneric>;
|
|
24
55
|
}
|
|
25
56
|
|
|
26
57
|
docId(o: InternalOpId): BucketDataDocumentGenericId {
|
|
27
|
-
// `satisfies
|
|
58
|
+
// `satisfies BucketDataKey` checks that we use the correct type for V3 storage
|
|
28
59
|
// `as BucketDataDocumentGenericId` does a cast to get the interface virtual type
|
|
29
60
|
return {
|
|
30
61
|
b: this.key.bucket,
|
|
31
62
|
o
|
|
32
|
-
} satisfies
|
|
63
|
+
} satisfies BucketDataKey as BucketDataDocumentGenericId;
|
|
33
64
|
}
|
|
34
65
|
|
|
35
66
|
get minId(): BucketDataDocumentGenericId {
|
|
36
|
-
return
|
|
37
|
-
b: this.key.bucket,
|
|
38
|
-
o: new mongo.MinKey()
|
|
39
|
-
} as any; // No way to properly type this
|
|
67
|
+
return minKeyForBucket(this.key.bucket);
|
|
40
68
|
}
|
|
41
69
|
|
|
42
70
|
get maxId(): BucketDataDocumentGenericId {
|
|
43
|
-
return
|
|
44
|
-
b: this.key.bucket,
|
|
45
|
-
o: new mongo.MaxKey()
|
|
46
|
-
} as any; // No way to properly type this
|
|
71
|
+
return maxKeyForBucket(this.key.bucket);
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
toPersistedDocument(source: Omit<BucketDataDoc, 'bucketKey'>): BucketDataDocumentGeneric {
|
|
50
|
-
return
|
|
75
|
+
return serializeBucketData(this.key.bucket, [
|
|
76
|
+
{ bucketKey: this.key, ...source }
|
|
77
|
+
]) as unknown as BucketDataDocumentGeneric;
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
fromPersistedDocument(doc: BucketDataDocumentGeneric): BucketDataDoc {
|
|
54
|
-
|
|
81
|
+
const generator = loadBucketDataDocument(this.key, doc as unknown as BucketDataDocumentV3);
|
|
82
|
+
const first = generator.next();
|
|
83
|
+
if (first.done) {
|
|
84
|
+
throw new Error('Empty ops array in BucketDataDocumentV3');
|
|
85
|
+
}
|
|
86
|
+
return first.value;
|
|
55
87
|
}
|
|
56
88
|
|
|
57
89
|
fromPartialPersistedDocument<T extends keyof BucketDataProperties>(
|
|
58
90
|
doc: Pick<BucketDataDocumentGeneric, '_id' | T>
|
|
59
91
|
): Pick<BucketDataDoc, 'bucketKey' | 'o' | T> {
|
|
60
|
-
const document = doc as Pick<BucketDataDocumentV3, '_id' |
|
|
61
|
-
const
|
|
92
|
+
const document = doc as unknown as Pick<BucketDataDocumentV3, '_id' | 'ops'>;
|
|
93
|
+
const op = document.ops?.[0];
|
|
94
|
+
if (op == null) {
|
|
95
|
+
const fields = extractPartialDocumentFields(doc);
|
|
96
|
+
const { _id, ...rest } = fields;
|
|
97
|
+
return {
|
|
98
|
+
bucketKey: this.key,
|
|
99
|
+
o: _id.o,
|
|
100
|
+
...rest
|
|
101
|
+
} as Pick<BucketDataDoc, 'bucketKey' | 'o' | T>;
|
|
102
|
+
}
|
|
62
103
|
return {
|
|
63
104
|
bucketKey: this.key,
|
|
64
|
-
|
|
65
|
-
...rest
|
|
105
|
+
...op
|
|
66
106
|
} as Pick<BucketDataDoc, 'bucketKey' | 'o' | T>;
|
|
67
107
|
}
|
|
68
108
|
}
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
3
3
|
import { Logger } from '@powersync/lib-services-framework';
|
|
4
|
-
import { storage } from '@powersync/service-core';
|
|
4
|
+
import { BucketDefinitionMapping, storage } from '@powersync/service-core';
|
|
5
5
|
import { EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
6
6
|
import * as bson from 'bson';
|
|
7
7
|
import { retryOnMongoMaxTimeMSExpired } from '../../../utils/util.js';
|
|
8
|
-
import { BucketDefinitionMapping } from '../BucketDefinitionMapping.js';
|
|
9
8
|
import { cacheKey } from '../OperationBatch.js';
|
|
10
9
|
import { LoadedSourceRecord, SourceRecordLookupEntry, SourceRecordStore } from '../common/SourceRecordStore.js';
|
|
11
|
-
import { serializeParameterLookupV3 } from './MongoParameterLookupV3.js';
|
|
12
10
|
import { VersionedPowerSyncMongoV3 } from './VersionedPowerSyncMongoV3.js';
|
|
13
|
-
import { CurrentDataDocumentV3, SourceTableDocumentV3 } from './models.js';
|
|
11
|
+
import { CurrentDataDocumentV3, serializeParameterLookup, SourceTableDocumentV3 } from './models.js';
|
|
14
12
|
|
|
15
13
|
export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
16
14
|
constructor(
|
|
17
15
|
private readonly db: VersionedPowerSyncMongoV3,
|
|
18
|
-
private readonly
|
|
16
|
+
private readonly replicationStreamId: number,
|
|
19
17
|
private readonly mapping: BucketDefinitionMapping
|
|
20
18
|
) {}
|
|
21
19
|
|
|
@@ -31,7 +29,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
31
29
|
mapParameterLookups(paramEvaluated: EvaluatedParameters[]): LoadedSourceRecord['lookups'] {
|
|
32
30
|
return paramEvaluated.map((entry) => ({
|
|
33
31
|
indexId: this.mapping.parameterLookupId(entry.lookup.source),
|
|
34
|
-
lookup:
|
|
32
|
+
lookup: serializeParameterLookup(entry.lookup)
|
|
35
33
|
}));
|
|
36
34
|
}
|
|
37
35
|
|
|
@@ -67,7 +65,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
67
65
|
_id: { $in: replicaIds as any[] }
|
|
68
66
|
} as unknown as mongo.Filter<CurrentDataDocumentV3>;
|
|
69
67
|
const sizeCursor: mongo.AggregationCursor<CurrentDataDocumentV3 & { size: number }> = this.db
|
|
70
|
-
.
|
|
68
|
+
.sourceRecords(this.replicationStreamId, sourceTableId)
|
|
71
69
|
.aggregate(
|
|
72
70
|
[
|
|
73
71
|
{
|
|
@@ -100,7 +98,9 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
100
98
|
const filter = {
|
|
101
99
|
_id: { $in: replicaIds as any[] }
|
|
102
100
|
} as unknown as mongo.Filter<CurrentDataDocumentV3>;
|
|
103
|
-
const cursor = this.db
|
|
101
|
+
const cursor = this.db
|
|
102
|
+
.sourceRecords(this.replicationStreamId, sourceTableId)
|
|
103
|
+
.find(filter, { session, projection });
|
|
104
104
|
for await (const doc of cursor.stream()) {
|
|
105
105
|
const loaded = this.createLoadedDocument(
|
|
106
106
|
sourceTableId,
|
|
@@ -120,7 +120,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
120
120
|
sourceTableId: bson.ObjectId,
|
|
121
121
|
limit: number
|
|
122
122
|
): Promise<LoadedSourceRecord[]> {
|
|
123
|
-
const cursor = this.db.
|
|
123
|
+
const cursor = this.db.sourceRecords(this.replicationStreamId, sourceTableId).find(
|
|
124
124
|
{
|
|
125
125
|
pending_delete: { $exists: false }
|
|
126
126
|
},
|
|
@@ -145,7 +145,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
145
145
|
// ones have dirty deletes in source_tables.
|
|
146
146
|
|
|
147
147
|
const dirtySourceTables = await this.db
|
|
148
|
-
.
|
|
148
|
+
.sourceTables(this.replicationStreamId)
|
|
149
149
|
.find(
|
|
150
150
|
{
|
|
151
151
|
latest_pending_delete: { $exists: true }
|
|
@@ -159,7 +159,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
159
159
|
let deletedCount = 0;
|
|
160
160
|
const sourceTableUpdates: mongo.AnyBulkWriteOperation<SourceTableDocumentV3>[] = [];
|
|
161
161
|
for (const sourceTable of dirtySourceTables) {
|
|
162
|
-
const collection = this.db.
|
|
162
|
+
const collection = this.db.sourceRecords(this.replicationStreamId, sourceTable._id);
|
|
163
163
|
const result = await this.deletePendingDeletes(collection, sourceTable._id, lastCheckpoint, logger);
|
|
164
164
|
deletedCount += result.deletedCount;
|
|
165
165
|
|
|
@@ -182,7 +182,7 @@ export class SourceRecordStoreV3 implements SourceRecordStore {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
if (sourceTableUpdates.length > 0) {
|
|
185
|
-
await this.db.
|
|
185
|
+
await this.db.sourceTables(this.replicationStreamId).bulkWrite(sourceTableUpdates, { ordered: false });
|
|
186
186
|
}
|
|
187
187
|
if (deletedCount > 0) {
|
|
188
188
|
logger.info(`Cleaned up ${deletedCount} pending delete current_data records for checkpoint ${lastCheckpoint}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
-
import { BucketDefinitionId, ParameterIndexId } from '
|
|
2
|
+
import { BucketDefinitionId, ParameterIndexId } from '@powersync/service-sync-rules';
|
|
3
3
|
import { BaseVersionedPowerSyncMongo } from '../common/VersionedPowerSyncMongoBase.js';
|
|
4
4
|
import { CommonSourceTableDocument } from '../models.js';
|
|
5
5
|
import {
|
|
@@ -7,53 +7,85 @@ import {
|
|
|
7
7
|
BucketParameterDocumentV3,
|
|
8
8
|
BucketStateDocumentV3,
|
|
9
9
|
CurrentDataDocumentV3,
|
|
10
|
-
SourceTableDocumentV3
|
|
10
|
+
SourceTableDocumentV3,
|
|
11
|
+
SyncConfigDefinition
|
|
11
12
|
} from './models.js';
|
|
12
13
|
|
|
13
14
|
export class VersionedPowerSyncMongoV3 extends BaseVersionedPowerSyncMongo {
|
|
14
|
-
|
|
15
|
+
constructor(
|
|
16
|
+
upstream: ConstructorParameters<typeof BaseVersionedPowerSyncMongo>[0],
|
|
17
|
+
storageConfig: ConstructorParameters<typeof BaseVersionedPowerSyncMongo>[1]
|
|
18
|
+
) {
|
|
19
|
+
super(upstream, storageConfig);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get syncConfigDefinitions() {
|
|
23
|
+
return this.db.collection<SyncConfigDefinition>('sync_config');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
sourceRecords(replicationStreamId: number, sourceTableId: mongo.ObjectId): mongo.Collection<CurrentDataDocumentV3> {
|
|
15
27
|
const collectionName = this.sourceRecordsCollectionName(replicationStreamId, sourceTableId);
|
|
16
28
|
return this.db.collection<CurrentDataDocumentV3>(collectionName);
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
async
|
|
31
|
+
async listSourceRecordCollections(replicationStreamId: number): Promise<mongo.Collection<CurrentDataDocumentV3>[]> {
|
|
20
32
|
return this.listCollectionsByPrefix<CurrentDataDocumentV3>(`source_records_${replicationStreamId}_`);
|
|
21
33
|
}
|
|
22
34
|
|
|
23
|
-
async initializeSourceRecordsCollection(
|
|
24
|
-
|
|
35
|
+
async initializeSourceRecordsCollection(
|
|
36
|
+
replicationStreamId: number,
|
|
37
|
+
sourceTableId: mongo.ObjectId,
|
|
38
|
+
session?: mongo.ClientSession
|
|
39
|
+
) {
|
|
40
|
+
await this.sourceRecords(replicationStreamId, sourceTableId).createIndex(
|
|
25
41
|
{
|
|
26
42
|
pending_delete: 1
|
|
27
43
|
},
|
|
28
44
|
{
|
|
29
45
|
partialFilterExpression: { pending_delete: { $exists: true } },
|
|
30
|
-
name: 'pending_delete'
|
|
46
|
+
name: 'pending_delete',
|
|
47
|
+
session
|
|
31
48
|
}
|
|
32
49
|
);
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
commonSourceTables(replicationStreamId: number): mongo.Collection<CommonSourceTableDocument> {
|
|
36
|
-
return this.
|
|
53
|
+
return this.sourceTables(replicationStreamId) as any as mongo.Collection<CommonSourceTableDocument>;
|
|
37
54
|
}
|
|
38
55
|
|
|
39
|
-
|
|
56
|
+
bucketState(replicationStreamId: number): mongo.Collection<BucketStateDocumentV3> {
|
|
40
57
|
return this.db.collection(`bucket_state_${replicationStreamId}`);
|
|
41
58
|
}
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
replicationStreamId: number,
|
|
45
|
-
indexId: ParameterIndexId
|
|
46
|
-
): mongo.Collection<BucketParameterDocumentV3> {
|
|
60
|
+
parameterIndex(replicationStreamId: number, indexId: ParameterIndexId): mongo.Collection<BucketParameterDocumentV3> {
|
|
47
61
|
return this.db.collection(`parameter_index_${replicationStreamId}_${indexId}`);
|
|
48
62
|
}
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
sourceTables(replicationStreamId: number): mongo.Collection<SourceTableDocumentV3> {
|
|
51
65
|
return this.db.collection<SourceTableDocumentV3>(this.sourceTableCollectionName(replicationStreamId));
|
|
52
66
|
}
|
|
53
67
|
|
|
68
|
+
bucketData(replicationStreamId: number, definitionId: BucketDefinitionId): mongo.Collection<BucketDataDocumentV3> {
|
|
69
|
+
return this.db.collection<BucketDataDocumentV3>(`bucket_data_${replicationStreamId}_${definitionId}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
listBucketDataCollections(replicationStreamId: number) {
|
|
73
|
+
return this.listCollectionsByPrefix(`bucket_data_${replicationStreamId}_`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async listParameterIndexCollections(replicationStreamId: number) {
|
|
77
|
+
const prefix = `parameter_index_${replicationStreamId}_`;
|
|
78
|
+
const collections = await this.listCollectionsByPrefix(prefix);
|
|
79
|
+
|
|
80
|
+
return collections.map((collection) => ({
|
|
81
|
+
collection,
|
|
82
|
+
indexId: collection.collectionName.slice(prefix.length)
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
|
|
54
86
|
async initializeStreamStorage(replicationStreamId: number) {
|
|
55
|
-
const sourceTables = this.
|
|
56
|
-
const bucketState = this.
|
|
87
|
+
const sourceTables = this.sourceTables(replicationStreamId);
|
|
88
|
+
const bucketState = this.bucketState(replicationStreamId);
|
|
57
89
|
await sourceTables.createIndex(
|
|
58
90
|
{
|
|
59
91
|
connection_id: 1,
|
|
@@ -87,26 +119,4 @@ export class VersionedPowerSyncMongoV3 extends BaseVersionedPowerSyncMongo {
|
|
|
87
119
|
{ name: 'dirty_count' }
|
|
88
120
|
);
|
|
89
121
|
}
|
|
90
|
-
|
|
91
|
-
bucketDataV3(replicationStreamId: number, definitionId: BucketDefinitionId) {
|
|
92
|
-
return this.db.collection<BucketDataDocumentV3>(`bucket_data_${replicationStreamId}_${definitionId}`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
listBucketDataCollectionsV3(replicationStreamId: number) {
|
|
96
|
-
return this.upstream.listBucketDataCollectionsV3(replicationStreamId);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async listParameterIndexCollectionsV3(
|
|
100
|
-
replicationStreamId: number
|
|
101
|
-
): Promise<{ collection: mongo.Collection<BucketParameterDocumentV3>; indexId: ParameterIndexId }[]> {
|
|
102
|
-
const prefix = `parameter_index_${replicationStreamId}_`;
|
|
103
|
-
const collections = await this.db.listCollections({ name: new RegExp(`^${prefix}`) }, { nameOnly: true }).toArray();
|
|
104
|
-
|
|
105
|
-
return collections
|
|
106
|
-
.filter((collection) => collection.name.startsWith(prefix))
|
|
107
|
-
.map((collection) => ({
|
|
108
|
-
collection: this.db.collection<BucketParameterDocumentV3>(collection.name),
|
|
109
|
-
indexId: collection.name.slice(prefix.length)
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
122
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { BucketDataDoc, BucketKey } from '../common/BucketDataDoc.js';
|
|
2
|
+
import { BucketDataDocumentV3, BucketOperation } from './models.js';
|
|
3
|
+
|
|
4
|
+
export function serializeBucketData(bucket: string, operations: BucketDataDoc[]): BucketDataDocumentV3 {
|
|
5
|
+
const minOp = operations[0].o;
|
|
6
|
+
const maxOp = operations[operations.length - 1].o;
|
|
7
|
+
|
|
8
|
+
let totalChecksum = 0n;
|
|
9
|
+
let totalSize = 0;
|
|
10
|
+
let maxTargetOp: bigint | null = null;
|
|
11
|
+
|
|
12
|
+
const ops: BucketOperation[] = operations.map((op) => {
|
|
13
|
+
totalChecksum += op.checksum;
|
|
14
|
+
totalSize += op.data?.length ?? 0;
|
|
15
|
+
|
|
16
|
+
if (op.target_op != null && (maxTargetOp == null || op.target_op > maxTargetOp)) {
|
|
17
|
+
maxTargetOp = op.target_op;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
o: op.o,
|
|
22
|
+
op: op.op,
|
|
23
|
+
source_table: op.source_table,
|
|
24
|
+
source_key: op.source_key,
|
|
25
|
+
table: op.table,
|
|
26
|
+
row_id: op.row_id,
|
|
27
|
+
checksum: op.checksum,
|
|
28
|
+
data: op.data
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
_id: {
|
|
34
|
+
b: bucket,
|
|
35
|
+
o: maxOp
|
|
36
|
+
},
|
|
37
|
+
min_op: minOp,
|
|
38
|
+
checksum: totalChecksum,
|
|
39
|
+
count: operations.length,
|
|
40
|
+
size: totalSize,
|
|
41
|
+
target_op: maxTargetOp,
|
|
42
|
+
ops
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function* loadBucketDataDocument(
|
|
47
|
+
context: Pick<BucketKey, 'replicationStreamId' | 'definitionId'>,
|
|
48
|
+
doc: BucketDataDocumentV3
|
|
49
|
+
): Generator<BucketDataDoc> {
|
|
50
|
+
const { _id, ops } = doc;
|
|
51
|
+
const bucketKey = {
|
|
52
|
+
...context,
|
|
53
|
+
bucket: _id.b
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
for (const op of ops) {
|
|
57
|
+
yield {
|
|
58
|
+
bucketKey,
|
|
59
|
+
o: op.o,
|
|
60
|
+
op: op.op,
|
|
61
|
+
source_table: op.source_table,
|
|
62
|
+
source_key: op.source_key,
|
|
63
|
+
table: op.table,
|
|
64
|
+
row_id: op.row_id,
|
|
65
|
+
checksum: op.checksum,
|
|
66
|
+
data: op.data,
|
|
67
|
+
target_op: doc.target_op ?? null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|