@powersync/service-core 0.18.1 → 1.7.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/api/RouteAPI.d.ts +1 -1
  3. package/dist/api/diagnostics.js +107 -169
  4. package/dist/api/diagnostics.js.map +1 -1
  5. package/dist/entry/commands/compact-action.js +10 -73
  6. package/dist/entry/commands/compact-action.js.map +1 -1
  7. package/dist/modules/AbstractModule.d.ts +1 -1
  8. package/dist/replication/AbstractReplicator.js +2 -65
  9. package/dist/replication/AbstractReplicator.js.map +1 -1
  10. package/dist/routes/endpoints/checkpointing.js +3 -2
  11. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  12. package/dist/routes/endpoints/socket-route.js +5 -5
  13. package/dist/routes/endpoints/socket-route.js.map +1 -1
  14. package/dist/routes/endpoints/sync-stream.js +5 -5
  15. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  16. package/dist/runner/teardown.js +3 -65
  17. package/dist/runner/teardown.js.map +1 -1
  18. package/dist/storage/BucketStorage.d.ts +1 -442
  19. package/dist/storage/BucketStorage.js +0 -9
  20. package/dist/storage/BucketStorage.js.map +1 -1
  21. package/dist/storage/BucketStorageBatch.d.ts +130 -0
  22. package/dist/storage/BucketStorageBatch.js +10 -0
  23. package/dist/storage/BucketStorageBatch.js.map +1 -0
  24. package/dist/storage/BucketStorageFactory.d.ts +136 -0
  25. package/dist/storage/BucketStorageFactory.js +2 -0
  26. package/dist/storage/BucketStorageFactory.js.map +1 -0
  27. package/dist/storage/ChecksumCache.js.map +1 -1
  28. package/dist/storage/PersistedSyncRulesContent.d.ts +20 -0
  29. package/dist/storage/PersistedSyncRulesContent.js +2 -0
  30. package/dist/storage/PersistedSyncRulesContent.js.map +1 -0
  31. package/dist/storage/ReplicationEventPayload.d.ts +1 -1
  32. package/dist/storage/ReplicationLock.d.ts +4 -0
  33. package/dist/storage/ReplicationLock.js +2 -0
  34. package/dist/storage/ReplicationLock.js.map +1 -0
  35. package/dist/storage/StorageEngine.d.ts +4 -4
  36. package/dist/storage/StorageEngine.js +2 -2
  37. package/dist/storage/StorageEngine.js.map +1 -1
  38. package/dist/storage/StorageProvider.d.ts +4 -1
  39. package/dist/storage/SyncRulesBucketStorage.d.ts +201 -0
  40. package/dist/storage/SyncRulesBucketStorage.js +7 -0
  41. package/dist/storage/SyncRulesBucketStorage.js.map +1 -0
  42. package/dist/storage/bson.d.ts +11 -3
  43. package/dist/storage/bson.js +24 -2
  44. package/dist/storage/bson.js.map +1 -1
  45. package/dist/storage/storage-index.d.ts +5 -0
  46. package/dist/storage/storage-index.js +5 -0
  47. package/dist/storage/storage-index.js.map +1 -1
  48. package/dist/sync/BucketChecksumState.d.ts +91 -0
  49. package/dist/sync/BucketChecksumState.js +313 -0
  50. package/dist/sync/BucketChecksumState.js.map +1 -0
  51. package/dist/sync/sync-index.d.ts +1 -0
  52. package/dist/sync/sync-index.js +1 -0
  53. package/dist/sync/sync-index.js.map +1 -1
  54. package/dist/sync/sync.d.ts +7 -3
  55. package/dist/sync/sync.js +131 -135
  56. package/dist/sync/sync.js.map +1 -1
  57. package/dist/sync/util.d.ts +9 -0
  58. package/dist/sync/util.js +44 -0
  59. package/dist/sync/util.js.map +1 -1
  60. package/dist/util/checkpointing.d.ts +1 -1
  61. package/dist/util/checkpointing.js +15 -78
  62. package/dist/util/checkpointing.js.map +1 -1
  63. package/dist/util/protocol-types.d.ts +13 -4
  64. package/package.json +4 -4
  65. package/src/api/RouteAPI.ts +1 -1
  66. package/src/api/diagnostics.ts +1 -1
  67. package/src/entry/commands/compact-action.ts +2 -3
  68. package/src/modules/AbstractModule.ts +1 -1
  69. package/src/replication/AbstractReplicator.ts +1 -2
  70. package/src/routes/endpoints/checkpointing.ts +3 -3
  71. package/src/routes/endpoints/socket-route.ts +7 -5
  72. package/src/routes/endpoints/sync-stream.ts +8 -5
  73. package/src/runner/teardown.ts +1 -1
  74. package/src/storage/BucketStorage.ts +1 -552
  75. package/src/storage/BucketStorageBatch.ts +158 -0
  76. package/src/storage/BucketStorageFactory.ts +156 -0
  77. package/src/storage/ChecksumCache.ts +1 -0
  78. package/src/storage/PersistedSyncRulesContent.ts +26 -0
  79. package/src/storage/ReplicationEventPayload.ts +1 -1
  80. package/src/storage/ReplicationLock.ts +5 -0
  81. package/src/storage/StorageEngine.ts +4 -4
  82. package/src/storage/StorageProvider.ts +4 -1
  83. package/src/storage/SyncRulesBucketStorage.ts +256 -0
  84. package/src/storage/bson.ts +28 -4
  85. package/src/storage/storage-index.ts +5 -0
  86. package/src/sync/BucketChecksumState.ts +392 -0
  87. package/src/sync/sync-index.ts +1 -0
  88. package/src/sync/sync.ts +173 -157
  89. package/src/sync/util.ts +54 -0
  90. package/src/util/checkpointing.ts +4 -6
  91. package/src/util/protocol-types.ts +16 -4
  92. package/test/src/auth.test.ts +5 -5
  93. package/test/src/sync/BucketChecksumState.test.ts +565 -0
  94. package/test/src/sync/util.test.ts +34 -0
  95. package/tsconfig.tsbuildinfo +1 -1
@@ -1,5 +1,5 @@
1
1
  import * as t from 'ts-codec';
2
- import { SqliteJsonValue } from '@powersync/service-sync-rules';
2
+ import { BucketDescription, BucketPriority, SqliteJsonValue } from '@powersync/service-sync-rules';
3
3
  export declare const BucketRequest: t.ObjectCodec<{
4
4
  name: t.IdentityCodec<t.CodecType.String>;
5
5
  /**
@@ -52,7 +52,7 @@ export interface StreamingSyncCheckpointDiff {
52
52
  checkpoint_diff: {
53
53
  last_op_id: OpId;
54
54
  write_checkpoint?: OpId;
55
- updated_buckets: BucketChecksum[];
55
+ updated_buckets: BucketChecksumWithDescription[];
56
56
  removed_buckets: string[];
57
57
  };
58
58
  }
@@ -64,9 +64,16 @@ export interface StreamingSyncCheckpointComplete {
64
64
  last_op_id: OpId;
65
65
  };
66
66
  }
67
+ export interface StreamingSyncCheckpointPartiallyComplete {
68
+ partial_checkpoint_complete: {
69
+ last_op_id: OpId;
70
+ priority: BucketPriority;
71
+ };
72
+ }
67
73
  export interface StreamingSyncKeepalive {
74
+ token_expires_in: number;
68
75
  }
69
- export type StreamingSyncLine = StreamingSyncData | StreamingSyncCheckpoint | StreamingSyncCheckpointDiff | StreamingSyncCheckpointComplete | StreamingSyncKeepalive;
76
+ export type StreamingSyncLine = StreamingSyncData | StreamingSyncCheckpoint | StreamingSyncCheckpointDiff | StreamingSyncCheckpointComplete | StreamingSyncCheckpointPartiallyComplete | StreamingSyncKeepalive;
70
77
  /**
71
78
  * 64-bit unsigned number, as a base-10 string.
72
79
  */
@@ -74,7 +81,7 @@ export type OpId = string;
74
81
  export interface Checkpoint {
75
82
  last_op_id: OpId;
76
83
  write_checkpoint?: OpId;
77
- buckets: BucketChecksum[];
84
+ buckets: BucketChecksumWithDescription[];
78
85
  }
79
86
  export interface BucketState {
80
87
  bucket: string;
@@ -119,3 +126,5 @@ export interface BucketChecksum {
119
126
  */
120
127
  count: number;
121
128
  }
129
+ export interface BucketChecksumWithDescription extends BucketChecksum, BucketDescription {
130
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "version": "0.18.1",
8
+ "version": "1.7.0",
9
9
  "main": "dist/index.js",
10
10
  "license": "FSL-1.1-Apache-2.0",
11
11
  "type": "module",
@@ -32,10 +32,10 @@
32
32
  "uuid": "^9.0.1",
33
33
  "winston": "^3.13.0",
34
34
  "yaml": "^2.3.2",
35
- "@powersync/lib-services-framework": "0.5.1",
35
+ "@powersync/lib-services-framework": "0.5.2",
36
36
  "@powersync/service-jsonbig": "0.17.10",
37
- "@powersync/service-rsocket-router": "0.0.18",
38
- "@powersync/service-sync-rules": "0.23.4",
37
+ "@powersync/service-rsocket-router": "0.0.19",
38
+ "@powersync/service-sync-rules": "0.24.0",
39
39
  "@powersync/service-types": "0.8.0"
40
40
  },
41
41
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  import { SqlSyncRules, TablePattern } from '@powersync/service-sync-rules';
2
2
  import * as types from '@powersync/service-types';
3
- import { ParseSyncRulesOptions, SyncRulesBucketStorage } from '../storage/BucketStorage.js';
3
+ import { ParseSyncRulesOptions, SyncRulesBucketStorage } from '../storage/storage-index.js';
4
4
 
5
5
  export interface PatternResult {
6
6
  schema: string;
@@ -57,7 +57,7 @@ export async function getSyncRulesStatus(
57
57
  // This method can run under some situations if no connection is configured yet.
58
58
  // It will return a default tag in such a case. This default tag is not module specific.
59
59
  const tag = sourceConfig.tag ?? DEFAULT_TAG;
60
- using systemStorage = live_status ? bucketStorage.getInstance(sync_rules) : undefined;
60
+ const systemStorage = live_status ? bucketStorage.getInstance(sync_rules) : undefined;
61
61
  const status = await systemStorage?.getStatus();
62
62
  let replication_lag_bytes: number | undefined = undefined;
63
63
 
@@ -50,14 +50,13 @@ export function registerCompactAction(program: Command) {
50
50
  await serviceContext.lifeCycleEngine.start();
51
51
  const bucketStorage = serviceContext.storageEngine.activeBucketStorage;
52
52
 
53
- const active = await bucketStorage.getActiveSyncRulesContent();
53
+ const active = await bucketStorage.getActiveStorage();
54
54
  if (active == null) {
55
55
  logger.info('No active instance to compact');
56
56
  return;
57
57
  }
58
- using p = bucketStorage.getInstance(active);
59
58
  logger.info('Performing compaction...');
60
- await p.compact({ memoryLimitMB: COMPACT_MEMORY_LIMIT_MB, compactBuckets: buckets });
59
+ await active.compact({ memoryLimitMB: COMPACT_MEMORY_LIMIT_MB, compactBuckets: buckets });
61
60
  logger.info('Successfully compacted storage.');
62
61
  } catch (e) {
63
62
  logger.error(`Failed to compact: ${e.toString()}`);
@@ -1,7 +1,7 @@
1
1
  import { ServiceContextContainer } from '../system/ServiceContext.js';
2
2
  import { logger } from '@powersync/lib-services-framework';
3
3
  import winston from 'winston';
4
- import { PersistedSyncRulesContent } from '../storage/BucketStorage.js';
4
+ import { PersistedSyncRulesContent } from '../storage/storage-index.js';
5
5
 
6
6
  export interface TearDownOptions {
7
7
  /**
@@ -199,7 +199,6 @@ export abstract class AbstractReplicator<T extends AbstractReplicationJob = Abst
199
199
  try {
200
200
  await job.stop();
201
201
  await this.terminateSyncRules(job.storage);
202
- job.storage[Symbol.dispose]();
203
202
  } catch (e) {
204
203
  // This will be retried
205
204
  this.logger.warn('Failed to terminate old replication job}', e);
@@ -210,7 +209,7 @@ export abstract class AbstractReplicator<T extends AbstractReplicationJob = Abst
210
209
  const stopped = await this.storage.getStoppedSyncRules();
211
210
  for (let syncRules of stopped) {
212
211
  try {
213
- using syncRuleStorage = this.storage.getInstance(syncRules);
212
+ const syncRuleStorage = this.storage.getInstance(syncRules);
214
213
  await this.terminateSyncRules(syncRuleStorage);
215
214
  } catch (e) {
216
215
  this.logger.warn(`Failed clean up replication config for sync rule: ${syncRules.id}`, e);
@@ -1,7 +1,6 @@
1
1
  import { logger, router, schema } from '@powersync/lib-services-framework';
2
2
  import * as t from 'ts-codec';
3
3
 
4
- import * as framework from '@powersync/lib-services-framework';
5
4
  import * as util from '../../util/util-index.js';
6
5
  import { authUser } from '../auth.js';
7
6
  import { routeDefinition } from '../router.js';
@@ -31,8 +30,9 @@ export const writeCheckpoint = routeDefinition({
31
30
 
32
31
  logger.info(`Waiting for LSN checkpoint: ${head}`);
33
32
  while (Date.now() - start < timeout) {
34
- const cp = await service_context.storageEngine.activeBucketStorage.getActiveCheckpoint();
35
- if (!cp.hasSyncRules()) {
33
+ const bucketStorage = await service_context.storageEngine.activeBucketStorage.getActiveStorage();
34
+ const cp = await bucketStorage?.getCheckpoint();
35
+ if (cp == null) {
36
36
  throw new Error('No sync rules available');
37
37
  }
38
38
  if (cp.lsn && cp.lsn >= head) {
@@ -49,9 +49,9 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
49
49
  const {
50
50
  storageEngine: { activeBucketStorage }
51
51
  } = service_context;
52
- // Sanity check before we start the stream
53
- const cp = await activeBucketStorage.getActiveCheckpoint();
54
- if (!cp.hasSyncRules()) {
52
+
53
+ const bucketStorage = await activeBucketStorage.getActiveStorage();
54
+ if (bucketStorage == null) {
55
55
  responder.onError(
56
56
  new errors.ServiceError({
57
57
  status: 500,
@@ -63,6 +63,8 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
63
63
  return;
64
64
  }
65
65
 
66
+ const syncRules = bucketStorage.getParsedSyncRules(routerEngine!.getAPI().getParseSyncRulesOptions());
67
+
66
68
  const removeStopHandler = routerEngine!.addStopHandler(() => {
67
69
  controller.abort();
68
70
  });
@@ -71,8 +73,8 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
71
73
  const tracker = new sync.RequestTracker();
72
74
  try {
73
75
  for await (const data of sync.streamResponse({
74
- storage: activeBucketStorage,
75
- parseOptions: routerEngine!.getAPI().getParseSyncRulesOptions(),
76
+ bucketStorage: bucketStorage,
77
+ syncRules: syncRules,
76
78
  params: {
77
79
  ...params,
78
80
  binary_data: true // always true for web sockets
@@ -36,15 +36,18 @@ export const syncStreamed = routeDefinition({
36
36
  const params: util.StreamingSyncRequest = payload.params;
37
37
  const syncParams = new RequestParameters(payload.context.token_payload!, payload.params.parameters ?? {});
38
38
 
39
- // Sanity check before we start the stream
40
- const cp = await storageEngine.activeBucketStorage.getActiveCheckpoint();
41
- if (!cp.hasSyncRules()) {
39
+ const bucketStorage = await storageEngine.activeBucketStorage.getActiveStorage();
40
+
41
+ if (bucketStorage == null) {
42
42
  throw new errors.ServiceError({
43
43
  status: 500,
44
44
  code: ErrorCode.PSYNC_S2302,
45
45
  description: 'No sync rules available'
46
46
  });
47
47
  }
48
+
49
+ const syncRules = bucketStorage.getParsedSyncRules(routerEngine!.getAPI().getParseSyncRulesOptions());
50
+
48
51
  const controller = new AbortController();
49
52
  const tracker = new sync.RequestTracker();
50
53
  try {
@@ -53,8 +56,8 @@ export const syncStreamed = routeDefinition({
53
56
  sync.transformToBytesTracked(
54
57
  sync.ndjson(
55
58
  sync.streamResponse({
56
- storage: storageEngine.activeBucketStorage,
57
- parseOptions: routerEngine!.getAPI().getParseSyncRulesOptions(),
59
+ bucketStorage,
60
+ syncRules: syncRules,
58
61
  params,
59
62
  syncParams,
60
63
  token: payload.context.token_payload!,
@@ -51,7 +51,7 @@ async function terminateSyncRules(storageFactory: storage.BucketStorageFactory,
51
51
 
52
52
  // Mark the sync rules as terminated
53
53
  for (let syncRules of combinedSyncRules) {
54
- using syncRulesStorage = storageFactory.getInstance(syncRules);
54
+ const syncRulesStorage = storageFactory.getInstance(syncRules);
55
55
  // The storage will be dropped at the end of the teardown, so we don't need to clear it here
56
56
  await syncRulesStorage.terminate({ clearStorage: false });
57
57
  }