@powersync/service-module-mongodb-storage 0.9.5 → 0.10.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 +23 -0
- package/dist/migrations/db/migrations/1749720702136-checkpoint-events.d.ts +3 -0
- package/dist/migrations/db/migrations/1749720702136-checkpoint-events.js +34 -0
- package/dist/migrations/db/migrations/1749720702136-checkpoint-events.js.map +1 -0
- package/dist/storage/MongoBucketStorage.js +5 -0
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +9 -3
- package/dist/storage/implementation/MongoBucketBatch.js +116 -36
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +1 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +2 -0
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/implementation/MongoStorageProvider.js +23 -1
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +14 -5
- package/dist/storage/implementation/MongoSyncBucketStorage.js +161 -159
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js +2 -0
- package/dist/storage/implementation/MongoTestStorageFactoryGenerator.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +9 -15
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +55 -191
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/PersistedBatch.d.ts +6 -2
- package/dist/storage/implementation/PersistedBatch.js +38 -6
- package/dist/storage/implementation/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/db.d.ts +12 -1
- package/dist/storage/implementation/db.js +39 -0
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +29 -1
- package/package.json +6 -6
- package/src/migrations/db/migrations/1749720702136-checkpoint-events.ts +50 -0
- package/src/storage/MongoBucketStorage.ts +5 -0
- package/src/storage/implementation/MongoBucketBatch.ts +159 -48
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +2 -0
- package/src/storage/implementation/MongoStorageProvider.ts +27 -1
- package/src/storage/implementation/MongoSyncBucketStorage.ts +187 -200
- package/src/storage/implementation/MongoTestStorageFactoryGenerator.ts +3 -0
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +66 -255
- package/src/storage/implementation/PersistedBatch.ts +49 -10
- package/src/storage/implementation/db.ts +42 -0
- package/src/storage/implementation/models.ts +32 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { GetCheckpointChangesOptions, InternalOpId, storage } from '@powersync/service-core';
|
|
2
3
|
import { PowerSyncMongo } from './db.js';
|
|
3
4
|
export type MongoCheckpointAPIOptions = {
|
|
4
5
|
db: PowerSyncMongo;
|
|
@@ -12,22 +13,15 @@ export declare class MongoWriteCheckpointAPI implements storage.WriteCheckpointA
|
|
|
12
13
|
constructor(options: MongoCheckpointAPIOptions);
|
|
13
14
|
get writeCheckpointMode(): storage.WriteCheckpointMode;
|
|
14
15
|
setWriteCheckpointMode(mode: storage.WriteCheckpointMode): void;
|
|
15
|
-
batchCreateCustomWriteCheckpoints(checkpoints: storage.CustomWriteCheckpointOptions[]): Promise<void>;
|
|
16
16
|
createManagedWriteCheckpoint(checkpoint: storage.ManagedWriteCheckpointOptions): Promise<bigint>;
|
|
17
17
|
lastWriteCheckpoint(filters: storage.LastWriteCheckpointFilters): Promise<bigint | null>;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
private sharedCustomIter;
|
|
23
|
-
private watchAllCustomWriteCheckpoints;
|
|
24
|
-
watchCustomWriteCheckpoint(options: WatchUserWriteCheckpointOptions): AsyncIterable<storage.WriteCheckpointResult>;
|
|
18
|
+
getWriteCheckpointChanges(options: GetCheckpointChangesOptions): Promise<{
|
|
19
|
+
invalidateWriteCheckpoints: boolean;
|
|
20
|
+
updatedWriteCheckpoints: Map<string, bigint>;
|
|
21
|
+
}>;
|
|
25
22
|
protected lastCustomWriteCheckpoint(filters: storage.CustomWriteCheckpointFilters): Promise<bigint | null>;
|
|
26
23
|
protected lastManagedWriteCheckpoint(filters: storage.ManagedWriteCheckpointFilters): Promise<bigint | null>;
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
* Makes a write checkpoint stream an orderered one - any out-of-order events are discarded.
|
|
30
|
-
*/
|
|
31
|
-
private orderedStream;
|
|
24
|
+
private getManagedWriteCheckpointChanges;
|
|
25
|
+
private getCustomWriteCheckpointChanges;
|
|
32
26
|
}
|
|
33
|
-
export declare function batchCreateCustomWriteCheckpoints(db: PowerSyncMongo, checkpoints: storage.CustomWriteCheckpointOptions[]): Promise<void>;
|
|
27
|
+
export declare function batchCreateCustomWriteCheckpoints(db: PowerSyncMongo, session: mongo.ClientSession, checkpoints: storage.CustomWriteCheckpointOptions[], opId: InternalOpId): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as framework from '@powersync/lib-services-framework';
|
|
2
|
-
import {
|
|
2
|
+
import { storage } from '@powersync/service-core';
|
|
3
3
|
export class MongoWriteCheckpointAPI {
|
|
4
4
|
db;
|
|
5
5
|
_mode;
|
|
@@ -15,19 +15,17 @@ export class MongoWriteCheckpointAPI {
|
|
|
15
15
|
setWriteCheckpointMode(mode) {
|
|
16
16
|
this._mode = mode;
|
|
17
17
|
}
|
|
18
|
-
async batchCreateCustomWriteCheckpoints(checkpoints) {
|
|
19
|
-
return batchCreateCustomWriteCheckpoints(this.db, checkpoints);
|
|
20
|
-
}
|
|
21
18
|
async createManagedWriteCheckpoint(checkpoint) {
|
|
22
19
|
if (this.writeCheckpointMode !== storage.WriteCheckpointMode.MANAGED) {
|
|
23
|
-
throw new framework.
|
|
20
|
+
throw new framework.ServiceAssertionError(`Attempting to create a managed Write Checkpoint when the current Write Checkpoint mode is set to "${this.writeCheckpointMode}"`);
|
|
24
21
|
}
|
|
25
22
|
const { user_id, heads: lsns } = checkpoint;
|
|
26
23
|
const doc = await this.db.write_checkpoints.findOneAndUpdate({
|
|
27
24
|
user_id: user_id
|
|
28
25
|
}, {
|
|
29
26
|
$set: {
|
|
30
|
-
lsns
|
|
27
|
+
lsns,
|
|
28
|
+
processed_at_lsn: null
|
|
31
29
|
},
|
|
32
30
|
$inc: {
|
|
33
31
|
client_id: 1n
|
|
@@ -39,184 +37,24 @@ export class MongoWriteCheckpointAPI {
|
|
|
39
37
|
switch (this.writeCheckpointMode) {
|
|
40
38
|
case storage.WriteCheckpointMode.CUSTOM:
|
|
41
39
|
if (false == 'sync_rules_id' in filters) {
|
|
42
|
-
throw new framework.
|
|
40
|
+
throw new framework.ServiceAssertionError(`Sync rules ID is required for custom Write Checkpoint filtering`);
|
|
43
41
|
}
|
|
44
42
|
return this.lastCustomWriteCheckpoint(filters);
|
|
45
43
|
case storage.WriteCheckpointMode.MANAGED:
|
|
46
44
|
if (false == 'heads' in filters) {
|
|
47
|
-
throw new framework.
|
|
45
|
+
throw new framework.ServiceAssertionError(`Replication HEAD is required for managed Write Checkpoint filtering`);
|
|
48
46
|
}
|
|
49
47
|
return this.lastManagedWriteCheckpoint(filters);
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
|
-
|
|
50
|
+
async getWriteCheckpointChanges(options) {
|
|
53
51
|
switch (this.writeCheckpointMode) {
|
|
54
52
|
case storage.WriteCheckpointMode.CUSTOM:
|
|
55
|
-
return this.
|
|
53
|
+
return this.getCustomWriteCheckpointChanges(options);
|
|
56
54
|
case storage.WriteCheckpointMode.MANAGED:
|
|
57
|
-
return this.
|
|
58
|
-
default:
|
|
59
|
-
throw new Error('Invalid write checkpoint mode');
|
|
55
|
+
return this.getManagedWriteCheckpointChanges(options);
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
|
-
sharedManagedIter = new Demultiplexer((signal) => {
|
|
63
|
-
const clusterTimePromise = this.getClusterTime();
|
|
64
|
-
return {
|
|
65
|
-
iterator: this.watchAllManagedWriteCheckpoints(clusterTimePromise, signal),
|
|
66
|
-
getFirstValue: async (user_id) => {
|
|
67
|
-
// Potential race conditions we cater for:
|
|
68
|
-
// Case 1: changestream is behind.
|
|
69
|
-
// We get a doc now, then the same or older doc again later.
|
|
70
|
-
// No problem!
|
|
71
|
-
// Case 2: Query is behind. I.e. doc has been created, and emitted on the changestream, but the query doesn't see it yet.
|
|
72
|
-
// Not possible luckily, but can we make sure?
|
|
73
|
-
// Case 3: changestream delays openeing. A doc is created after our query here, but before the changestream is opened.
|
|
74
|
-
// Awaiting clusterTimePromise should be sufficient here, but as a sanity check we also confirm that our query
|
|
75
|
-
// timestamp is > the startClusterTime.
|
|
76
|
-
const changeStreamStart = await clusterTimePromise;
|
|
77
|
-
let doc = null;
|
|
78
|
-
let clusterTime = null;
|
|
79
|
-
await this.db.client.withSession(async (session) => {
|
|
80
|
-
doc = await this.db.write_checkpoints.findOne({
|
|
81
|
-
user_id: user_id
|
|
82
|
-
}, {
|
|
83
|
-
session
|
|
84
|
-
});
|
|
85
|
-
const time = session.clusterTime?.clusterTime ?? null;
|
|
86
|
-
clusterTime = time;
|
|
87
|
-
});
|
|
88
|
-
if (clusterTime == null) {
|
|
89
|
-
throw new framework.ServiceAssertionError('Could not get clusterTime for write checkpoint');
|
|
90
|
-
}
|
|
91
|
-
if (clusterTime.lessThan(changeStreamStart)) {
|
|
92
|
-
throw new framework.ServiceAssertionError('clusterTime for write checkpoint is older than changestream start');
|
|
93
|
-
}
|
|
94
|
-
if (doc == null) {
|
|
95
|
-
return {
|
|
96
|
-
id: null,
|
|
97
|
-
lsn: null
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
id: doc.client_id,
|
|
102
|
-
lsn: doc.lsns['1']
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
async *watchAllManagedWriteCheckpoints(clusterTimePromise, signal) {
|
|
108
|
-
const clusterTime = await clusterTimePromise;
|
|
109
|
-
const stream = this.db.write_checkpoints.watch([{ $match: { operationType: { $in: ['insert', 'update', 'replace'] } } }], {
|
|
110
|
-
fullDocument: 'updateLookup',
|
|
111
|
-
startAtOperationTime: clusterTime
|
|
112
|
-
});
|
|
113
|
-
signal.onabort = () => {
|
|
114
|
-
stream.close();
|
|
115
|
-
};
|
|
116
|
-
if (signal.aborted) {
|
|
117
|
-
stream.close();
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
for await (let event of stream) {
|
|
121
|
-
if (!('fullDocument' in event) || event.fullDocument == null) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
const user_id = event.fullDocument.user_id;
|
|
125
|
-
yield {
|
|
126
|
-
key: user_id,
|
|
127
|
-
value: {
|
|
128
|
-
id: event.fullDocument.client_id,
|
|
129
|
-
lsn: event.fullDocument.lsns['1']
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
watchManagedWriteCheckpoint(options) {
|
|
135
|
-
const stream = this.sharedManagedIter.subscribe(options.user_id, options.signal);
|
|
136
|
-
return this.orderedStream(stream);
|
|
137
|
-
}
|
|
138
|
-
sharedCustomIter = new Demultiplexer((signal) => {
|
|
139
|
-
const clusterTimePromise = this.getClusterTime();
|
|
140
|
-
return {
|
|
141
|
-
iterator: this.watchAllCustomWriteCheckpoints(clusterTimePromise, signal),
|
|
142
|
-
getFirstValue: async (user_id) => {
|
|
143
|
-
// We cater for the same potential race conditions as for managed write checkpoints.
|
|
144
|
-
const changeStreamStart = await clusterTimePromise;
|
|
145
|
-
let doc = null;
|
|
146
|
-
let clusterTime = null;
|
|
147
|
-
await this.db.client.withSession(async (session) => {
|
|
148
|
-
doc = await this.db.custom_write_checkpoints.findOne({
|
|
149
|
-
user_id: user_id,
|
|
150
|
-
sync_rules_id: this.sync_rules_id
|
|
151
|
-
}, {
|
|
152
|
-
session
|
|
153
|
-
});
|
|
154
|
-
const time = session.clusterTime?.clusterTime ?? null;
|
|
155
|
-
clusterTime = time;
|
|
156
|
-
});
|
|
157
|
-
if (clusterTime == null) {
|
|
158
|
-
throw new framework.ServiceAssertionError('Could not get clusterTime for write checkpoint');
|
|
159
|
-
}
|
|
160
|
-
if (clusterTime.lessThan(changeStreamStart)) {
|
|
161
|
-
throw new framework.ServiceAssertionError('clusterTime for write checkpoint is older than changestream start');
|
|
162
|
-
}
|
|
163
|
-
if (doc == null) {
|
|
164
|
-
// No write checkpoint, but we still need to return a result
|
|
165
|
-
return {
|
|
166
|
-
id: null,
|
|
167
|
-
lsn: null
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
id: doc.checkpoint,
|
|
172
|
-
// custom write checkpoints are not tied to a LSN
|
|
173
|
-
lsn: null
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
async *watchAllCustomWriteCheckpoints(clusterTimePromise, signal) {
|
|
179
|
-
const clusterTime = await clusterTimePromise;
|
|
180
|
-
const stream = this.db.custom_write_checkpoints.watch([
|
|
181
|
-
{
|
|
182
|
-
$match: {
|
|
183
|
-
'fullDocument.sync_rules_id': this.sync_rules_id,
|
|
184
|
-
operationType: { $in: ['insert', 'update', 'replace'] }
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
], {
|
|
188
|
-
fullDocument: 'updateLookup',
|
|
189
|
-
startAtOperationTime: clusterTime
|
|
190
|
-
});
|
|
191
|
-
signal.onabort = () => {
|
|
192
|
-
stream.close();
|
|
193
|
-
};
|
|
194
|
-
if (signal.aborted) {
|
|
195
|
-
stream.close();
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
for await (let event of stream) {
|
|
199
|
-
if (!('fullDocument' in event) || event.fullDocument == null) {
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
const user_id = event.fullDocument.user_id;
|
|
203
|
-
yield {
|
|
204
|
-
key: user_id,
|
|
205
|
-
value: {
|
|
206
|
-
id: event.fullDocument.checkpoint,
|
|
207
|
-
// Custom write checkpoints are not tied to a specific LSN
|
|
208
|
-
lsn: null
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
watchCustomWriteCheckpoint(options) {
|
|
214
|
-
if (options.sync_rules_id != this.sync_rules_id) {
|
|
215
|
-
throw new framework.ServiceAssertionError('sync_rules_id does not match');
|
|
216
|
-
}
|
|
217
|
-
const stream = this.sharedCustomIter.subscribe(options.user_id, options.signal);
|
|
218
|
-
return this.orderedStream(stream);
|
|
219
|
-
}
|
|
220
58
|
async lastCustomWriteCheckpoint(filters) {
|
|
221
59
|
const { user_id, sync_rules_id } = filters;
|
|
222
60
|
const lastWriteCheckpoint = await this.db.custom_write_checkpoints.findOne({
|
|
@@ -239,29 +77,54 @@ export class MongoWriteCheckpointAPI {
|
|
|
239
77
|
});
|
|
240
78
|
return lastWriteCheckpoint?.client_id ?? null;
|
|
241
79
|
}
|
|
242
|
-
async
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
80
|
+
async getManagedWriteCheckpointChanges(options) {
|
|
81
|
+
const limit = 1000;
|
|
82
|
+
const changes = await this.db.write_checkpoints
|
|
83
|
+
.find({
|
|
84
|
+
processed_at_lsn: { $gt: options.lastCheckpoint.lsn, $lte: options.nextCheckpoint.lsn }
|
|
85
|
+
}, {
|
|
86
|
+
limit: limit + 1,
|
|
87
|
+
batchSize: limit + 1,
|
|
88
|
+
singleBatch: true
|
|
89
|
+
})
|
|
90
|
+
.toArray();
|
|
91
|
+
const invalidate = changes.length > limit;
|
|
92
|
+
const updatedWriteCheckpoints = new Map();
|
|
93
|
+
if (!invalidate) {
|
|
94
|
+
for (let c of changes) {
|
|
95
|
+
updatedWriteCheckpoints.set(c.user_id, c.client_id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
invalidateWriteCheckpoints: invalidate,
|
|
100
|
+
updatedWriteCheckpoints
|
|
101
|
+
};
|
|
247
102
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
103
|
+
async getCustomWriteCheckpointChanges(options) {
|
|
104
|
+
const limit = 1000;
|
|
105
|
+
const changes = await this.db.custom_write_checkpoints
|
|
106
|
+
.find({
|
|
107
|
+
op_id: { $gt: options.lastCheckpoint.checkpoint, $lte: options.nextCheckpoint.checkpoint }
|
|
108
|
+
}, {
|
|
109
|
+
limit: limit + 1,
|
|
110
|
+
batchSize: limit + 1,
|
|
111
|
+
singleBatch: true
|
|
112
|
+
})
|
|
113
|
+
.toArray();
|
|
114
|
+
const invalidate = changes.length > limit;
|
|
115
|
+
const updatedWriteCheckpoints = new Map();
|
|
116
|
+
if (!invalidate) {
|
|
117
|
+
for (let c of changes) {
|
|
118
|
+
updatedWriteCheckpoints.set(c.user_id, c.checkpoint);
|
|
260
119
|
}
|
|
261
120
|
}
|
|
121
|
+
return {
|
|
122
|
+
invalidateWriteCheckpoints: invalidate,
|
|
123
|
+
updatedWriteCheckpoints
|
|
124
|
+
};
|
|
262
125
|
}
|
|
263
126
|
}
|
|
264
|
-
export async function batchCreateCustomWriteCheckpoints(db, checkpoints) {
|
|
127
|
+
export async function batchCreateCustomWriteCheckpoints(db, session, checkpoints, opId) {
|
|
265
128
|
if (checkpoints.length == 0) {
|
|
266
129
|
return;
|
|
267
130
|
}
|
|
@@ -271,11 +134,12 @@ export async function batchCreateCustomWriteCheckpoints(db, checkpoints) {
|
|
|
271
134
|
update: {
|
|
272
135
|
$set: {
|
|
273
136
|
checkpoint: checkpointOptions.checkpoint,
|
|
274
|
-
sync_rules_id: checkpointOptions.sync_rules_id
|
|
137
|
+
sync_rules_id: checkpointOptions.sync_rules_id,
|
|
138
|
+
op_id: opId
|
|
275
139
|
}
|
|
276
140
|
},
|
|
277
141
|
upsert: true
|
|
278
142
|
}
|
|
279
|
-
})), {});
|
|
143
|
+
})), { session });
|
|
280
144
|
}
|
|
281
145
|
//# sourceMappingURL=MongoWriteCheckpointAPI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MongoWriteCheckpointAPI.js","sourceRoot":"","sources":["../../../src/storage/implementation/MongoWriteCheckpointAPI.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,SAAS,MAAM,mCAAmC,CAAC;AAC/D,OAAO,
|
|
1
|
+
{"version":3,"file":"MongoWriteCheckpointAPI.js","sourceRoot":"","sources":["../../../src/storage/implementation/MongoWriteCheckpointAPI.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { EvaluatedParameters, EvaluatedRow } from '@powersync/service-sync-rules';
|
|
3
3
|
import * as bson from 'bson';
|
|
4
|
+
import { Logger } from '@powersync/lib-services-framework';
|
|
4
5
|
import { InternalOpId, storage } from '@powersync/service-core';
|
|
5
6
|
import { MongoIdSequence } from './MongoIdSequence.js';
|
|
6
7
|
import { PowerSyncMongo } from './db.js';
|
|
@@ -13,6 +14,7 @@ import { BucketDataDocument, BucketParameterDocument, CurrentBucket, CurrentData
|
|
|
13
14
|
*/
|
|
14
15
|
export declare class PersistedBatch {
|
|
15
16
|
private group_id;
|
|
17
|
+
logger: Logger;
|
|
16
18
|
bucketData: mongo.AnyBulkWriteOperation<BucketDataDocument>[];
|
|
17
19
|
bucketParameters: mongo.AnyBulkWriteOperation<BucketParameterDocument>[];
|
|
18
20
|
currentData: mongo.AnyBulkWriteOperation<CurrentDataDocument>[];
|
|
@@ -25,7 +27,9 @@ export declare class PersistedBatch {
|
|
|
25
27
|
* Very rough estimate of transaction size.
|
|
26
28
|
*/
|
|
27
29
|
currentSize: number;
|
|
28
|
-
constructor(group_id: number, writtenSize: number
|
|
30
|
+
constructor(group_id: number, writtenSize: number, options?: {
|
|
31
|
+
logger?: Logger;
|
|
32
|
+
});
|
|
29
33
|
private incrementBucket;
|
|
30
34
|
saveBucketData(options: {
|
|
31
35
|
op_seq: MongoIdSequence;
|
|
@@ -44,7 +48,7 @@ export declare class PersistedBatch {
|
|
|
44
48
|
deleteCurrentData(id: SourceKey): void;
|
|
45
49
|
upsertCurrentData(id: SourceKey, values: Partial<CurrentDataDocument>): void;
|
|
46
50
|
shouldFlushTransaction(): boolean;
|
|
47
|
-
flush(db: PowerSyncMongo, session: mongo.ClientSession): Promise<void>;
|
|
51
|
+
flush(db: PowerSyncMongo, session: mongo.ClientSession, options?: storage.BucketBatchCommitOptions): Promise<void>;
|
|
48
52
|
private getBucketStateUpdates;
|
|
49
53
|
}
|
|
50
54
|
interface BucketStateUpdate {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSONBig } from '@powersync/service-jsonbig';
|
|
2
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { logger as defaultLogger } from '@powersync/lib-services-framework';
|
|
3
3
|
import { storage, utils } from '@powersync/service-core';
|
|
4
4
|
import { currentBucketKey, MAX_ROW_SIZE } from './MongoBucketBatch.js';
|
|
5
5
|
import { replicaIdToSubkey } from './util.js';
|
|
@@ -30,6 +30,7 @@ const MAX_TRANSACTION_DOC_COUNT = 2_000;
|
|
|
30
30
|
*/
|
|
31
31
|
export class PersistedBatch {
|
|
32
32
|
group_id;
|
|
33
|
+
logger;
|
|
33
34
|
bucketData = [];
|
|
34
35
|
bucketParameters = [];
|
|
35
36
|
currentData = [];
|
|
@@ -42,9 +43,10 @@ export class PersistedBatch {
|
|
|
42
43
|
* Very rough estimate of transaction size.
|
|
43
44
|
*/
|
|
44
45
|
currentSize = 0;
|
|
45
|
-
constructor(group_id, writtenSize) {
|
|
46
|
+
constructor(group_id, writtenSize, options) {
|
|
46
47
|
this.group_id = group_id;
|
|
47
48
|
this.currentSize = writtenSize;
|
|
49
|
+
this.logger = options?.logger ?? defaultLogger;
|
|
48
50
|
}
|
|
49
51
|
incrementBucket(bucket, op_id) {
|
|
50
52
|
let existingState = this.bucketStates.get(bucket);
|
|
@@ -76,7 +78,7 @@ export class PersistedBatch {
|
|
|
76
78
|
// the BSON size is small enough, but the JSON size is too large.
|
|
77
79
|
// In these cases, we can't store the data, so we skip it, or generate a REMOVE operation if the row
|
|
78
80
|
// was synced previously.
|
|
79
|
-
logger.error(`
|
|
81
|
+
this.logger.error(`Row ${key} too large: ${recordData.length} bytes. Removing.`);
|
|
80
82
|
continue;
|
|
81
83
|
}
|
|
82
84
|
remaining_buckets.delete(key);
|
|
@@ -214,9 +216,11 @@ export class PersistedBatch {
|
|
|
214
216
|
this.currentData.length >= MAX_TRANSACTION_DOC_COUNT ||
|
|
215
217
|
this.bucketParameters.length >= MAX_TRANSACTION_DOC_COUNT);
|
|
216
218
|
}
|
|
217
|
-
async flush(db, session) {
|
|
219
|
+
async flush(db, session, options) {
|
|
218
220
|
const startAt = performance.now();
|
|
221
|
+
let flushedSomething = false;
|
|
219
222
|
if (this.bucketData.length > 0) {
|
|
223
|
+
flushedSomething = true;
|
|
220
224
|
await db.bucket_data.bulkWrite(this.bucketData, {
|
|
221
225
|
session,
|
|
222
226
|
// inserts only - order doesn't matter
|
|
@@ -224,6 +228,7 @@ export class PersistedBatch {
|
|
|
224
228
|
});
|
|
225
229
|
}
|
|
226
230
|
if (this.bucketParameters.length > 0) {
|
|
231
|
+
flushedSomething = true;
|
|
227
232
|
await db.bucket_parameters.bulkWrite(this.bucketParameters, {
|
|
228
233
|
session,
|
|
229
234
|
// inserts only - order doesn't matter
|
|
@@ -231,6 +236,7 @@ export class PersistedBatch {
|
|
|
231
236
|
});
|
|
232
237
|
}
|
|
233
238
|
if (this.currentData.length > 0) {
|
|
239
|
+
flushedSomething = true;
|
|
234
240
|
await db.current_data.bulkWrite(this.currentData, {
|
|
235
241
|
session,
|
|
236
242
|
// may update and delete data within the same batch - order matters
|
|
@@ -238,14 +244,40 @@ export class PersistedBatch {
|
|
|
238
244
|
});
|
|
239
245
|
}
|
|
240
246
|
if (this.bucketStates.size > 0) {
|
|
247
|
+
flushedSomething = true;
|
|
241
248
|
await db.bucket_state.bulkWrite(this.getBucketStateUpdates(), {
|
|
242
249
|
session,
|
|
243
250
|
// Per-bucket operation - order doesn't matter
|
|
244
251
|
ordered: false
|
|
245
252
|
});
|
|
246
253
|
}
|
|
247
|
-
|
|
248
|
-
|
|
254
|
+
if (flushedSomething) {
|
|
255
|
+
const duration = Math.round(performance.now() - startAt);
|
|
256
|
+
if (options?.oldestUncommittedChange != null) {
|
|
257
|
+
const replicationLag = Math.round((Date.now() - options.oldestUncommittedChange.getTime()) / 1000);
|
|
258
|
+
this.logger.info(`Flushed ${this.bucketData.length} + ${this.bucketParameters.length} + ${this.currentData.length} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}. Replication lag: ${replicationLag}s`, {
|
|
259
|
+
flushed: {
|
|
260
|
+
duration: duration,
|
|
261
|
+
size: this.currentSize,
|
|
262
|
+
bucket_data_count: this.bucketData.length,
|
|
263
|
+
parameter_data_count: this.bucketParameters.length,
|
|
264
|
+
current_data_count: this.currentData.length,
|
|
265
|
+
replication_lag_seconds: replicationLag
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
this.logger.info(`Flushed ${this.bucketData.length} + ${this.bucketParameters.length} + ${this.currentData.length} updates, ${Math.round(this.currentSize / 1024)}kb in ${duration}ms. Last op_id: ${this.debugLastOpId}`, {
|
|
271
|
+
flushed: {
|
|
272
|
+
duration: duration,
|
|
273
|
+
size: this.currentSize,
|
|
274
|
+
bucket_data_count: this.bucketData.length,
|
|
275
|
+
parameter_data_count: this.bucketParameters.length,
|
|
276
|
+
current_data_count: this.currentData.length
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
249
281
|
this.bucketData = [];
|
|
250
282
|
this.bucketParameters = [];
|
|
251
283
|
this.currentData = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersistedBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/PersistedBatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAIrD,OAAO,
|
|
1
|
+
{"version":3,"file":"PersistedBatch.js","sourceRoot":"","sources":["../../../src/storage/implementation/PersistedBatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAIrD,OAAO,EAAU,MAAM,IAAI,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAgB,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAWvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,0BAA0B,GAAG,UAAU,CAAC;AAE9C;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAExC;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IAkBf;IAjBV,MAAM,CAAS;IACf,UAAU,GAAsD,EAAE,CAAC;IACnE,gBAAgB,GAA2D,EAAE,CAAC;IAC9E,WAAW,GAAuD,EAAE,CAAC;IACrE,YAAY,GAAmC,IAAI,GAAG,EAAE,CAAC;IAEzD;;OAEG;IACH,aAAa,GAAwB,IAAI,CAAC;IAE1C;;OAEG;IACH,WAAW,GAAG,CAAC,CAAC;IAEhB,YACU,QAAgB,EACxB,WAAmB,EACnB,OAA6B;QAFrB,aAAQ,GAAR,QAAQ,CAAQ;QAIxB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,aAAa,CAAC;IACjD,CAAC;IAEO,eAAe,CAAC,MAAc,EAAE,KAAmB;QACzD,IAAI,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC,MAAM,GAAG,KAAK,CAAC;YAC7B,aAAa,CAAC,cAAc,IAAI,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE;gBAC5B,MAAM,EAAE,KAAK;gBACb,cAAc,EAAE,CAAC;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,cAAc,CAAC,OAMd;QACC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAyB,CAAC;QAC3D,KAAK,IAAI,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAChC,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAChC,CAAC;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAE3F,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAEhC,SAAS;YACT,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC3D,IAAI,UAAU,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;gBACrC,gGAAgG;gBAChG,iEAAiE;gBACjE,oGAAoG;gBACpG,yBAAyB;gBACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,eAAe,UAAU,CAAC,MAAM,mBAAmB,CAAC,CAAC;gBACjF,SAAS;YACX,CAAC;YAED,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,WAAW,IAAI,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC;YAE5C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAE3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,GAAG,EAAE;4BACH,CAAC,EAAE,IAAI,CAAC,QAAQ;4BAChB,CAAC,EAAE,CAAC,CAAC,MAAM;4BACX,CAAC,EAAE,KAAK;yBACT;wBACD,EAAE,EAAE,KAAK;wBACT,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE;wBAC9B,UAAU,EAAE,OAAO,CAAC,SAAS;wBAC7B,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,MAAM,EAAE,CAAC,CAAC,EAAE;wBACZ,QAAQ,EAAE,QAAQ;wBAClB,IAAI,EAAE,UAAU;qBACjB;iBACF;aACF,CAAC,CAAC;YACH,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,KAAK,IAAI,EAAE,IAAI,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1C,SAAS;YAET,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAE3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,GAAG,EAAE;4BACH,CAAC,EAAE,IAAI,CAAC,QAAQ;4BAChB,CAAC,EAAE,EAAE,CAAC,MAAM;4BACZ,CAAC,EAAE,KAAK;yBACT;wBACD,EAAE,EAAE,QAAQ;wBACZ,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE;wBAC9B,UAAU,EAAE,OAAO,CAAC,SAAS;wBAC7B,KAAK,EAAE,EAAE,CAAC,KAAK;wBACf,MAAM,EAAE,EAAE,CAAC,EAAE;wBACb,QAAQ,EAAE,SAAS;wBACnB,IAAI,EAAE,IAAI;qBACX;iBACF;aACF,CAAC,CAAC;YACH,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;YACxB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,IAMjB;QACC,yCAAyC;QACzC,qEAAqE;QACrE,0HAA0H;QAC1H,2DAA2D;QAC3D,8GAA8G;QAC9G,+BAA+B;QAC/B,6CAA6C;QAC7C,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QAEnD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAuB,CAAC;QACzD,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,wBAAwB;QACxB,KAAK,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACzD,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACzC,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;gBACzB,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,GAAG,EAAE,KAAK;wBACV,GAAG,EAAE;4BACH,CAAC,EAAE,IAAI,CAAC,QAAQ;4BAChB,CAAC,EAAE,WAAW,CAAC,EAAE;4BACjB,CAAC,EAAE,SAAS;yBACb;wBACD,MAAM,EAAE,SAAS;wBACjB,iBAAiB,EAAE,MAAM,CAAC,gBAAgB;qBAC3C;iBACF;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;QAC1B,CAAC;QAED,kDAAkD;QAClD,KAAK,IAAI,MAAM,IAAI,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;gBACzB,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,GAAG,EAAE,KAAK;wBACV,GAAG,EAAE;4BACH,CAAC,EAAE,IAAI,CAAC,QAAQ;4BAChB,CAAC,EAAE,WAAW,CAAC,EAAE;4BACjB,CAAC,EAAE,SAAS;yBACb;wBACD,MAAM,EAAE,MAAM;wBACd,iBAAiB,EAAE,EAAE;qBACtB;iBACF;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,EAAa;QAC7B,MAAM,EAAE,GAAqD;YAC3D,SAAS,EAAE;gBACT,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;aACpB;SACF,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,iBAAiB,CAAC,EAAa,EAAE,MAAoC;QACnE,MAAM,EAAE,GAAqD;YAC3D,SAAS,EAAE;gBACT,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;gBACnB,MAAM,EAAE;oBACN,IAAI,EAAE,MAAM;iBACb;gBACD,MAAM,EAAE,IAAI;aACb;SACF,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;IACzD,CAAC;IAED,sBAAsB;QACpB,OAAO,CACL,IAAI,CAAC,WAAW,IAAI,0BAA0B;YAC9C,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,yBAAyB;YACnD,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,yBAAyB;YACpD,IAAI,CAAC,gBAAgB,CAAC,MAAM,IAAI,yBAAyB,CAC1D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAkB,EAAE,OAA4B,EAAE,OAA0C;QACtG,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,gBAAgB,GAAG,IAAI,CAAC;YACxB,MAAM,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE;gBAC9C,OAAO;gBACP,sCAAsC;gBACtC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,gBAAgB,GAAG,IAAI,CAAC;YACxB,MAAM,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBAC1D,OAAO;gBACP,sCAAsC;gBACtC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,gBAAgB,GAAG,IAAI,CAAC;YACxB,MAAM,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE;gBAChD,OAAO;gBACP,mEAAmE;gBACnE,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC/B,gBAAgB,GAAG,IAAI,CAAC;YACxB,MAAM,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE;gBAC5D,OAAO;gBACP,8CAA8C;gBAC9C,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAED,IAAI,gBAAgB,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;YACzD,IAAI,OAAO,EAAE,uBAAuB,IAAI,IAAI,EAAE,CAAC;gBAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;gBAEnG,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,WAAW,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,MACjE,IAAI,CAAC,WAAW,CAAC,MACnB,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,QAAQ,mBAAmB,IAAI,CAAC,aAAa,sBAAsB,cAAc,GAAG,EAC7I;oBACE,OAAO,EAAE;wBACP,QAAQ,EAAE,QAAQ;wBAClB,IAAI,EAAE,IAAI,CAAC,WAAW;wBACtB,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM;wBACzC,oBAAoB,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM;wBAClD,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;wBAC3C,uBAAuB,EAAE,cAAc;qBACxC;iBACF,CACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,WAAW,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,MACjE,IAAI,CAAC,WAAW,CAAC,MACnB,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,QAAQ,mBAAmB,IAAI,CAAC,aAAa,EAAE,EACxG;oBACE,OAAO,EAAE;wBACP,QAAQ,EAAE,QAAQ;wBAClB,IAAI,EAAE,IAAI,CAAC,WAAW;wBACtB,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM;wBACzC,oBAAoB,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM;wBAClD,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;qBAC5C;iBACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEO,qBAAqB;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE;YACrE,OAAO;gBACL,SAAS,EAAE;oBACT,MAAM,EAAE;wBACN,GAAG,EAAE;4BACH,CAAC,EAAE,IAAI,CAAC,QAAQ;4BAChB,CAAC,EAAE,MAAM;yBACV;qBACF;oBACD,MAAM,EAAE;wBACN,IAAI,EAAE;4BACJ,OAAO,EAAE,KAAK,CAAC,MAAM;yBACtB;qBACF;oBACD,MAAM,EAAE,IAAI;iBACb;aACyD,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
3
3
|
import { MongoStorageConfig } from '../../types/types.js';
|
|
4
|
-
import { BucketDataDocument, BucketParameterDocument, BucketStateDocument, CurrentDataDocument, CustomWriteCheckpointDocument, IdSequenceDocument, InstanceDocument, SourceTableDocument, SyncRuleDocument, WriteCheckpointDocument } from './models.js';
|
|
4
|
+
import { BucketDataDocument, BucketParameterDocument, BucketStateDocument, CheckpointEventDocument, CurrentDataDocument, CustomWriteCheckpointDocument, IdSequenceDocument, InstanceDocument, SourceTableDocument, SyncRuleDocument, WriteCheckpointDocument } from './models.js';
|
|
5
5
|
export interface PowerSyncMongoOptions {
|
|
6
6
|
/**
|
|
7
7
|
* Optional - uses the database from the MongoClient connection URI if not specified.
|
|
@@ -20,6 +20,7 @@ export declare class PowerSyncMongo {
|
|
|
20
20
|
readonly instance: mongo.Collection<InstanceDocument>;
|
|
21
21
|
readonly locks: mongo.Collection<lib_mongo.locks.Lock>;
|
|
22
22
|
readonly bucket_state: mongo.Collection<BucketStateDocument>;
|
|
23
|
+
readonly checkpoint_events: mongo.Collection<CheckpointEventDocument>;
|
|
23
24
|
readonly client: mongo.MongoClient;
|
|
24
25
|
readonly db: mongo.Db;
|
|
25
26
|
constructor(client: mongo.MongoClient, options?: PowerSyncMongoOptions);
|
|
@@ -33,5 +34,15 @@ export declare class PowerSyncMongo {
|
|
|
33
34
|
* Primarily for tests.
|
|
34
35
|
*/
|
|
35
36
|
drop(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Call this after every checkpoint or sync rules status update. Rather call too often than too rarely.
|
|
39
|
+
*
|
|
40
|
+
* This is used in a similar way to the Postgres NOTIFY functionality.
|
|
41
|
+
*/
|
|
42
|
+
notifyCheckpoint(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Only use in migrations and tests.
|
|
45
|
+
*/
|
|
46
|
+
createCheckpointEventsCollection(): Promise<void>;
|
|
36
47
|
}
|
|
37
48
|
export declare function createPowerSyncMongo(config: MongoStorageConfig, options?: lib_mongo.MongoConnectionOptions): PowerSyncMongo;
|