@powersync/service-module-mongodb-storage 0.23.2 → 0.24.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 +45 -0
- package/LICENSE +201 -67
- package/dist/storage/MongoBucketStorage.d.ts +1 -0
- package/dist/storage/MongoBucketStorage.js +45 -83
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +60 -39
- package/dist/storage/implementation/MongoBucketBatch.js +123 -296
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoOpIdAllocator.d.ts +6 -1
- package/dist/storage/implementation/MongoOpIdAllocator.js +12 -5
- package/dist/storage/implementation/MongoOpIdAllocator.js.map +1 -1
- package/dist/storage/implementation/MongoParsedSyncConfigSet.d.ts +7 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js +28 -2
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js.map +1 -1
- package/dist/storage/implementation/MongoReplicationOptions.d.ts +27 -0
- package/dist/storage/implementation/MongoReplicationOptions.js +26 -0
- package/dist/storage/implementation/MongoReplicationOptions.js.map +1 -0
- package/dist/storage/implementation/MongoSyncBucketStorage.js +2 -3
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +15 -2
- package/dist/storage/implementation/MongoSyncRulesLock.js +36 -14
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/common/BatchOperationBuffer.d.ts +79 -0
- package/dist/storage/implementation/common/BatchOperationBuffer.js +286 -0
- package/dist/storage/implementation/common/BatchOperationBuffer.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +10 -103
- package/dist/storage/implementation/common/PersistedBatch.js +1 -291
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/common/PreparedPublication.d.ts +43 -0
- package/dist/storage/implementation/common/PreparedPublication.js +2 -0
- package/dist/storage/implementation/common/PreparedPublication.js.map +1 -0
- package/dist/storage/implementation/common/SourceRecordStore.d.ts +0 -2
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +17 -13
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +259 -18
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/PersistedBatchV1.d.ts +21 -15
- package/dist/storage/implementation/v1/PersistedBatchV1.js +58 -24
- package/dist/storage/implementation/v1/PersistedBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/SourceRecordStoreV1.d.ts +0 -2
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js +0 -3
- package/dist/storage/implementation/v1/SourceRecordStoreV1.js.map +1 -1
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +25 -14
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +350 -23
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +1 -0
- package/dist/storage/implementation/v3/MongoCompactorV3.js +10 -4
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +39 -28
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +46 -24
- package/dist/storage/implementation/v3/PersistedBatchV3.js +159 -83
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +12 -0
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +41 -13
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -1
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.d.ts +4 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js +4 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js.map +1 -1
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.d.ts +27 -2
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js +61 -5
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js.map +1 -1
- package/package.json +9 -10
- package/src/storage/MongoBucketStorage.ts +55 -122
- package/src/storage/implementation/MongoBucketBatch.ts +185 -392
- package/src/storage/implementation/MongoOpIdAllocator.ts +12 -5
- package/src/storage/implementation/MongoParsedSyncConfigSet.ts +40 -1
- package/src/storage/implementation/MongoReplicationOptions.ts +28 -0
- package/src/storage/implementation/MongoSyncBucketStorage.ts +2 -3
- package/src/storage/implementation/MongoSyncRulesLock.ts +39 -17
- package/src/storage/implementation/common/BatchOperationBuffer.ts +353 -0
- package/src/storage/implementation/common/PersistedBatch.ts +12 -390
- package/src/storage/implementation/common/PreparedPublication.ts +49 -0
- package/src/storage/implementation/common/SourceRecordStore.ts +0 -2
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +339 -27
- package/src/storage/implementation/v1/PersistedBatchV1.ts +74 -32
- package/src/storage/implementation/v1/SourceRecordStoreV1.ts +0 -5
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +430 -32
- package/src/storage/implementation/v3/MongoCompactorV3.ts +13 -4
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +43 -29
- package/src/storage/implementation/v3/PersistedBatchV3.ts +209 -108
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +45 -15
- package/src/storage/implementation/v3/object-storage/BucketDataObjectStorage.ts +9 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorageLifecycle.ts +79 -5
- package/test/src/checkpoint_cleanup.test.ts +75 -0
- package/test/src/concurrent_writers.test.ts +127 -53
- package/test/src/helpers/PublicationCommandMonitor.ts +119 -0
- package/test/src/helpers/concurrentWriter.mjs +2 -2
- package/test/src/invalid_sync_config.test.ts +9 -0
- package/test/src/object_storage_lifecycle.test.ts +72 -2
- package/test/src/prepared_publication.test.ts +388 -0
- package/test/src/replication_preparation.test.ts +829 -0
- package/test/src/replication_publication_baseline.test.ts +203 -0
- package/test/src/replication_publication_batching.test.ts +212 -0
- package/test/src/replication_uploads.test.ts +393 -0
- package/test/src/source_table_config.test.ts +4 -4
- package/test/src/storage_object_storage_inline_threshold.test.ts +1 -1
- package/test/src/storage_s3_compaction_lifecycle.test.ts +93 -1
- package/test/src/storage_sync.test.ts +101 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { InternalOpId, storage } from '@powersync/service-core';
|
|
3
|
+
import { BucketDataSource, BucketDefinitionId } from '@powersync/service-sync-rules';
|
|
4
|
+
import { TaggedBucketParameterDocument } from '../models.js';
|
|
5
|
+
import { BucketDataDoc, BucketKey } from './BucketDataDoc.js';
|
|
6
|
+
import { BucketStateUpdate, SaveBucketDataOptions } from './PersistedBatch.js';
|
|
7
|
+
import { PublicationStats } from './PreparedPublication.js';
|
|
8
|
+
/**
|
|
9
|
+
* Shared operation generation, size accounting and diagnostics. Each storage
|
|
10
|
+
* version owns this buffer and decides when to write, retain or clear its data.
|
|
11
|
+
* No transaction, sealing or payload-preparation state lives here.
|
|
12
|
+
*/
|
|
13
|
+
export declare class BatchOperationBuffer {
|
|
14
|
+
private readonly group_id;
|
|
15
|
+
private readonly definitions;
|
|
16
|
+
private readonly logger;
|
|
17
|
+
bucketData: BucketDataDoc[];
|
|
18
|
+
bucketParameters: TaggedBucketParameterDocument[];
|
|
19
|
+
bucketStates: Map<string, BucketStateUpdate>;
|
|
20
|
+
/**
|
|
21
|
+
* For debug logging only.
|
|
22
|
+
*/
|
|
23
|
+
debugLastOpId: InternalOpId | null;
|
|
24
|
+
/**
|
|
25
|
+
* Very rough estimate of transaction size.
|
|
26
|
+
*/
|
|
27
|
+
currentSize: number;
|
|
28
|
+
constructor(group_id: number, writtenSize: number, definitions: {
|
|
29
|
+
checkDefinitionId(id: BucketDefinitionId | null): BucketDefinitionId;
|
|
30
|
+
getBucketDefinitionId(source: BucketDataSource): BucketDefinitionId;
|
|
31
|
+
}, logger?: Logger);
|
|
32
|
+
saveBucketData(options: SaveBucketDataOptions): void;
|
|
33
|
+
/**
|
|
34
|
+
* New bucket operations persist protocol subkeys during replication. Older
|
|
35
|
+
* V1 documents may not have one, so sync reads retain a fallback.
|
|
36
|
+
*/
|
|
37
|
+
persistedSubkey(table: storage.SourceTableId, key: storage.ReplicaId): string;
|
|
38
|
+
get bucketDataCount(): number;
|
|
39
|
+
incrementBucket(definitionId: BucketDefinitionId, bucket: string, op_id: InternalOpId, bytes: number): void;
|
|
40
|
+
/**
|
|
41
|
+
* V3 persists operations in chunks. Keep this separate from incrementBucket:
|
|
42
|
+
* operation counts are known while evaluating rows, while chunk counts and
|
|
43
|
+
* exact persisted bytes are only known after the writer has chunked a flush.
|
|
44
|
+
*/
|
|
45
|
+
incrementBucketPersistedChunk(definitionId: BucketDefinitionId, bucket: string, bytes: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* V3's compactor calculates byte deltas from persisted chunk metadata.
|
|
48
|
+
* Replace the writer's per-operation estimate with those exact sizes before
|
|
49
|
+
* flushing the corresponding bucket state.
|
|
50
|
+
*/
|
|
51
|
+
resetBucketPersistedBytes(definitionId: BucketDefinitionId, bucket: string): void;
|
|
52
|
+
addBucketDataPut(options: {
|
|
53
|
+
op_id: InternalOpId;
|
|
54
|
+
bucketKey: BucketKey;
|
|
55
|
+
bucket: string;
|
|
56
|
+
sourceTableId: storage.SourceTable['id'];
|
|
57
|
+
sourceKey: storage.ReplicaId;
|
|
58
|
+
subkey: string;
|
|
59
|
+
table: string;
|
|
60
|
+
rowId: string;
|
|
61
|
+
checksum: bigint;
|
|
62
|
+
data: string;
|
|
63
|
+
}): void;
|
|
64
|
+
addBucketDataRemove(options: {
|
|
65
|
+
op_id: InternalOpId;
|
|
66
|
+
bucketKey: BucketKey;
|
|
67
|
+
sourceTableId: storage.SourceTable['id'];
|
|
68
|
+
sourceKey: storage.ReplicaId;
|
|
69
|
+
subkey: string;
|
|
70
|
+
table: string;
|
|
71
|
+
rowId: string;
|
|
72
|
+
checksum: bigint;
|
|
73
|
+
}): void;
|
|
74
|
+
shouldFlushTransaction(currentDataCount: number): boolean;
|
|
75
|
+
/** Adopt one fully evaluated row; unfinished rows never mutate this buffer. */
|
|
76
|
+
append(row: BatchOperationBuffer): void;
|
|
77
|
+
clear(): void;
|
|
78
|
+
logFlush(startAt: number, currentDataCount: number, options?: storage.BucketBatchCommitOptions): PublicationStats;
|
|
79
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { logger as defaultLogger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { utils } from '@powersync/service-core';
|
|
3
|
+
import { JSONBig } from '@powersync/service-jsonbig';
|
|
4
|
+
import { mongoTableId, replicaIdToSubkey } from '../../../utils/util.js';
|
|
5
|
+
import { currentBucketKey, MAX_ROW_SIZE } from '../MongoBucketBatchShared.js';
|
|
6
|
+
/**
|
|
7
|
+
* Maximum size of operations we write in a single transaction.
|
|
8
|
+
*
|
|
9
|
+
* It's tricky to find the exact limit, but from experience, over 100MB
|
|
10
|
+
* can cause an error:
|
|
11
|
+
* > transaction is too large and will not fit in the storage engine cache
|
|
12
|
+
*
|
|
13
|
+
* Additionally, unbounded size here can balloon our memory usage in some edge
|
|
14
|
+
* cases.
|
|
15
|
+
*
|
|
16
|
+
* When we reach this threshold, we commit the transaction and start a new one.
|
|
17
|
+
*/
|
|
18
|
+
const MAX_TRANSACTION_BATCH_SIZE = 30_000_000;
|
|
19
|
+
/**
|
|
20
|
+
* Limit number of documents to write in a single transaction.
|
|
21
|
+
*
|
|
22
|
+
* This has an effect on error message size in some cases.
|
|
23
|
+
*/
|
|
24
|
+
const MAX_TRANSACTION_DOC_COUNT = 2_000;
|
|
25
|
+
/**
|
|
26
|
+
* Shared operation generation, size accounting and diagnostics. Each storage
|
|
27
|
+
* version owns this buffer and decides when to write, retain or clear its data.
|
|
28
|
+
* No transaction, sealing or payload-preparation state lives here.
|
|
29
|
+
*/
|
|
30
|
+
export class BatchOperationBuffer {
|
|
31
|
+
group_id;
|
|
32
|
+
definitions;
|
|
33
|
+
logger;
|
|
34
|
+
bucketData = [];
|
|
35
|
+
bucketParameters = [];
|
|
36
|
+
bucketStates = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* For debug logging only.
|
|
39
|
+
*/
|
|
40
|
+
debugLastOpId = null;
|
|
41
|
+
/**
|
|
42
|
+
* Very rough estimate of transaction size.
|
|
43
|
+
*/
|
|
44
|
+
currentSize;
|
|
45
|
+
constructor(group_id, writtenSize, definitions, logger = defaultLogger) {
|
|
46
|
+
this.group_id = group_id;
|
|
47
|
+
this.definitions = definitions;
|
|
48
|
+
this.logger = logger;
|
|
49
|
+
this.currentSize = writtenSize;
|
|
50
|
+
}
|
|
51
|
+
saveBucketData(options) {
|
|
52
|
+
const remaining_buckets = new Map();
|
|
53
|
+
for (let bucket of options.before_buckets) {
|
|
54
|
+
const mapped = {
|
|
55
|
+
bucket: bucket.bucket,
|
|
56
|
+
definitionId: this.definitions.checkDefinitionId(bucket.definitionId),
|
|
57
|
+
id: bucket.id,
|
|
58
|
+
table: bucket.table
|
|
59
|
+
};
|
|
60
|
+
if (options.table.bucketDataSourceIds != null && !options.table.bucketDataSourceIds.has(mapped.definitionId)) {
|
|
61
|
+
// The bucket definition is not active anymore.
|
|
62
|
+
// We don't cleanup these references upfront, but do need to ignore them after the definition is removed.
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
remaining_buckets.set(currentBucketKey(mapped), mapped);
|
|
66
|
+
}
|
|
67
|
+
const subkey = this.persistedSubkey(options.table.id, options.sourceKey);
|
|
68
|
+
const dchecksum = BigInt(utils.hashDelete(subkey));
|
|
69
|
+
for (const evaluated of options.evaluated) {
|
|
70
|
+
const definitionId = this.definitions.getBucketDefinitionId(evaluated.source);
|
|
71
|
+
const key = currentBucketKey({
|
|
72
|
+
definitionId: definitionId,
|
|
73
|
+
bucket: evaluated.bucket,
|
|
74
|
+
table: evaluated.table,
|
|
75
|
+
id: evaluated.id
|
|
76
|
+
});
|
|
77
|
+
const recordData = JSONBig.stringify(evaluated.data);
|
|
78
|
+
const checksum = utils.hashData(evaluated.table, evaluated.id, recordData);
|
|
79
|
+
if (recordData.length > MAX_ROW_SIZE) {
|
|
80
|
+
const message = `Row ${key} too large: ${recordData.length} bytes. Removing.`;
|
|
81
|
+
this.logger.error(message);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
remaining_buckets.delete(key);
|
|
85
|
+
const byteEstimate = recordData.length + 200;
|
|
86
|
+
this.currentSize += byteEstimate;
|
|
87
|
+
const op_id = options.op_seq.next();
|
|
88
|
+
this.debugLastOpId = op_id;
|
|
89
|
+
this.addBucketDataPut({
|
|
90
|
+
bucketKey: {
|
|
91
|
+
bucket: evaluated.bucket,
|
|
92
|
+
definitionId: definitionId,
|
|
93
|
+
replicationStreamId: this.group_id
|
|
94
|
+
},
|
|
95
|
+
op_id,
|
|
96
|
+
bucket: evaluated.bucket,
|
|
97
|
+
sourceTableId: options.table.id,
|
|
98
|
+
sourceKey: options.sourceKey,
|
|
99
|
+
subkey,
|
|
100
|
+
table: evaluated.table,
|
|
101
|
+
rowId: evaluated.id,
|
|
102
|
+
checksum: BigInt(checksum),
|
|
103
|
+
data: recordData
|
|
104
|
+
});
|
|
105
|
+
this.incrementBucket(definitionId, evaluated.bucket, op_id, byteEstimate);
|
|
106
|
+
}
|
|
107
|
+
for (let bucket of remaining_buckets.values()) {
|
|
108
|
+
const definitionId = bucket.definitionId;
|
|
109
|
+
const op_id = options.op_seq.next();
|
|
110
|
+
this.debugLastOpId = op_id;
|
|
111
|
+
this.addBucketDataRemove({
|
|
112
|
+
bucketKey: {
|
|
113
|
+
replicationStreamId: this.group_id,
|
|
114
|
+
definitionId,
|
|
115
|
+
bucket: bucket.bucket
|
|
116
|
+
},
|
|
117
|
+
op_id,
|
|
118
|
+
sourceTableId: options.table.id,
|
|
119
|
+
sourceKey: options.sourceKey,
|
|
120
|
+
subkey,
|
|
121
|
+
table: bucket.table,
|
|
122
|
+
rowId: bucket.id,
|
|
123
|
+
checksum: dchecksum
|
|
124
|
+
});
|
|
125
|
+
this.currentSize += 200;
|
|
126
|
+
this.incrementBucket(definitionId, bucket.bucket, op_id, 200);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* New bucket operations persist protocol subkeys during replication. Older
|
|
131
|
+
* V1 documents may not have one, so sync reads retain a fallback.
|
|
132
|
+
*/
|
|
133
|
+
persistedSubkey(table, key) {
|
|
134
|
+
return replicaIdToSubkey(table, key);
|
|
135
|
+
}
|
|
136
|
+
get bucketDataCount() {
|
|
137
|
+
return this.bucketData.length;
|
|
138
|
+
}
|
|
139
|
+
incrementBucket(definitionId, bucket, op_id, bytes) {
|
|
140
|
+
const key = `${definitionId ?? ''}:${bucket}`;
|
|
141
|
+
let existingState = this.bucketStates.get(key);
|
|
142
|
+
if (existingState) {
|
|
143
|
+
existingState.lastOp = op_id;
|
|
144
|
+
existingState.incrementCount += 1;
|
|
145
|
+
existingState.incrementBytes += bytes;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.bucketStates.set(key, {
|
|
149
|
+
definitionId,
|
|
150
|
+
bucket,
|
|
151
|
+
lastOp: op_id,
|
|
152
|
+
incrementCount: 1,
|
|
153
|
+
incrementBytes: bytes,
|
|
154
|
+
incrementChunks: 0
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* V3 persists operations in chunks. Keep this separate from incrementBucket:
|
|
160
|
+
* operation counts are known while evaluating rows, while chunk counts and
|
|
161
|
+
* exact persisted bytes are only known after the writer has chunked a flush.
|
|
162
|
+
*/
|
|
163
|
+
incrementBucketPersistedChunk(definitionId, bucket, bytes) {
|
|
164
|
+
const key = `${definitionId ?? ''}:${bucket}`;
|
|
165
|
+
const existingState = this.bucketStates.get(key);
|
|
166
|
+
if (existingState != null) {
|
|
167
|
+
existingState.incrementChunks += 1;
|
|
168
|
+
existingState.incrementBytes += bytes;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* V3's compactor calculates byte deltas from persisted chunk metadata.
|
|
173
|
+
* Replace the writer's per-operation estimate with those exact sizes before
|
|
174
|
+
* flushing the corresponding bucket state.
|
|
175
|
+
*/
|
|
176
|
+
resetBucketPersistedBytes(definitionId, bucket) {
|
|
177
|
+
const state = this.bucketStates.get(`${definitionId ?? ''}:${bucket}`);
|
|
178
|
+
if (state != null) {
|
|
179
|
+
state.incrementBytes = 0;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
addBucketDataPut(options) {
|
|
183
|
+
this.bucketData.push({
|
|
184
|
+
bucketKey: options.bucketKey,
|
|
185
|
+
o: options.op_id,
|
|
186
|
+
op: 'PUT',
|
|
187
|
+
source_table: mongoTableId(options.sourceTableId),
|
|
188
|
+
source_key: options.sourceKey,
|
|
189
|
+
subkey: options.subkey,
|
|
190
|
+
table: options.table,
|
|
191
|
+
row_id: options.rowId,
|
|
192
|
+
checksum: options.checksum,
|
|
193
|
+
data: options.data
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
addBucketDataRemove(options) {
|
|
197
|
+
this.bucketData.push({
|
|
198
|
+
bucketKey: options.bucketKey,
|
|
199
|
+
o: options.op_id,
|
|
200
|
+
op: 'REMOVE',
|
|
201
|
+
source_table: mongoTableId(options.sourceTableId),
|
|
202
|
+
source_key: options.sourceKey,
|
|
203
|
+
subkey: options.subkey,
|
|
204
|
+
table: options.table,
|
|
205
|
+
row_id: options.rowId,
|
|
206
|
+
checksum: options.checksum,
|
|
207
|
+
data: null
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
shouldFlushTransaction(currentDataCount) {
|
|
211
|
+
return (this.currentSize >= MAX_TRANSACTION_BATCH_SIZE ||
|
|
212
|
+
this.bucketDataCount >= MAX_TRANSACTION_DOC_COUNT ||
|
|
213
|
+
currentDataCount >= MAX_TRANSACTION_DOC_COUNT ||
|
|
214
|
+
this.bucketParameters.length >= MAX_TRANSACTION_DOC_COUNT);
|
|
215
|
+
}
|
|
216
|
+
/** Adopt one fully evaluated row; unfinished rows never mutate this buffer. */
|
|
217
|
+
append(row) {
|
|
218
|
+
// A single high-fanout row may exceed a normal batch target. Avoid the
|
|
219
|
+
// JavaScript argument-count limit while retaining its operation order.
|
|
220
|
+
for (const operation of row.bucketData) {
|
|
221
|
+
this.bucketData.push(operation);
|
|
222
|
+
}
|
|
223
|
+
for (const parameter of row.bucketParameters) {
|
|
224
|
+
this.bucketParameters.push(parameter);
|
|
225
|
+
}
|
|
226
|
+
for (const [key, state] of row.bucketStates) {
|
|
227
|
+
const previous = this.bucketStates.get(key);
|
|
228
|
+
this.bucketStates.set(key, {
|
|
229
|
+
...state,
|
|
230
|
+
incrementCount: (previous?.incrementCount ?? 0) + state.incrementCount,
|
|
231
|
+
incrementBytes: (previous?.incrementBytes ?? 0) + state.incrementBytes,
|
|
232
|
+
incrementChunks: (previous?.incrementChunks ?? 0) + state.incrementChunks
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
this.currentSize += row.currentSize;
|
|
236
|
+
this.debugLastOpId = row.debugLastOpId ?? this.debugLastOpId;
|
|
237
|
+
}
|
|
238
|
+
clear() {
|
|
239
|
+
this.bucketData = [];
|
|
240
|
+
this.bucketParameters = [];
|
|
241
|
+
this.bucketStates.clear();
|
|
242
|
+
this.currentSize = 0;
|
|
243
|
+
this.debugLastOpId = null;
|
|
244
|
+
}
|
|
245
|
+
logFlush(startAt, currentDataCount, options) {
|
|
246
|
+
const flushedSomething = this.bucketDataCount > 0 ||
|
|
247
|
+
this.bucketParameters.length > 0 ||
|
|
248
|
+
currentDataCount > 0 ||
|
|
249
|
+
this.bucketStates.size > 0;
|
|
250
|
+
if (flushedSomething) {
|
|
251
|
+
const duration = Math.round(performance.now() - startAt);
|
|
252
|
+
if (options?.oldestUncommittedChange != null) {
|
|
253
|
+
const replicationLag = Math.round((Date.now() - options.oldestUncommittedChange.getTime()) / 1000);
|
|
254
|
+
this.logger.info(`Flushed: ${this.bucketDataCount} ops, ${this.bucketParameters.length} index entries, ${currentDataCount} records. ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}. Replication lag: ${replicationLag}s`, {
|
|
255
|
+
flushed: {
|
|
256
|
+
duration: duration,
|
|
257
|
+
size: this.currentSize,
|
|
258
|
+
bucket_ops_count: this.bucketDataCount,
|
|
259
|
+
parameter_indexes_count: this.bucketParameters.length,
|
|
260
|
+
source_records_count: currentDataCount,
|
|
261
|
+
replication_lag_seconds: replicationLag
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
this.logger.info(`Flushed: ${this.bucketDataCount} ops, ${this.bucketParameters.length} index entries, ${currentDataCount} records. ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}`, {
|
|
267
|
+
flushed: {
|
|
268
|
+
duration: duration,
|
|
269
|
+
size: this.currentSize,
|
|
270
|
+
bucket_ops_count: this.bucketDataCount,
|
|
271
|
+
parameter_indexes_count: this.bucketParameters.length,
|
|
272
|
+
source_records_count: currentDataCount
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const stats = {
|
|
278
|
+
bucketDataCount: this.bucketDataCount,
|
|
279
|
+
parameterDataCount: this.bucketParameters.length,
|
|
280
|
+
currentDataCount: currentDataCount,
|
|
281
|
+
flushedAny: flushedSomething
|
|
282
|
+
};
|
|
283
|
+
return stats;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=BatchOperationBuffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BatchOperationBuffer.js","sourceRoot":"","sources":["../../../../src/storage/implementation/common/BatchOperationBuffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
-
import { BucketDataSource, BucketDefinitionId, EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
3
|
-
import * as bson from 'bson';
|
|
4
1
|
import { Logger } from '@powersync/lib-services-framework';
|
|
5
|
-
import {
|
|
2
|
+
import { InternalOpId, storage } from '@powersync/service-core';
|
|
3
|
+
import { BucketDefinitionId, EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
4
|
+
import * as bson from 'bson';
|
|
6
5
|
import { MongoIdSequence } from '../MongoIdSequence.js';
|
|
7
|
-
import { MongoWriteBatch } from '../MongoWriteBatch.js';
|
|
8
|
-
import type { VersionedPowerSyncMongo } from '../db.js';
|
|
9
|
-
import { TaggedBucketParameterDocument } from '../models.js';
|
|
10
|
-
import { ObjectStorage } from '../v3/object-storage/ObjectStorage.js';
|
|
11
|
-
import { BucketDataDoc, BucketKey } from './BucketDataDoc.js';
|
|
12
6
|
import { SourceRecordBucketState, SourceRecordLookupState } from './SourceRecordStore.js';
|
|
13
|
-
export declare const DEFAULT_INLINE_THRESHOLD_BYTES: number;
|
|
14
7
|
export interface SaveBucketDataOptions {
|
|
15
8
|
op_seq: MongoIdSequence;
|
|
16
9
|
sourceKey: storage.ReplicaId;
|
|
@@ -34,102 +27,16 @@ export interface UpsertCurrentDataOptions {
|
|
|
34
27
|
}
|
|
35
28
|
export interface PersistedBatchOptions {
|
|
36
29
|
logger?: Logger;
|
|
37
|
-
objectStorage?: ObjectStorage;
|
|
38
|
-
inlineThresholdBytes?: number;
|
|
39
|
-
/**
|
|
40
|
-
* Aborts in-flight object storage uploads when replication stops.
|
|
41
|
-
*/
|
|
42
|
-
signal?: AbortSignal;
|
|
43
|
-
objectStorageUsageWriterId?: string;
|
|
44
30
|
}
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
* There may be multiple of these batches per transaction, but it may not span
|
|
49
|
-
* multiple transactions.
|
|
50
|
-
*/
|
|
51
|
-
export declare abstract class PersistedBatch {
|
|
52
|
-
protected readonly db: VersionedPowerSyncMongo;
|
|
53
|
-
protected readonly group_id: number;
|
|
54
|
-
protected readonly mapping: BucketDefinitionMapping;
|
|
55
|
-
logger: Logger;
|
|
56
|
-
bucketData: BucketDataDoc[];
|
|
57
|
-
bucketParameters: TaggedBucketParameterDocument[];
|
|
58
|
-
bucketStates: Map<string, BucketStateUpdate>;
|
|
59
|
-
protected readonly objectStorage?: ObjectStorage;
|
|
60
|
-
protected readonly inlineThresholdBytes: number;
|
|
61
|
-
protected readonly signal?: AbortSignal;
|
|
62
|
-
protected readonly objectStorageUsageWriterId?: string;
|
|
63
|
-
/**
|
|
64
|
-
* For debug logging only.
|
|
65
|
-
*/
|
|
66
|
-
debugLastOpId: InternalOpId | null;
|
|
67
|
-
/**
|
|
68
|
-
* Very rough estimate of transaction size.
|
|
69
|
-
*/
|
|
70
|
-
currentSize: number;
|
|
71
|
-
constructor(db: VersionedPowerSyncMongo, group_id: number, mapping: BucketDefinitionMapping, writtenSize: number, options?: PersistedBatchOptions);
|
|
31
|
+
/** Operations used by the shared writer; each storage version owns its lifecycle. */
|
|
32
|
+
export interface PersistedBatch {
|
|
33
|
+
readonly currentSize: number;
|
|
72
34
|
saveBucketData(options: SaveBucketDataOptions): void;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
protected abstract get currentDataCount(): number;
|
|
78
|
-
protected abstract queueBucketData(writes: MongoWriteBatch): Promise<void>;
|
|
79
|
-
protected abstract queueBucketParameters(writes: MongoWriteBatch): void;
|
|
80
|
-
protected abstract queueCurrentData(writes: MongoWriteBatch): void;
|
|
81
|
-
protected abstract queueBucketStates(writes: MongoWriteBatch): void;
|
|
82
|
-
protected abstract resetCurrentData(): void;
|
|
83
|
-
protected abstract checkDefinitionId(definitionId: BucketDefinitionId | null): BucketDefinitionId;
|
|
84
|
-
protected abstract getBucketDefinitionId(bucketSource: BucketDataSource): BucketDefinitionId;
|
|
85
|
-
/**
|
|
86
|
-
* New bucket operations persist protocol subkeys during replication. Older
|
|
87
|
-
* V1 documents may not have one, so sync reads retain a fallback.
|
|
88
|
-
*/
|
|
89
|
-
protected persistedSubkey(table: storage.SourceTableId, key: storage.ReplicaId): string;
|
|
90
|
-
protected get bucketDataCount(): number;
|
|
91
|
-
protected incrementBucket(definitionId: BucketDefinitionId, bucket: string, op_id: InternalOpId, bytes: number): void;
|
|
92
|
-
/**
|
|
93
|
-
* V3 persists operations in chunks. Keep this separate from incrementBucket:
|
|
94
|
-
* operation counts are known while evaluating rows, while chunk counts and
|
|
95
|
-
* exact persisted bytes are only known after the writer has chunked a flush.
|
|
96
|
-
*/
|
|
97
|
-
protected incrementBucketPersistedChunk(definitionId: BucketDefinitionId, bucket: string, bytes: number): void;
|
|
98
|
-
/**
|
|
99
|
-
* V3's compactor calculates byte deltas from persisted chunk metadata.
|
|
100
|
-
* Replace the writer's per-operation estimate with those exact sizes before
|
|
101
|
-
* flushing the corresponding bucket state.
|
|
102
|
-
*/
|
|
103
|
-
protected resetBucketPersistedBytes(definitionId: BucketDefinitionId, bucket: string): void;
|
|
104
|
-
protected addBucketDataPut(options: {
|
|
105
|
-
op_id: InternalOpId;
|
|
106
|
-
bucketKey: BucketKey;
|
|
107
|
-
bucket: string;
|
|
108
|
-
sourceTableId: storage.SourceTable['id'];
|
|
109
|
-
sourceKey: storage.ReplicaId;
|
|
110
|
-
subkey: string;
|
|
111
|
-
table: string;
|
|
112
|
-
rowId: string;
|
|
113
|
-
checksum: bigint;
|
|
114
|
-
data: string;
|
|
115
|
-
}): void;
|
|
116
|
-
protected addBucketDataRemove(options: {
|
|
117
|
-
op_id: InternalOpId;
|
|
118
|
-
bucketKey: BucketKey;
|
|
119
|
-
sourceTableId: storage.SourceTable['id'];
|
|
120
|
-
sourceKey: storage.ReplicaId;
|
|
121
|
-
subkey: string;
|
|
122
|
-
table: string;
|
|
123
|
-
rowId: string;
|
|
124
|
-
checksum: bigint;
|
|
125
|
-
}): void;
|
|
35
|
+
saveParameterData(options: SaveParameterDataOptions): void;
|
|
36
|
+
hardDeleteCurrentData(sourceTableId: bson.ObjectId, replicaId: storage.ReplicaId): void;
|
|
37
|
+
softDeleteCurrentData(sourceTableId: bson.ObjectId, replicaId: storage.ReplicaId, checkpointGreaterThan: bigint): void;
|
|
38
|
+
upsertCurrentData(values: UpsertCurrentDataOptions): void;
|
|
126
39
|
shouldFlushTransaction(): boolean;
|
|
127
|
-
flush(session: mongo.ClientSession, options?: storage.BucketBatchCommitOptions): Promise<{
|
|
128
|
-
bucketDataCount: number;
|
|
129
|
-
parameterDataCount: number;
|
|
130
|
-
currentDataCount: number;
|
|
131
|
-
flushedAny: boolean;
|
|
132
|
-
}>;
|
|
133
40
|
}
|
|
134
41
|
export interface BucketStateUpdate {
|
|
135
42
|
definitionId: BucketDefinitionId | null;
|