@powersync/service-core 0.0.0-dev-20241017141000 → 0.0.0-dev-20241021151922
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 +5 -5
- package/dist/routes/endpoints/checkpointing.js +82 -14
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +4 -8
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +1 -18
- package/dist/storage/MongoBucketStorage.js +9 -41
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/StorageEngine.d.ts +1 -5
- package/dist/storage/StorageEngine.js +1 -19
- package/dist/storage/StorageEngine.js.map +1 -1
- package/dist/storage/StorageProvider.d.ts +1 -8
- package/dist/storage/{write-checkpoint.d.ts → WriteCheckpointAPI.d.ts} +26 -9
- package/dist/storage/{write-checkpoint.js → WriteCheckpointAPI.js} +1 -1
- package/dist/storage/WriteCheckpointAPI.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +2 -2
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
- package/dist/storage/mongo/MongoStorageProvider.js +1 -2
- package/dist/storage/mongo/MongoStorageProvider.js.map +1 -1
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +9 -1
- package/dist/storage/mongo/MongoSyncBucketStorage.js +33 -4
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +1 -1
- package/dist/storage/mongo/MongoWriteCheckpointAPI.js +4 -6
- package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/storage-index.d.ts +2 -2
- package/dist/storage/storage-index.js +2 -2
- package/dist/storage/storage-index.js.map +1 -1
- package/package.json +5 -5
- package/src/routes/endpoints/checkpointing.ts +8 -1
- package/src/storage/BucketStorage.ts +6 -12
- package/src/storage/MongoBucketStorage.ts +9 -63
- package/src/storage/StorageEngine.ts +2 -24
- package/src/storage/StorageProvider.ts +1 -9
- package/src/storage/{write-checkpoint.ts → WriteCheckpointAPI.ts} +27 -13
- package/src/storage/mongo/MongoBucketBatch.ts +2 -2
- package/src/storage/mongo/MongoStorageProvider.ts +1 -2
- package/src/storage/mongo/MongoSyncBucketStorage.ts +49 -4
- package/src/storage/mongo/MongoWriteCheckpointAPI.ts +7 -6
- package/src/storage/storage-index.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/write-checkpoint.js.map +0 -1
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { DisposableListener, DisposableObserver, logger } from '@powersync/lib-services-framework';
|
|
2
2
|
import { ResolvedPowerSyncConfig } from '../util/util-index.js';
|
|
3
3
|
import { BucketStorageFactory } from './BucketStorage.js';
|
|
4
|
-
import { ActiveStorage, BucketStorageProvider
|
|
5
|
-
import { DEFAULT_WRITE_CHECKPOINT_MODE } from './write-checkpoint.js';
|
|
4
|
+
import { ActiveStorage, BucketStorageProvider } from './StorageProvider.js';
|
|
6
5
|
|
|
7
6
|
export type StorageEngineOptions = {
|
|
8
7
|
configuration: ResolvedPowerSyncConfig;
|
|
9
8
|
};
|
|
10
9
|
|
|
11
|
-
export const DEFAULT_STORAGE_SETTINGS: StorageSettings = {
|
|
12
|
-
writeCheckpointMode: DEFAULT_WRITE_CHECKPOINT_MODE
|
|
13
|
-
};
|
|
14
|
-
|
|
15
10
|
export interface StorageEngineListener extends DisposableListener {
|
|
16
11
|
storageActivated: (storage: BucketStorageFactory) => void;
|
|
17
12
|
}
|
|
@@ -20,11 +15,9 @@ export class StorageEngine extends DisposableObserver<StorageEngineListener> {
|
|
|
20
15
|
// TODO: This will need to revisited when we actually support multiple storage providers.
|
|
21
16
|
private storageProviders: Map<string, BucketStorageProvider> = new Map();
|
|
22
17
|
private currentActiveStorage: ActiveStorage | null = null;
|
|
23
|
-
private _activeSettings: StorageSettings;
|
|
24
18
|
|
|
25
19
|
constructor(private options: StorageEngineOptions) {
|
|
26
20
|
super();
|
|
27
|
-
this._activeSettings = DEFAULT_STORAGE_SETTINGS;
|
|
28
21
|
}
|
|
29
22
|
|
|
30
23
|
get activeBucketStorage(): BucketStorageFactory {
|
|
@@ -39,20 +32,6 @@ export class StorageEngine extends DisposableObserver<StorageEngineListener> {
|
|
|
39
32
|
return this.currentActiveStorage;
|
|
40
33
|
}
|
|
41
34
|
|
|
42
|
-
get activeSettings(): StorageSettings {
|
|
43
|
-
return { ...this._activeSettings };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
updateSettings(settings: Partial<StorageSettings>) {
|
|
47
|
-
if (this.currentActiveStorage) {
|
|
48
|
-
throw new Error(`Storage is already active, settings cannot be modified.`);
|
|
49
|
-
}
|
|
50
|
-
this._activeSettings = {
|
|
51
|
-
...this._activeSettings,
|
|
52
|
-
...settings
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
35
|
/**
|
|
57
36
|
* Register a provider which generates a {@link BucketStorageFactory}
|
|
58
37
|
* given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
|
|
@@ -65,8 +44,7 @@ export class StorageEngine extends DisposableObserver<StorageEngineListener> {
|
|
|
65
44
|
logger.info('Starting Storage Engine...');
|
|
66
45
|
const { configuration } = this.options;
|
|
67
46
|
this.currentActiveStorage = await this.storageProviders.get(configuration.storage.type)!.getStorage({
|
|
68
|
-
resolvedConfig: configuration
|
|
69
|
-
...this.activeSettings
|
|
47
|
+
resolvedConfig: configuration
|
|
70
48
|
});
|
|
71
49
|
this.iterateListeners((cb) => cb.storageActivated?.(this.activeBucketStorage));
|
|
72
50
|
logger.info(`Successfully activated storage: ${configuration.storage.type}.`);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as util from '../util/util-index.js';
|
|
2
2
|
import { BucketStorageFactory } from './BucketStorage.js';
|
|
3
|
-
import { WriteCheckpointMode } from './write-checkpoint.js';
|
|
4
3
|
|
|
5
4
|
export interface ActiveStorage {
|
|
6
5
|
storage: BucketStorageFactory;
|
|
@@ -12,14 +11,7 @@ export interface ActiveStorage {
|
|
|
12
11
|
tearDown(): Promise<boolean>;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
* Settings which can be modified by various modules in their initialization.
|
|
17
|
-
*/
|
|
18
|
-
export interface StorageSettings {
|
|
19
|
-
writeCheckpointMode: WriteCheckpointMode;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface GetStorageOptions extends StorageSettings {
|
|
14
|
+
export interface GetStorageOptions {
|
|
23
15
|
// TODO: This should just be the storage config. Update once the slot name prefix coupling has been removed from the storage
|
|
24
16
|
resolvedConfig: util.ResolvedPowerSyncConfig;
|
|
25
17
|
}
|
|
@@ -26,19 +26,19 @@ export interface CustomWriteCheckpointFilters extends BaseWriteCheckpointIdentif
|
|
|
26
26
|
sync_rules_id: number;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export interface
|
|
29
|
+
export interface BatchedCustomWriteCheckpointOptions extends BaseWriteCheckpointIdentifier {
|
|
30
30
|
/**
|
|
31
31
|
* A supplied incrementing Write Checkpoint number
|
|
32
32
|
*/
|
|
33
33
|
checkpoint: bigint;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
export interface CustomWriteCheckpointOptions extends BatchedCustomWriteCheckpointOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Sync rules which were active when this checkpoint was created.
|
|
39
|
+
*/
|
|
40
|
+
sync_rules_id: number;
|
|
41
|
+
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Managed Write Checkpoints are a mapping of User ID to replication HEAD
|
|
@@ -52,19 +52,33 @@ export interface ManagedWriteCheckpointFilters extends BaseWriteCheckpointIdenti
|
|
|
52
52
|
|
|
53
53
|
export type ManagedWriteCheckpointOptions = ManagedWriteCheckpointFilters;
|
|
54
54
|
|
|
55
|
+
export type SyncStorageLastWriteCheckpointFilters = BaseWriteCheckpointIdentifier | ManagedWriteCheckpointFilters;
|
|
55
56
|
export type LastWriteCheckpointFilters = CustomWriteCheckpointFilters | ManagedWriteCheckpointFilters;
|
|
56
57
|
|
|
57
|
-
export interface
|
|
58
|
+
export interface BaseWriteCheckpointAPI {
|
|
58
59
|
readonly writeCheckpointMode: WriteCheckpointMode;
|
|
59
|
-
|
|
60
60
|
setWriteCheckpointMode(mode: WriteCheckpointMode): void;
|
|
61
|
+
createManagedWriteCheckpoint(checkpoint: ManagedWriteCheckpointOptions): Promise<bigint>;
|
|
62
|
+
}
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Write Checkpoint API to be used in conjunction with a {@link SyncRulesBucketStorage}.
|
|
66
|
+
* This storage corresponds with a set of sync rules. These APIs don't require specifying a
|
|
67
|
+
* sync rules id.
|
|
68
|
+
*/
|
|
69
|
+
export interface SyncStorageWriteCheckpointAPI extends BaseWriteCheckpointAPI {
|
|
70
|
+
batchCreateCustomWriteCheckpoints(checkpoints: BatchedCustomWriteCheckpointOptions[]): Promise<void>;
|
|
71
|
+
createCustomWriteCheckpoint(checkpoint: BatchedCustomWriteCheckpointOptions): Promise<bigint>;
|
|
72
|
+
lastWriteCheckpoint(filters: SyncStorageLastWriteCheckpointFilters): Promise<bigint | null>;
|
|
73
|
+
}
|
|
63
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Write Checkpoint API which is interfaced directly with the storage layer. This requires
|
|
77
|
+
* sync rules identifiers for custom write checkpoints.
|
|
78
|
+
*/
|
|
79
|
+
export interface WriteCheckpointAPI extends BaseWriteCheckpointAPI {
|
|
80
|
+
batchCreateCustomWriteCheckpoints(checkpoints: CustomWriteCheckpointOptions[]): Promise<void>;
|
|
64
81
|
createCustomWriteCheckpoint(checkpoint: CustomWriteCheckpointOptions): Promise<bigint>;
|
|
65
|
-
|
|
66
|
-
createManagedWriteCheckpoint(checkpoint: ManagedWriteCheckpointOptions): Promise<bigint>;
|
|
67
|
-
|
|
68
82
|
lastWriteCheckpoint(filters: LastWriteCheckpointFilters): Promise<bigint | null>;
|
|
69
83
|
}
|
|
70
84
|
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
SaveOptions
|
|
13
13
|
} from '../BucketStorage.js';
|
|
14
14
|
import { SourceTable } from '../SourceTable.js';
|
|
15
|
-
import { CustomWriteCheckpointOptions } from '../
|
|
15
|
+
import { BatchedCustomWriteCheckpointOptions, CustomWriteCheckpointOptions } from '../WriteCheckpointAPI.js';
|
|
16
16
|
import { PowerSyncMongo } from './db.js';
|
|
17
17
|
import { CurrentBucket, CurrentDataDocument, SourceKey, SyncRuleDocument } from './models.js';
|
|
18
18
|
import { MongoIdSequence } from './MongoIdSequence.js';
|
|
@@ -83,7 +83,7 @@ export class MongoBucketBatch extends DisposableObserver<BucketBatchStorageListe
|
|
|
83
83
|
this.sync_rules = sync_rules;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
addCustomWriteCheckpoint(checkpoint:
|
|
86
|
+
addCustomWriteCheckpoint(checkpoint: BatchedCustomWriteCheckpointOptions): void {
|
|
87
87
|
this.write_checkpoint_batch.push({
|
|
88
88
|
...checkpoint,
|
|
89
89
|
sync_rules_id: this.group_id
|
|
@@ -19,8 +19,7 @@ export class MongoStorageProvider implements BucketStorageProvider {
|
|
|
19
19
|
return {
|
|
20
20
|
storage: new MongoBucketStorage(database, {
|
|
21
21
|
// TODO currently need the entire resolved config due to this
|
|
22
|
-
slot_name_prefix: resolvedConfig.slot_name_prefix
|
|
23
|
-
write_checkpoint_mode: options.writeCheckpointMode
|
|
22
|
+
slot_name_prefix: resolvedConfig.slot_name_prefix
|
|
24
23
|
}),
|
|
25
24
|
shutDown: () => client.close(),
|
|
26
25
|
tearDown: () => {
|
|
@@ -2,7 +2,8 @@ import { SqliteJsonRow, SqliteJsonValue, SqlSyncRules } from '@powersync/service
|
|
|
2
2
|
import * as bson from 'bson';
|
|
3
3
|
import * as mongo from 'mongodb';
|
|
4
4
|
|
|
5
|
-
import { DisposableObserver } from '@powersync/lib-services-framework';
|
|
5
|
+
import { DisposableObserver, logger } from '@powersync/lib-services-framework';
|
|
6
|
+
import * as timers from 'timers/promises';
|
|
6
7
|
import * as db from '../../db/db-index.js';
|
|
7
8
|
import * as util from '../../util/util-index.js';
|
|
8
9
|
import {
|
|
@@ -26,13 +27,19 @@ import {
|
|
|
26
27
|
import { ChecksumCache, FetchPartialBucketChecksum, PartialChecksum, PartialChecksumMap } from '../ChecksumCache.js';
|
|
27
28
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
28
29
|
import { SourceTable } from '../SourceTable.js';
|
|
30
|
+
import {
|
|
31
|
+
BatchedCustomWriteCheckpointOptions,
|
|
32
|
+
ManagedWriteCheckpointOptions,
|
|
33
|
+
SyncStorageLastWriteCheckpointFilters,
|
|
34
|
+
WriteCheckpointAPI,
|
|
35
|
+
WriteCheckpointMode
|
|
36
|
+
} from '../WriteCheckpointAPI.js';
|
|
29
37
|
import { PowerSyncMongo } from './db.js';
|
|
30
38
|
import { BucketDataDocument, BucketDataKey, SourceKey, SyncRuleState } from './models.js';
|
|
31
39
|
import { MongoBucketBatch } from './MongoBucketBatch.js';
|
|
32
40
|
import { MongoCompactor } from './MongoCompactor.js';
|
|
41
|
+
import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
33
42
|
import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, mapOpEntry, readSingleBatch, serializeLookup } from './util.js';
|
|
34
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
35
|
-
import * as timers from 'timers/promises';
|
|
36
43
|
|
|
37
44
|
export class MongoSyncBucketStorage
|
|
38
45
|
extends DisposableObserver<SyncRulesBucketStorageListener>
|
|
@@ -46,15 +53,53 @@ export class MongoSyncBucketStorage
|
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
private parsedSyncRulesCache: SqlSyncRules | undefined;
|
|
56
|
+
private writeCheckpointAPI: WriteCheckpointAPI;
|
|
49
57
|
|
|
50
58
|
constructor(
|
|
51
59
|
public readonly factory: MongoBucketStorage,
|
|
52
60
|
public readonly group_id: number,
|
|
53
61
|
private readonly sync_rules: PersistedSyncRulesContent,
|
|
54
|
-
public readonly slot_name: string
|
|
62
|
+
public readonly slot_name: string,
|
|
63
|
+
writeCheckpointMode: WriteCheckpointMode = WriteCheckpointMode.MANAGED
|
|
55
64
|
) {
|
|
56
65
|
super();
|
|
57
66
|
this.db = factory.db;
|
|
67
|
+
this.writeCheckpointAPI = new MongoWriteCheckpointAPI({
|
|
68
|
+
db: this.db,
|
|
69
|
+
mode: writeCheckpointMode
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get writeCheckpointMode() {
|
|
74
|
+
return this.writeCheckpointAPI.writeCheckpointMode;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setWriteCheckpointMode(mode: WriteCheckpointMode): void {
|
|
78
|
+
this.writeCheckpointAPI.setWriteCheckpointMode(mode);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
batchCreateCustomWriteCheckpoints(checkpoints: BatchedCustomWriteCheckpointOptions[]): Promise<void> {
|
|
82
|
+
return this.writeCheckpointAPI.batchCreateCustomWriteCheckpoints(
|
|
83
|
+
checkpoints.map((checkpoint) => ({ ...checkpoint, sync_rules_id: this.group_id }))
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
createCustomWriteCheckpoint(checkpoint: BatchedCustomWriteCheckpointOptions): Promise<bigint> {
|
|
88
|
+
return this.writeCheckpointAPI.createCustomWriteCheckpoint({
|
|
89
|
+
...checkpoint,
|
|
90
|
+
sync_rules_id: this.group_id
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
createManagedWriteCheckpoint(checkpoint: ManagedWriteCheckpointOptions): Promise<bigint> {
|
|
95
|
+
return this.writeCheckpointAPI.createManagedWriteCheckpoint(checkpoint);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
lastWriteCheckpoint(filters: SyncStorageLastWriteCheckpointFilters): Promise<bigint | null> {
|
|
99
|
+
return this.writeCheckpointAPI.lastWriteCheckpoint({
|
|
100
|
+
...filters,
|
|
101
|
+
sync_rules_id: this.group_id
|
|
102
|
+
});
|
|
58
103
|
}
|
|
59
104
|
|
|
60
105
|
getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
ManagedWriteCheckpointOptions,
|
|
8
8
|
WriteCheckpointAPI,
|
|
9
9
|
WriteCheckpointMode
|
|
10
|
-
} from '../
|
|
10
|
+
} from '../WriteCheckpointAPI.js';
|
|
11
11
|
import { PowerSyncMongo } from './db.js';
|
|
12
12
|
|
|
13
13
|
export type MongoCheckpointAPIOptions = {
|
|
@@ -37,11 +37,12 @@ export class MongoWriteCheckpointAPI implements WriteCheckpointAPI {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
async createCustomWriteCheckpoint(options: CustomWriteCheckpointOptions): Promise<bigint> {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
if (this.writeCheckpointMode !== WriteCheckpointMode.CUSTOM) {
|
|
41
|
+
throw new framework.errors.ValidationError(
|
|
42
|
+
`Creating a custom Write Checkpoint when the current Write Checkpoint mode is set to "${this.writeCheckpointMode}"`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
45
46
|
const { checkpoint, user_id, sync_rules_id } = options;
|
|
46
47
|
const doc = await this.db.custom_write_checkpoints.findOneAndUpdate(
|
|
47
48
|
{
|
|
@@ -5,6 +5,7 @@ export * from './SourceEntity.js';
|
|
|
5
5
|
export * from './SourceTable.js';
|
|
6
6
|
export * from './StorageEngine.js';
|
|
7
7
|
|
|
8
|
+
export * from './mongo/config.js';
|
|
8
9
|
export * from './mongo/db.js';
|
|
9
10
|
export * from './mongo/models.js';
|
|
10
11
|
export * from './mongo/MongoBucketBatch.js';
|
|
@@ -17,5 +18,4 @@ export * from './mongo/MongoSyncRulesLock.js';
|
|
|
17
18
|
export * from './mongo/OperationBatch.js';
|
|
18
19
|
export * from './mongo/PersistedBatch.js';
|
|
19
20
|
export * from './mongo/util.js';
|
|
20
|
-
export * from './
|
|
21
|
-
export * from './write-checkpoint.js';
|
|
21
|
+
export * from './WriteCheckpointAPI.js';
|