@powersync/service-module-mongodb-storage 0.17.0 → 0.18.1
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 +27 -0
- package/dist/storage/MongoBucketStorage.d.ts +34 -16
- package/dist/storage/MongoBucketStorage.js +219 -70
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +42 -23
- package/dist/storage/implementation/MongoBucketBatch.js +61 -44
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoChecksums.d.ts +10 -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 +2 -0
- 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 +123 -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 +41 -23
- package/dist/storage/implementation/MongoSyncBucketStorage.js +51 -43
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js +3 -3
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +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 +1 -2
- package/dist/storage/implementation/common/PersistedBatch.js +5 -0
- package/dist/storage/implementation/common/PersistedBatch.js.map +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.js +9 -14
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +4 -13
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +9 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +42 -26
- 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/MongoSyncBucketStorageV1.d.ts +15 -17
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +47 -45
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.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 +10 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +8 -4
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +286 -259
- 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 +19 -2
- 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 +40 -28
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +232 -116
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +1 -1
- 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 +13 -12
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +29 -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 +64 -21
- 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/storage/MongoBucketStorage.ts +334 -87
- package/src/storage/implementation/MongoBucketBatch.ts +86 -58
- package/src/storage/implementation/MongoChecksums.ts +6 -138
- package/src/storage/implementation/MongoCompactor.ts +19 -9
- 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 +154 -0
- package/src/storage/implementation/MongoStorageProvider.ts +5 -2
- package/src/storage/implementation/MongoSyncBucketStorage.ts +70 -56
- package/src/storage/implementation/MongoSyncRulesLock.ts +7 -4
- package/src/storage/implementation/common/MongoSyncBucketStorageCheckpoint.ts +7 -0
- package/src/storage/implementation/common/PersistedBatch.ts +7 -3
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +1 -1
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +21 -7
- package/src/storage/implementation/db.ts +11 -19
- package/src/storage/implementation/models.ts +4 -14
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +55 -34
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +137 -4
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +70 -64
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +11 -1
- package/src/storage/implementation/v1/models.ts +11 -1
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +358 -314
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +262 -26
- package/src/storage/implementation/v3/MongoCompactorV3.ts +646 -29
- package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +480 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +315 -157
- package/src/storage/implementation/v3/PersistedBatchV3.ts +62 -36
- 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 +41 -36
- 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 +93 -55
- 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 +1077 -68
- package/test/src/storeCurrentData.test.ts +17 -7
- 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 -15
- 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 -67
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +0 -1
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +0 -29
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +0 -76
- 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 -4
- 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 -75
- package/src/storage/implementation/MongoPersistedSyncRules.ts +0 -82
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +0 -101
- 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 -11
|
@@ -1,41 +1,61 @@
|
|
|
1
|
+
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
1
2
|
import {
|
|
2
3
|
bson,
|
|
3
4
|
BucketChecksum,
|
|
4
5
|
FetchPartialBucketChecksum,
|
|
5
6
|
InternalOpId,
|
|
7
|
+
isPartialChecksum,
|
|
6
8
|
PartialChecksumMap,
|
|
7
|
-
PartialOrFullChecksum
|
|
9
|
+
PartialOrFullChecksum,
|
|
10
|
+
SingleSyncConfigBucketDefinitionMapping
|
|
8
11
|
} from '@powersync/service-core';
|
|
9
|
-
import { BucketDefinitionMapping } from '../BucketDefinitionMapping.js';
|
|
10
12
|
import {
|
|
13
|
+
checksumFromAggregate,
|
|
11
14
|
emptyChecksumForRequest,
|
|
12
|
-
|
|
15
|
+
FetchPartialBucketChecksumByBucket,
|
|
16
|
+
FetchPartialBucketChecksumByDefinition,
|
|
13
17
|
MongoChecksumOptions,
|
|
14
18
|
MongoChecksums
|
|
15
19
|
} from '../MongoChecksums.js';
|
|
16
20
|
import { VersionedPowerSyncMongoV3 } from './VersionedPowerSyncMongoV3.js';
|
|
21
|
+
import { BucketDataDocumentV3 } from './models.js';
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Checksum operations addressed by persisted definition id.
|
|
25
|
+
*
|
|
26
|
+
* Safe on any storage instance, including multi-config replication-side instances - no
|
|
27
|
+
* source resolution is involved. This is the only checksum surface the compactor may use.
|
|
28
|
+
*/
|
|
29
|
+
export interface DefinitionChecksumOperations {
|
|
30
|
+
computePartialChecksumsDirectByDefinition(
|
|
31
|
+
batch: FetchPartialBucketChecksumByDefinition[]
|
|
32
|
+
): Promise<PartialChecksumMap>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface MongoChecksumOptionsV3 extends MongoChecksumOptions {
|
|
36
|
+
/**
|
|
37
|
+
* The persisted mapping of the single sync config that reads are served from.
|
|
38
|
+
*
|
|
39
|
+
* A thunk rather than a plain value: checksums are constructed eagerly with the storage
|
|
40
|
+
* instance, but the single-config requirement may only be asserted when a read happens.
|
|
41
|
+
*/
|
|
42
|
+
syncConfigMapping: () => SingleSyncConfigBucketDefinitionMapping;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class MongoChecksumsV3 extends MongoChecksums implements DefinitionChecksumOperations {
|
|
19
46
|
declare protected readonly db: VersionedPowerSyncMongoV3;
|
|
20
|
-
private readonly
|
|
47
|
+
private readonly syncConfigMapping: () => SingleSyncConfigBucketDefinitionMapping;
|
|
21
48
|
|
|
22
|
-
constructor(db: VersionedPowerSyncMongoV3, group_id: number, options:
|
|
49
|
+
constructor(db: VersionedPowerSyncMongoV3, group_id: number, options: MongoChecksumOptionsV3) {
|
|
23
50
|
super(db, group_id, options);
|
|
24
|
-
this.
|
|
51
|
+
this.syncConfigMapping = options.syncConfigMapping;
|
|
25
52
|
}
|
|
26
53
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
definitionId: this.mapping.bucketSourceId(request.source),
|
|
31
|
-
start: request.start,
|
|
32
|
-
end: request.end
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async computePartialChecksumsDirectByDefinition(batch: FetchPartialBucketChecksumV3[]): Promise<PartialChecksumMap> {
|
|
54
|
+
async computePartialChecksumsDirectByDefinition(
|
|
55
|
+
batch: FetchPartialBucketChecksumByDefinition[]
|
|
56
|
+
): Promise<PartialChecksumMap> {
|
|
37
57
|
const results = new Map<string, PartialOrFullChecksum>();
|
|
38
|
-
const requestsByDefinition = new Map<string,
|
|
58
|
+
const requestsByDefinition = new Map<string, FetchPartialBucketChecksumByDefinition[]>();
|
|
39
59
|
|
|
40
60
|
for (const request of batch) {
|
|
41
61
|
const existing = requestsByDefinition.get(request.definitionId) ?? [];
|
|
@@ -44,10 +64,9 @@ export class MongoChecksumsV3 extends MongoChecksums {
|
|
|
44
64
|
}
|
|
45
65
|
|
|
46
66
|
for (const [definitionId, requests] of requestsByDefinition.entries()) {
|
|
47
|
-
const groupResults = await this.
|
|
67
|
+
const groupResults = await this.computeChecksumsByDefinition(
|
|
48
68
|
requests,
|
|
49
|
-
this.db.
|
|
50
|
-
createV3BucketFilter
|
|
69
|
+
this.db.bucketData(this.group_id, definitionId)
|
|
51
70
|
);
|
|
52
71
|
for (const checksum of groupResults.values()) {
|
|
53
72
|
results.set(checksum.bucket, checksum);
|
|
@@ -62,7 +81,14 @@ export class MongoChecksumsV3 extends MongoChecksums {
|
|
|
62
81
|
protected async fetchPreStates(
|
|
63
82
|
batch: FetchPartialBucketChecksum[]
|
|
64
83
|
): Promise<Map<string, { opId: InternalOpId; checksum: BucketChecksum }>> {
|
|
65
|
-
const
|
|
84
|
+
const normalizedBatch = batch.map((request) => ({
|
|
85
|
+
bucket: request.bucket,
|
|
86
|
+
definitionId: this.syncConfigMapping().bucketSourceId(request.source),
|
|
87
|
+
start: request.start,
|
|
88
|
+
end: request.end
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const preFilters = normalizedBatch
|
|
66
92
|
.filter((request) => request.start == null)
|
|
67
93
|
.map((request) => ({
|
|
68
94
|
_id: {
|
|
@@ -78,7 +104,7 @@ export class MongoChecksumsV3 extends MongoChecksums {
|
|
|
78
104
|
}
|
|
79
105
|
|
|
80
106
|
const states = await this.db
|
|
81
|
-
.
|
|
107
|
+
.bucketState(this.group_id)
|
|
82
108
|
.find({
|
|
83
109
|
$or: preFilters
|
|
84
110
|
})
|
|
@@ -100,11 +126,218 @@ export class MongoChecksumsV3 extends MongoChecksums {
|
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
protected async computePartialChecksumsInternal(batch: FetchPartialBucketChecksum[]): Promise<PartialChecksumMap> {
|
|
103
|
-
|
|
129
|
+
const normalized = batch.map((request) => ({
|
|
130
|
+
bucket: request.bucket,
|
|
131
|
+
definitionId: this.syncConfigMapping().bucketSourceId(request.source),
|
|
132
|
+
start: request.start,
|
|
133
|
+
end: request.end
|
|
134
|
+
}));
|
|
135
|
+
|
|
136
|
+
const results = new Map<string, PartialOrFullChecksum>();
|
|
137
|
+
const requestsByDefinition = new Map<string, FetchPartialBucketChecksumByDefinition[]>();
|
|
138
|
+
|
|
139
|
+
for (const request of normalized) {
|
|
140
|
+
const existing = requestsByDefinition.get(request.definitionId) ?? [];
|
|
141
|
+
existing.push(request);
|
|
142
|
+
requestsByDefinition.set(request.definitionId, existing);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const [definitionId, requests] of requestsByDefinition.entries()) {
|
|
146
|
+
const groupResults = await this.computeChecksumsByDefinition(
|
|
147
|
+
requests,
|
|
148
|
+
this.db.bucketData(this.group_id, definitionId)
|
|
149
|
+
);
|
|
150
|
+
for (const checksum of groupResults.values()) {
|
|
151
|
+
results.set(checksum.bucket, checksum);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return new Map<string, PartialOrFullChecksum>(
|
|
156
|
+
normalized.map((request) => [request.bucket, results.get(request.bucket) ?? emptyChecksumForRequest(request)])
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private async computeChecksumsByDefinition(
|
|
161
|
+
batch: FetchPartialBucketChecksumByBucket[],
|
|
162
|
+
collection: lib_mongo.mongo.Collection<BucketDataDocumentV3>
|
|
163
|
+
): Promise<PartialChecksumMap> {
|
|
164
|
+
const requests = new Map<string, FetchPartialBucketChecksumByBucket>();
|
|
165
|
+
for (let request of batch) {
|
|
166
|
+
requests.set(request.bucket, request);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const pipeline = this.buildPartialChecksumPipeline(requests);
|
|
170
|
+
const aggregate = await collection
|
|
171
|
+
.aggregate(pipeline, {
|
|
172
|
+
session: undefined,
|
|
173
|
+
readConcern: 'snapshot',
|
|
174
|
+
maxTimeMS: lib_mongo.MONGO_CHECKSUM_TIMEOUT_MS
|
|
175
|
+
})
|
|
176
|
+
.toArray()
|
|
177
|
+
.catch((e) => {
|
|
178
|
+
throw lib_mongo.mapQueryError(e, 'while reading checksums');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
return this.normalizePartialChecksumResults(batch, aggregate);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private buildPartialChecksumPipeline(requests: Map<string, FetchPartialBucketChecksumByBucket>): bson.Document[] {
|
|
185
|
+
const filters = Array.from(requests.values(), createBucketFilter);
|
|
186
|
+
|
|
187
|
+
return [
|
|
188
|
+
// $match with $or filters
|
|
189
|
+
{
|
|
190
|
+
$match: {
|
|
191
|
+
$or: filters
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
$addFields: {
|
|
196
|
+
bucket_start: {
|
|
197
|
+
$switch: {
|
|
198
|
+
branches: Array.from(requests.entries()).map(([bucket, req]) => ({
|
|
199
|
+
case: { $eq: ['$_id.b', bucket] },
|
|
200
|
+
then: req.start ?? new bson.MinKey()
|
|
201
|
+
})),
|
|
202
|
+
default: new bson.MinKey()
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
bucket_end: {
|
|
206
|
+
$switch: {
|
|
207
|
+
branches: Array.from(requests.entries()).map(([bucket, req]) => ({
|
|
208
|
+
case: { $eq: ['$_id.b', bucket] },
|
|
209
|
+
then: req.end
|
|
210
|
+
})),
|
|
211
|
+
default: new bson.MaxKey()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
// Determine if document is fully included within [start, end] range
|
|
217
|
+
{
|
|
218
|
+
$project: {
|
|
219
|
+
_id: 1,
|
|
220
|
+
min_op: 1,
|
|
221
|
+
checksum: 1,
|
|
222
|
+
count: 1,
|
|
223
|
+
ops: 1,
|
|
224
|
+
bucket_start: 1,
|
|
225
|
+
bucket_end: 1,
|
|
226
|
+
is_fully_included: {
|
|
227
|
+
$and: [{ $gt: ['$min_op', '$bucket_start'] }, { $lte: ['$_id.o', '$bucket_end'] }]
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
// Compute included checksum, count, and clear op detection
|
|
232
|
+
{
|
|
233
|
+
$project: {
|
|
234
|
+
_id: 1,
|
|
235
|
+
checksum_total: {
|
|
236
|
+
$cond: {
|
|
237
|
+
if: '$is_fully_included',
|
|
238
|
+
then: '$checksum',
|
|
239
|
+
else: {
|
|
240
|
+
$sum: {
|
|
241
|
+
$map: {
|
|
242
|
+
input: {
|
|
243
|
+
$filter: {
|
|
244
|
+
input: '$ops',
|
|
245
|
+
cond: {
|
|
246
|
+
$and: [{ $gt: ['$$this.o', '$bucket_start'] }, { $lte: ['$$this.o', '$bucket_end'] }]
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
in: '$$this.checksum'
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
count_total: {
|
|
257
|
+
$cond: {
|
|
258
|
+
if: '$is_fully_included',
|
|
259
|
+
then: '$count',
|
|
260
|
+
else: {
|
|
261
|
+
$size: {
|
|
262
|
+
$filter: {
|
|
263
|
+
input: '$ops',
|
|
264
|
+
cond: {
|
|
265
|
+
$and: [{ $gt: ['$$this.o', '$bucket_start'] }, { $lte: ['$$this.o', '$bucket_end'] }]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
has_clear_op: {
|
|
273
|
+
$max: {
|
|
274
|
+
$map: {
|
|
275
|
+
input: {
|
|
276
|
+
$filter: {
|
|
277
|
+
input: '$ops',
|
|
278
|
+
cond: {
|
|
279
|
+
$and: [{ $gt: ['$$this.o', '$bucket_start'] }, { $lte: ['$$this.o', '$bucket_end'] }]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
in: { $cond: [{ $eq: ['$$this.op', 'CLEAR'] }, 1, 0] }
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
last_op: { $max: '$_id.o' }
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
// Group by bucket
|
|
291
|
+
{
|
|
292
|
+
$group: {
|
|
293
|
+
_id: '$_id.b',
|
|
294
|
+
checksum_total: { $sum: '$checksum_total' },
|
|
295
|
+
count: { $sum: '$count_total' },
|
|
296
|
+
has_clear_op: { $max: '$has_clear_op' },
|
|
297
|
+
last_op: { $max: '$last_op' }
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
// $sort results
|
|
301
|
+
{ $sort: { _id: 1 } }
|
|
302
|
+
];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private normalizePartialChecksumResults(
|
|
306
|
+
batch: FetchPartialBucketChecksumByBucket[],
|
|
307
|
+
aggregate: bson.Document[]
|
|
308
|
+
): PartialChecksumMap {
|
|
309
|
+
const partialChecksums = new Map<string, PartialOrFullChecksum>();
|
|
310
|
+
for (let doc of aggregate) {
|
|
311
|
+
const bucket = doc._id;
|
|
312
|
+
partialChecksums.set(bucket, checksumFromAggregate(doc));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return new Map<string, PartialOrFullChecksum>(
|
|
316
|
+
batch.map((request) => {
|
|
317
|
+
const bucket = request.bucket;
|
|
318
|
+
let partialChecksum = partialChecksums.get(bucket);
|
|
319
|
+
if (partialChecksum == null) {
|
|
320
|
+
partialChecksum = {
|
|
321
|
+
bucket,
|
|
322
|
+
partialCount: 0,
|
|
323
|
+
partialChecksum: 0
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
if (request.start == null && isPartialChecksum(partialChecksum)) {
|
|
327
|
+
partialChecksum = {
|
|
328
|
+
bucket,
|
|
329
|
+
count: partialChecksum.partialCount,
|
|
330
|
+
checksum: partialChecksum.partialChecksum
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return [bucket, partialChecksum];
|
|
335
|
+
})
|
|
336
|
+
);
|
|
104
337
|
}
|
|
105
338
|
}
|
|
106
339
|
|
|
107
|
-
function
|
|
340
|
+
function createBucketFilter(request: Pick<FetchPartialBucketChecksumByBucket, 'bucket' | 'start' | 'end'>) {
|
|
108
341
|
return {
|
|
109
342
|
_id: {
|
|
110
343
|
$gt: {
|
|
@@ -113,8 +346,11 @@ function createV3BucketFilter(request: Pick<FetchPartialBucketChecksumV3, 'bucke
|
|
|
113
346
|
},
|
|
114
347
|
$lte: {
|
|
115
348
|
b: request.bucket,
|
|
116
|
-
o:
|
|
349
|
+
o: new bson.MaxKey()
|
|
117
350
|
}
|
|
351
|
+
},
|
|
352
|
+
min_op: {
|
|
353
|
+
$lte: request.end
|
|
118
354
|
}
|
|
119
355
|
};
|
|
120
356
|
}
|