@powersync/service-core 0.0.0-dev-20240725112650 → 0.0.0-dev-20240918092408

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 (331) hide show
  1. package/CHANGELOG.md +80 -2
  2. package/dist/api/RouteAPI.d.ts +68 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +11 -65
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +9 -79
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/KeyStore.d.ts +7 -4
  15. package/dist/auth/KeyStore.js +1 -1
  16. package/dist/auth/KeyStore.js.map +1 -1
  17. package/dist/auth/auth-index.d.ts +0 -1
  18. package/dist/auth/auth-index.js +0 -1
  19. package/dist/auth/auth-index.js.map +1 -1
  20. package/dist/entry/cli-entry.js +3 -2
  21. package/dist/entry/cli-entry.js.map +1 -1
  22. package/dist/entry/commands/compact-action.js +12 -8
  23. package/dist/entry/commands/compact-action.js.map +1 -1
  24. package/dist/entry/commands/migrate-action.js +4 -5
  25. package/dist/entry/commands/migrate-action.js.map +1 -1
  26. package/dist/entry/commands/teardown-action.js +2 -2
  27. package/dist/entry/commands/teardown-action.js.map +1 -1
  28. package/dist/index.d.ts +4 -2
  29. package/dist/index.js +4 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/metrics/Metrics.d.ts +2 -2
  32. package/dist/metrics/Metrics.js +5 -13
  33. package/dist/metrics/Metrics.js.map +1 -1
  34. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  35. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  36. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  37. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  38. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  39. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  40. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  41. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  42. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  43. package/dist/migrations/migrations.d.ts +8 -0
  44. package/dist/migrations/migrations.js +19 -7
  45. package/dist/migrations/migrations.js.map +1 -1
  46. package/dist/modules/AbstractModule.d.ts +26 -0
  47. package/dist/modules/AbstractModule.js +11 -0
  48. package/dist/modules/AbstractModule.js.map +1 -0
  49. package/dist/modules/ModuleManager.d.ts +11 -0
  50. package/dist/modules/ModuleManager.js +32 -0
  51. package/dist/modules/ModuleManager.js.map +1 -0
  52. package/dist/modules/modules-index.d.ts +2 -0
  53. package/dist/modules/modules-index.js +3 -0
  54. package/dist/modules/modules-index.js.map +1 -0
  55. package/dist/replication/AbstractReplicationJob.d.ts +38 -0
  56. package/dist/replication/AbstractReplicationJob.js +51 -0
  57. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  58. package/dist/replication/AbstractReplicator.d.ts +53 -0
  59. package/dist/replication/AbstractReplicator.js +187 -0
  60. package/dist/replication/AbstractReplicator.js.map +1 -0
  61. package/dist/replication/ErrorRateLimiter.d.ts +0 -9
  62. package/dist/replication/ErrorRateLimiter.js +1 -42
  63. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  64. package/dist/replication/ReplicationEngine.d.ts +18 -0
  65. package/dist/replication/ReplicationEngine.js +41 -0
  66. package/dist/replication/ReplicationEngine.js.map +1 -0
  67. package/dist/replication/ReplicationModule.d.ts +39 -0
  68. package/dist/replication/ReplicationModule.js +65 -0
  69. package/dist/replication/ReplicationModule.js.map +1 -0
  70. package/dist/replication/replication-index.d.ts +4 -6
  71. package/dist/replication/replication-index.js +4 -6
  72. package/dist/replication/replication-index.js.map +1 -1
  73. package/dist/routes/RouterEngine.d.ts +42 -0
  74. package/dist/routes/RouterEngine.js +80 -0
  75. package/dist/routes/RouterEngine.js.map +1 -0
  76. package/dist/routes/auth.d.ts +2 -2
  77. package/dist/routes/auth.js +11 -11
  78. package/dist/routes/auth.js.map +1 -1
  79. package/dist/routes/configure-fastify.d.ts +30 -176
  80. package/dist/routes/configure-fastify.js +10 -11
  81. package/dist/routes/configure-fastify.js.map +1 -1
  82. package/dist/routes/configure-rsocket.d.ts +3 -3
  83. package/dist/routes/configure-rsocket.js +6 -5
  84. package/dist/routes/configure-rsocket.js.map +1 -1
  85. package/dist/routes/endpoints/admin.d.ts +0 -34
  86. package/dist/routes/endpoints/admin.js +48 -89
  87. package/dist/routes/endpoints/admin.js.map +1 -1
  88. package/dist/routes/endpoints/checkpointing.d.ts +56 -16
  89. package/dist/routes/endpoints/checkpointing.js +33 -12
  90. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  91. package/dist/routes/endpoints/route-endpoints-index.d.ts +0 -1
  92. package/dist/routes/endpoints/route-endpoints-index.js +0 -1
  93. package/dist/routes/endpoints/route-endpoints-index.js.map +1 -1
  94. package/dist/routes/endpoints/socket-route.js +40 -25
  95. package/dist/routes/endpoints/socket-route.js.map +1 -1
  96. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  97. package/dist/routes/endpoints/sync-rules.js +32 -23
  98. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  99. package/dist/routes/endpoints/sync-stream.d.ts +10 -0
  100. package/dist/routes/endpoints/sync-stream.js +13 -8
  101. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  102. package/dist/routes/router-socket.d.ts +1 -0
  103. package/dist/routes/router-socket.js +2 -1
  104. package/dist/routes/router-socket.js.map +1 -1
  105. package/dist/routes/router.d.ts +6 -2
  106. package/dist/routes/router.js.map +1 -1
  107. package/dist/routes/routes-index.d.ts +1 -0
  108. package/dist/routes/routes-index.js +1 -0
  109. package/dist/routes/routes-index.js.map +1 -1
  110. package/dist/runner/teardown.js +47 -76
  111. package/dist/runner/teardown.js.map +1 -1
  112. package/dist/storage/BucketStorage.d.ts +30 -19
  113. package/dist/storage/BucketStorage.js +0 -10
  114. package/dist/storage/BucketStorage.js.map +1 -1
  115. package/dist/storage/MongoBucketStorage.d.ts +4 -4
  116. package/dist/storage/MongoBucketStorage.js +19 -24
  117. package/dist/storage/MongoBucketStorage.js.map +1 -1
  118. package/dist/storage/SourceEntity.d.ts +20 -0
  119. package/dist/storage/SourceEntity.js +2 -0
  120. package/dist/storage/SourceEntity.js.map +1 -0
  121. package/dist/storage/SourceTable.d.ts +4 -5
  122. package/dist/storage/SourceTable.js +3 -4
  123. package/dist/storage/SourceTable.js.map +1 -1
  124. package/dist/storage/StorageEngine.d.ts +24 -0
  125. package/dist/storage/StorageEngine.js +43 -0
  126. package/dist/storage/StorageEngine.js.map +1 -0
  127. package/dist/storage/StorageProvider.d.ts +21 -0
  128. package/dist/storage/StorageProvider.js +2 -0
  129. package/dist/storage/StorageProvider.js.map +1 -0
  130. package/dist/storage/mongo/MongoBucketBatch.d.ts +1 -1
  131. package/dist/storage/mongo/MongoBucketBatch.js +6 -7
  132. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  133. package/dist/storage/mongo/MongoCompactor.js +2 -1
  134. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  135. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  136. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  137. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  138. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  139. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  140. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  141. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +7 -6
  142. package/dist/storage/mongo/MongoSyncBucketStorage.js +24 -15
  143. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  144. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  145. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  146. package/dist/storage/mongo/OperationBatch.d.ts +7 -3
  147. package/dist/storage/mongo/OperationBatch.js +16 -7
  148. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  149. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  150. package/dist/storage/mongo/PersistedBatch.js +2 -2
  151. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  152. package/dist/storage/mongo/models.d.ts +13 -4
  153. package/dist/storage/mongo/models.js.map +1 -1
  154. package/dist/storage/mongo/util.d.ts +12 -1
  155. package/dist/storage/mongo/util.js +50 -2
  156. package/dist/storage/mongo/util.js.map +1 -1
  157. package/dist/storage/storage-index.d.ts +5 -2
  158. package/dist/storage/storage-index.js +5 -2
  159. package/dist/storage/storage-index.js.map +1 -1
  160. package/dist/sync/sync.d.ts +2 -1
  161. package/dist/sync/sync.js +36 -10
  162. package/dist/sync/sync.js.map +1 -1
  163. package/dist/sync/util.js.map +1 -1
  164. package/dist/system/ServiceContext.d.ts +37 -0
  165. package/dist/system/ServiceContext.js +48 -0
  166. package/dist/system/ServiceContext.js.map +1 -0
  167. package/dist/system/system-index.d.ts +1 -1
  168. package/dist/system/system-index.js +1 -1
  169. package/dist/system/system-index.js.map +1 -1
  170. package/dist/util/config/compound-config-collector.d.ts +9 -2
  171. package/dist/util/config/compound-config-collector.js +14 -23
  172. package/dist/util/config/compound-config-collector.js.map +1 -1
  173. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  174. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  175. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  176. package/dist/util/config/types.d.ts +6 -4
  177. package/dist/util/config/types.js.map +1 -1
  178. package/dist/util/config.d.ts +3 -4
  179. package/dist/util/config.js +5 -20
  180. package/dist/util/config.js.map +1 -1
  181. package/dist/util/protocol-types.d.ts +4 -0
  182. package/dist/util/protocol-types.js +5 -1
  183. package/dist/util/protocol-types.js.map +1 -1
  184. package/dist/util/util-index.d.ts +3 -6
  185. package/dist/util/util-index.js +3 -6
  186. package/dist/util/util-index.js.map +1 -1
  187. package/dist/util/utils.d.ts +10 -6
  188. package/dist/util/utils.js +45 -25
  189. package/dist/util/utils.js.map +1 -1
  190. package/package.json +5 -7
  191. package/src/api/RouteAPI.ts +78 -0
  192. package/src/api/api-index.ts +1 -0
  193. package/src/api/diagnostics.ts +16 -71
  194. package/src/api/schema.ts +13 -89
  195. package/src/auth/KeyStore.ts +9 -6
  196. package/src/auth/auth-index.ts +0 -1
  197. package/src/entry/cli-entry.ts +3 -2
  198. package/src/entry/commands/compact-action.ts +12 -9
  199. package/src/entry/commands/migrate-action.ts +5 -8
  200. package/src/entry/commands/teardown-action.ts +2 -2
  201. package/src/index.ts +5 -2
  202. package/src/metrics/Metrics.ts +6 -16
  203. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  204. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  205. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  206. package/src/migrations/migrations.ts +24 -8
  207. package/src/modules/AbstractModule.ts +37 -0
  208. package/src/modules/ModuleManager.ts +34 -0
  209. package/src/modules/modules-index.ts +2 -0
  210. package/src/replication/AbstractReplicationJob.ts +79 -0
  211. package/src/replication/AbstractReplicator.ts +227 -0
  212. package/src/replication/ErrorRateLimiter.ts +0 -44
  213. package/src/replication/ReplicationEngine.ts +43 -0
  214. package/src/replication/ReplicationModule.ts +101 -0
  215. package/src/replication/replication-index.ts +4 -6
  216. package/src/routes/RouterEngine.ts +120 -0
  217. package/src/routes/auth.ts +21 -12
  218. package/src/routes/configure-fastify.ts +13 -14
  219. package/src/routes/configure-rsocket.ts +9 -8
  220. package/src/routes/endpoints/admin.ts +74 -100
  221. package/src/routes/endpoints/checkpointing.ts +46 -12
  222. package/src/routes/endpoints/route-endpoints-index.ts +0 -1
  223. package/src/routes/endpoints/socket-route.ts +44 -27
  224. package/src/routes/endpoints/sync-rules.ts +41 -25
  225. package/src/routes/endpoints/sync-stream.ts +13 -8
  226. package/src/routes/router-socket.ts +2 -1
  227. package/src/routes/router.ts +6 -3
  228. package/src/routes/routes-index.ts +1 -0
  229. package/src/runner/teardown.ts +50 -88
  230. package/src/storage/BucketStorage.ts +38 -25
  231. package/src/storage/MongoBucketStorage.ts +23 -26
  232. package/src/storage/SourceEntity.ts +22 -0
  233. package/src/storage/SourceTable.ts +4 -6
  234. package/src/storage/StorageEngine.ts +55 -0
  235. package/src/storage/StorageProvider.ts +27 -0
  236. package/src/storage/mongo/MongoBucketBatch.ts +8 -8
  237. package/src/storage/mongo/MongoCompactor.ts +2 -1
  238. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +3 -3
  239. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  240. package/src/storage/mongo/MongoSyncBucketStorage.ts +39 -20
  241. package/src/storage/mongo/MongoSyncRulesLock.ts +1 -1
  242. package/src/storage/mongo/OperationBatch.ts +18 -11
  243. package/src/storage/mongo/PersistedBatch.ts +6 -5
  244. package/src/storage/mongo/models.ts +13 -4
  245. package/src/storage/mongo/util.ts +49 -4
  246. package/src/storage/storage-index.ts +5 -2
  247. package/src/sync/sync.ts +46 -11
  248. package/src/sync/util.ts +0 -1
  249. package/src/system/ServiceContext.ts +68 -0
  250. package/src/system/system-index.ts +1 -1
  251. package/src/util/config/compound-config-collector.ts +30 -31
  252. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  253. package/src/util/config/types.ts +6 -5
  254. package/src/util/config.ts +6 -23
  255. package/src/util/protocol-types.ts +6 -1
  256. package/src/util/util-index.ts +3 -6
  257. package/src/util/utils.ts +55 -39
  258. package/test/src/__snapshots__/sync.test.ts.snap +7 -7
  259. package/test/src/auth.test.ts +7 -7
  260. package/test/src/broadcast_iterable.test.ts +1 -1
  261. package/test/src/checksum_cache.test.ts +3 -3
  262. package/test/src/compacting.test.ts +26 -17
  263. package/test/src/data_storage.test.ts +258 -146
  264. package/test/src/env.ts +1 -3
  265. package/test/src/merge_iterable.test.ts +1 -6
  266. package/test/src/setup.ts +1 -1
  267. package/test/src/stream_utils.ts +42 -0
  268. package/test/src/sync.test.ts +52 -31
  269. package/test/src/util.ts +48 -51
  270. package/test/tsconfig.json +1 -1
  271. package/tsconfig.tsbuildinfo +1 -1
  272. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  273. package/dist/auth/SupabaseKeyCollector.js +0 -61
  274. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  275. package/dist/replication/PgRelation.d.ts +0 -16
  276. package/dist/replication/PgRelation.js +0 -26
  277. package/dist/replication/PgRelation.js.map +0 -1
  278. package/dist/replication/WalConnection.d.ts +0 -34
  279. package/dist/replication/WalConnection.js +0 -190
  280. package/dist/replication/WalConnection.js.map +0 -1
  281. package/dist/replication/WalStream.d.ts +0 -57
  282. package/dist/replication/WalStream.js +0 -515
  283. package/dist/replication/WalStream.js.map +0 -1
  284. package/dist/replication/WalStreamManager.d.ts +0 -30
  285. package/dist/replication/WalStreamManager.js +0 -198
  286. package/dist/replication/WalStreamManager.js.map +0 -1
  287. package/dist/replication/WalStreamRunner.d.ts +0 -38
  288. package/dist/replication/WalStreamRunner.js +0 -155
  289. package/dist/replication/WalStreamRunner.js.map +0 -1
  290. package/dist/replication/util.d.ts +0 -9
  291. package/dist/replication/util.js +0 -62
  292. package/dist/replication/util.js.map +0 -1
  293. package/dist/routes/endpoints/dev.d.ts +0 -312
  294. package/dist/routes/endpoints/dev.js +0 -172
  295. package/dist/routes/endpoints/dev.js.map +0 -1
  296. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  297. package/dist/system/CorePowerSyncSystem.js +0 -52
  298. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  299. package/dist/util/PgManager.d.ts +0 -24
  300. package/dist/util/PgManager.js +0 -55
  301. package/dist/util/PgManager.js.map +0 -1
  302. package/dist/util/migration_lib.d.ts +0 -11
  303. package/dist/util/migration_lib.js +0 -64
  304. package/dist/util/migration_lib.js.map +0 -1
  305. package/dist/util/pgwire_utils.d.ts +0 -24
  306. package/dist/util/pgwire_utils.js +0 -117
  307. package/dist/util/pgwire_utils.js.map +0 -1
  308. package/dist/util/populate_test_data.d.ts +0 -8
  309. package/dist/util/populate_test_data.js +0 -65
  310. package/dist/util/populate_test_data.js.map +0 -1
  311. package/src/auth/SupabaseKeyCollector.ts +0 -67
  312. package/src/replication/PgRelation.ts +0 -42
  313. package/src/replication/WalConnection.ts +0 -227
  314. package/src/replication/WalStream.ts +0 -624
  315. package/src/replication/WalStreamManager.ts +0 -213
  316. package/src/replication/WalStreamRunner.ts +0 -180
  317. package/src/replication/util.ts +0 -76
  318. package/src/routes/endpoints/dev.ts +0 -199
  319. package/src/system/CorePowerSyncSystem.ts +0 -64
  320. package/src/util/PgManager.ts +0 -64
  321. package/src/util/migration_lib.ts +0 -79
  322. package/src/util/pgwire_utils.ts +0 -139
  323. package/src/util/populate_test_data.ts +0 -78
  324. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  325. package/test/src/large_batch.test.ts +0 -194
  326. package/test/src/pg_test.test.ts +0 -450
  327. package/test/src/schema_changes.test.ts +0 -545
  328. package/test/src/slow_tests.test.ts +0 -338
  329. package/test/src/validation.test.ts +0 -63
  330. package/test/src/wal_stream.test.ts +0 -319
  331. package/test/src/wal_stream_utils.ts +0 -156
@@ -1,17 +1,19 @@
1
- import * as mongo from 'mongodb';
2
- import * as timers from 'timers/promises';
3
- import { LRUCache } from 'lru-cache/min';
4
1
  import { SqlSyncRules } from '@powersync/service-sync-rules';
5
2
  import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
3
+ import { LRUCache } from 'lru-cache/min';
4
+ import * as mongo from 'mongodb';
5
+ import * as timers from 'timers/promises';
6
6
 
7
- import * as replication from '../replication/replication-index.js';
7
+ import * as locks from '../locks/locks-index.js';
8
8
  import * as sync from '../sync/sync-index.js';
9
9
  import * as util from '../util/util-index.js';
10
- import * as locks from '../locks/locks-index.js';
11
10
 
11
+ import { logger } from '@powersync/lib-services-framework';
12
+ import { v4 as uuid } from 'uuid';
12
13
  import {
13
14
  ActiveCheckpoint,
14
15
  BucketStorageFactory,
16
+ ParseSyncRulesOptions,
15
17
  PersistedSyncRules,
16
18
  PersistedSyncRulesContent,
17
19
  StorageMetrics,
@@ -23,14 +25,13 @@ import { MongoSyncBucketStorage } from './mongo/MongoSyncBucketStorage.js';
23
25
  import { PowerSyncMongo, PowerSyncMongoOptions } from './mongo/db.js';
24
26
  import { SyncRuleDocument, SyncRuleState } from './mongo/models.js';
25
27
  import { generateSlotName } from './mongo/util.js';
26
- import { v4 as uuid } from 'uuid';
27
- import { logger } from '@powersync/lib-services-framework';
28
28
 
29
29
  export interface MongoBucketStorageOptions extends PowerSyncMongoOptions {}
30
30
 
31
31
  export class MongoBucketStorage implements BucketStorageFactory {
32
32
  private readonly client: mongo.MongoClient;
33
33
  private readonly session: mongo.ClientSession;
34
+ // TODO: This is still Postgres specific and needs to be reworked
34
35
  public readonly slot_name_prefix: string;
35
36
 
36
37
  private readonly storageCache = new LRUCache<number, MongoSyncBucketStorage>({
@@ -47,8 +48,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
47
48
  return undefined;
48
49
  }
49
50
  const rules = new MongoPersistedSyncRulesContent(this.db, doc2);
50
- const storage = this.getInstance(rules.parsed());
51
- return storage;
51
+ return this.getInstance(rules);
52
52
  }
53
53
  });
54
54
 
@@ -61,12 +61,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
61
61
  this.slot_name_prefix = options.slot_name_prefix;
62
62
  }
63
63
 
64
- getInstance(options: PersistedSyncRules): MongoSyncBucketStorage {
65
- let { id, sync_rules, slot_name } = options;
64
+ getInstance(options: PersistedSyncRulesContent): MongoSyncBucketStorage {
65
+ let { id, slot_name } = options;
66
66
  if ((typeof id as any) == 'bigint') {
67
67
  id = Number(id);
68
68
  }
69
- return new MongoSyncBucketStorage(this, id, sync_rules, slot_name);
69
+ return new MongoSyncBucketStorage(this, id, options, slot_name);
70
70
  }
71
71
 
72
72
  async configureSyncRules(sync_rules: string, options?: { lock?: boolean }) {
@@ -136,7 +136,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
136
136
 
137
137
  async updateSyncRules(options: UpdateSyncRulesOptions): Promise<MongoPersistedSyncRulesContent> {
138
138
  // Parse and validate before applying any changes
139
- const parsed = SqlSyncRules.fromYaml(options.content);
139
+ const parsed = SqlSyncRules.fromYaml(options.content, {
140
+ // No schema-based validation at this point
141
+ schema: undefined,
142
+ defaultSchema: 'not_applicable', // Not needed for validation
143
+ throwOnError: true
144
+ });
140
145
 
141
146
  let rules: MongoPersistedSyncRulesContent | undefined = undefined;
142
147
 
@@ -204,9 +209,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
204
209
  return new MongoPersistedSyncRulesContent(this.db, doc);
205
210
  }
206
211
 
207
- async getActiveSyncRules(): Promise<PersistedSyncRules | null> {
212
+ async getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
208
213
  const content = await this.getActiveSyncRulesContent();
209
- return content?.parsed() ?? null;
214
+ return content?.parsed(options) ?? null;
210
215
  }
211
216
 
212
217
  async getNextSyncRulesContent(): Promise<MongoPersistedSyncRulesContent | null> {
@@ -223,9 +228,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
223
228
  return new MongoPersistedSyncRulesContent(this.db, doc);
224
229
  }
225
230
 
226
- async getNextSyncRules(): Promise<PersistedSyncRules | null> {
231
+ async getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
227
232
  const content = await this.getNextSyncRulesContent();
228
- return content?.parsed() ?? null;
233
+ return content?.parsed(options) ?? null;
229
234
  }
230
235
 
231
236
  async getReplicatingSyncRules(): Promise<PersistedSyncRulesContent[]> {
@@ -294,14 +299,6 @@ export class MongoBucketStorage implements BucketStorageFactory {
294
299
  }
295
300
 
296
301
  async getStorageMetrics(): Promise<StorageMetrics> {
297
- const active_sync_rules = await this.getActiveSyncRules();
298
- if (active_sync_rules == null) {
299
- return {
300
- operations_size_bytes: 0,
301
- parameters_size_bytes: 0,
302
- replication_size_bytes: 0
303
- };
304
- }
305
302
  const operations_aggregate = await this.db.bucket_data
306
303
 
307
304
  .aggregate([
@@ -370,7 +367,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
370
367
  private makeActiveCheckpoint(doc: SyncRuleDocument | null) {
371
368
  return {
372
369
  checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n),
373
- lsn: doc?.last_checkpoint_lsn ?? replication.ZERO_LSN,
370
+ lsn: doc?.last_checkpoint_lsn ?? null,
374
371
  hasSyncRules() {
375
372
  return doc != null;
376
373
  },
@@ -0,0 +1,22 @@
1
+ export interface ColumnDescriptor {
2
+ name: string;
3
+ /**
4
+ * The type of the column ie VARCHAR, INT, etc
5
+ */
6
+ type?: string;
7
+ /**
8
+ * Some data sources have a type id that can be used to identify the type of the column
9
+ */
10
+ typeId?: number;
11
+ }
12
+
13
+ // TODO: This needs to be consolidated with SourceTable into something new.
14
+ export interface SourceEntityDescriptor {
15
+ /**
16
+ * The internal id of the data source structure in the database
17
+ */
18
+ objectId: number | string;
19
+ schema: string;
20
+ name: string;
21
+ replicationColumns: ColumnDescriptor[];
22
+ }
@@ -1,10 +1,8 @@
1
- import { DEFAULT_SCHEMA, DEFAULT_TAG } from '@powersync/service-sync-rules';
2
-
3
- import * as replication from '../replication/replication-index.js';
1
+ import { DEFAULT_TAG } from '@powersync/service-sync-rules';
4
2
  import * as util from '../util/util-index.js';
3
+ import { ColumnDescriptor } from './SourceEntity.js';
5
4
 
6
5
  export class SourceTable {
7
- static readonly DEFAULT_SCHEMA = DEFAULT_SCHEMA;
8
6
  static readonly DEFAULT_TAG = DEFAULT_TAG;
9
7
 
10
8
  /**
@@ -28,11 +26,11 @@ export class SourceTable {
28
26
  constructor(
29
27
  public readonly id: any,
30
28
  public readonly connectionTag: string,
31
- public readonly relationId: number,
29
+ public readonly objectId: number | string,
32
30
  public readonly schema: string,
33
31
  public readonly table: string,
34
32
 
35
- public readonly replicaIdColumns: replication.ReplicationColumn[],
33
+ public readonly replicaIdColumns: ColumnDescriptor[],
36
34
  public readonly snapshotComplete: boolean
37
35
  ) {}
38
36
 
@@ -0,0 +1,55 @@
1
+ import { ResolvedPowerSyncConfig } from '../util/util-index.js';
2
+ import { BucketStorageFactory } from './BucketStorage.js';
3
+ import { BucketStorageProvider, ActiveStorage } from './StorageProvider.js';
4
+ import { logger } from '@powersync/lib-services-framework';
5
+
6
+ export type StorageEngineOptions = {
7
+ configuration: ResolvedPowerSyncConfig;
8
+ };
9
+
10
+ export class StorageEngine {
11
+ // TODO: This will need to revisited when we actually support multiple storage providers.
12
+ private storageProviders: Map<string, BucketStorageProvider> = new Map();
13
+ private currentActiveStorage: ActiveStorage | null = null;
14
+
15
+ constructor(private options: StorageEngineOptions) {}
16
+
17
+ get activeBucketStorage(): BucketStorageFactory {
18
+ return this.activeStorage.storage;
19
+ }
20
+
21
+ get activeStorage(): ActiveStorage {
22
+ if (!this.currentActiveStorage) {
23
+ throw new Error(`No storage provider has been initialized yet.`);
24
+ }
25
+
26
+ return this.currentActiveStorage;
27
+ }
28
+
29
+ /**
30
+ * Register a provider which generates a {@link BucketStorageFactory}
31
+ * given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
32
+ */
33
+ registerProvider(provider: BucketStorageProvider) {
34
+ this.storageProviders.set(provider.type, provider);
35
+ }
36
+
37
+ public async start(): Promise<void> {
38
+ logger.info('Starting Storage Engine...');
39
+ const { configuration } = this.options;
40
+ this.currentActiveStorage = await this.storageProviders.get(configuration.storage.type)!.getStorage({
41
+ resolvedConfig: configuration
42
+ });
43
+ logger.info(`Successfully activated storage: ${configuration.storage.type}.`);
44
+ logger.info('Successfully started Storage Engine.');
45
+ }
46
+
47
+ /**
48
+ * Shutdown the storage engine, safely shutting down any activated storage providers.
49
+ */
50
+ public async shutDown(): Promise<void> {
51
+ logger.info('Shutting down Storage Engine...');
52
+ await this.currentActiveStorage?.shutDown();
53
+ logger.info('Successfully shut down Storage Engine.');
54
+ }
55
+ }
@@ -0,0 +1,27 @@
1
+ import { BucketStorageFactory } from './BucketStorage.js';
2
+ import * as util from '../util/util-index.js';
3
+
4
+ export interface ActiveStorage {
5
+ storage: BucketStorageFactory;
6
+ shutDown(): Promise<void>;
7
+
8
+ /**
9
+ * Tear down / drop the storage permanently
10
+ */
11
+ tearDown(): Promise<boolean>;
12
+ }
13
+
14
+ export interface GetStorageOptions {
15
+ // TODO: This should just be the storage config. Update once the slot name prefix coupling has been removed from the storage
16
+ resolvedConfig: util.ResolvedPowerSyncConfig;
17
+ }
18
+
19
+ export interface BucketStorageProvider {
20
+ /**
21
+ * The storage type that this provider provides.
22
+ * The type should match the `type` field in the config.
23
+ */
24
+ type: string;
25
+
26
+ getStorage(options: GetStorageOptions): Promise<ActiveStorage>;
27
+ }
@@ -2,9 +2,8 @@ import { SqliteRow, SqlSyncRules } from '@powersync/service-sync-rules';
2
2
  import * as bson from 'bson';
3
3
  import * as mongo from 'mongodb';
4
4
 
5
- import * as util from '../../util/util-index.js';
6
- import * as replication from '../../replication/replication-index.js';
7
5
  import { container, errors, logger } from '@powersync/lib-services-framework';
6
+ import * as util from '../../util/util-index.js';
8
7
  import { BucketStorageBatch, FlushedResult, mergeToast, SaveOptions } from '../BucketStorage.js';
9
8
  import { SourceTable } from '../SourceTable.js';
10
9
  import { PowerSyncMongo } from './db.js';
@@ -12,7 +11,7 @@ import { CurrentBucket, CurrentDataDocument, SourceKey } from './models.js';
12
11
  import { MongoIdSequence } from './MongoIdSequence.js';
13
12
  import { cacheKey, OperationBatch, RecordOperation } from './OperationBatch.js';
14
13
  import { PersistedBatch } from './PersistedBatch.js';
15
- import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, serializeLookup } from './util.js';
14
+ import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, replicaIdEquals, serializeLookup } from './util.js';
16
15
 
17
16
  /**
18
17
  * 15MB
@@ -25,6 +24,7 @@ const MAX_ROW_SIZE = 15 * 1024 * 1024;
25
24
  //
26
25
  // In the future, we can investigate allowing multiple replication streams operating independently.
27
26
  const replicationMutex = new util.Mutex();
27
+
28
28
  export class MongoBucketBatch implements BucketStorageBatch {
29
29
  private readonly client: mongo.MongoClient;
30
30
  public readonly db: PowerSyncMongo;
@@ -61,7 +61,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
61
61
  group_id: number,
62
62
  slot_name: string,
63
63
  last_checkpoint_lsn: string | null,
64
- no_checkpoint_before_lsn: string | null
64
+ no_checkpoint_before_lsn: string
65
65
  ) {
66
66
  this.db = db;
67
67
  this.client = db.client;
@@ -70,7 +70,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
70
70
  this.slot_name = slot_name;
71
71
  this.session = this.client.startSession();
72
72
  this.last_checkpoint_lsn = last_checkpoint_lsn;
73
- this.no_checkpoint_before_lsn = no_checkpoint_before_lsn ?? replication.ZERO_LSN;
73
+ this.no_checkpoint_before_lsn = no_checkpoint_before_lsn;
74
74
  }
75
75
 
76
76
  async flush(): Promise<FlushedResult | null> {
@@ -301,7 +301,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
301
301
  }
302
302
 
303
303
  // 2. Save bucket data
304
- if (beforeId != null && (afterId == null || !beforeId.equals(afterId))) {
304
+ if (beforeId != null && (afterId == null || !replicaIdEquals(beforeId, afterId))) {
305
305
  // Source ID updated
306
306
  if (sourceTable.syncData) {
307
307
  // Delete old record
@@ -431,7 +431,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
431
431
  };
432
432
  }
433
433
 
434
- if (afterId == null || !beforeId.equals(afterId)) {
434
+ if (afterId == null || !replicaIdEquals(beforeId, afterId)) {
435
435
  // Either a delete (afterId == null), or replaced the old replication id
436
436
  batch.deleteCurrentData(before_key);
437
437
  }
@@ -743,7 +743,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
743
743
  const copy = new SourceTable(
744
744
  table.id,
745
745
  table.connectionTag,
746
- table.relationId,
746
+ table.objectId,
747
747
  table.schema,
748
748
  table.table,
749
749
  table.replicaIdColumns,
@@ -4,6 +4,7 @@ import { addChecksums } from '../../util/utils.js';
4
4
  import { PowerSyncMongo } from './db.js';
5
5
  import { BucketDataDocument, BucketDataKey } from './models.js';
6
6
  import { CompactOptions } from '../BucketStorage.js';
7
+ import { cacheKey } from './OperationBatch.js';
7
8
 
8
9
  interface CurrentBucketState {
9
10
  /** Bucket name */
@@ -168,7 +169,7 @@ export class MongoCompactor {
168
169
  let isPersistentPut = doc.op == 'PUT';
169
170
 
170
171
  if (doc.op == 'REMOVE' || doc.op == 'PUT') {
171
- const key = `${doc.table}/${doc.row_id}/${doc.source_table}/${doc.source_key?.toHexString()}`;
172
+ const key = `${doc.table}/${doc.row_id}/${cacheKey(doc.source_table!, doc.source_key!)}`;
172
173
  const targetOp = currentState.seen.get(key);
173
174
  if (targetOp) {
174
175
  // Will convert to MOVE, so don't count as PUT
@@ -1,7 +1,7 @@
1
1
  import { SqlSyncRules } from '@powersync/service-sync-rules';
2
2
  import * as mongo from 'mongodb';
3
3
 
4
- import { PersistedSyncRulesContent } from '../BucketStorage.js';
4
+ import { ParseSyncRulesOptions, PersistedSyncRulesContent } from '../BucketStorage.js';
5
5
  import { MongoPersistedSyncRules } from './MongoPersistedSyncRules.js';
6
6
  import { MongoSyncRulesLock } from './MongoSyncRulesLock.js';
7
7
  import { PowerSyncMongo } from './db.js';
@@ -30,10 +30,10 @@ export class MongoPersistedSyncRulesContent implements PersistedSyncRulesContent
30
30
  this.last_keepalive_ts = doc.last_keepalive_ts;
31
31
  }
32
32
 
33
- parsed() {
33
+ parsed(options: ParseSyncRulesOptions) {
34
34
  return new MongoPersistedSyncRules(
35
35
  this.id,
36
- SqlSyncRules.fromYaml(this.sync_rules_content),
36
+ SqlSyncRules.fromYaml(this.sync_rules_content, options),
37
37
  this.last_checkpoint_lsn,
38
38
  this.slot_name
39
39
  );
@@ -0,0 +1,31 @@
1
+ import * as db from '../../db/db-index.js';
2
+ import { MongoBucketStorage } from '../MongoBucketStorage.js';
3
+ import { BucketStorageProvider, ActiveStorage, GetStorageOptions } from '../StorageProvider.js';
4
+ import { PowerSyncMongo } from './db.js';
5
+ import { logger } from '@powersync/lib-services-framework';
6
+
7
+ export class MongoStorageProvider implements BucketStorageProvider {
8
+ get type() {
9
+ return 'mongodb';
10
+ }
11
+
12
+ async getStorage(options: GetStorageOptions): Promise<ActiveStorage> {
13
+ const { resolvedConfig } = options;
14
+
15
+ const client = db.mongo.createMongoClient(resolvedConfig.storage);
16
+
17
+ const database = new PowerSyncMongo(client, { database: resolvedConfig.storage.database });
18
+
19
+ return {
20
+ storage: new MongoBucketStorage(database, {
21
+ // TODO currently need the entire resolved config due to this
22
+ slot_name_prefix: resolvedConfig.slot_name_prefix
23
+ }),
24
+ shutDown: () => client.close(),
25
+ tearDown: () => {
26
+ logger.info(`Tearing down storage: ${database.db.namespace}...`);
27
+ return database.db.dropDatabase();
28
+ }
29
+ } satisfies ActiveStorage;
30
+ }
31
+ }
@@ -3,7 +3,6 @@ import * as bson from 'bson';
3
3
  import * as mongo from 'mongodb';
4
4
 
5
5
  import * as db from '../../db/db-index.js';
6
- import * as replication from '../../replication/WalStream.js';
7
6
  import * as util from '../../util/util-index.js';
8
7
  import {
9
8
  BucketDataBatchOptions,
@@ -12,11 +11,16 @@ import {
12
11
  DEFAULT_DOCUMENT_BATCH_LIMIT,
13
12
  DEFAULT_DOCUMENT_CHUNK_LIMIT_BYTES,
14
13
  FlushedResult,
14
+ ParseSyncRulesOptions,
15
+ PersistedSyncRules,
16
+ PersistedSyncRulesContent,
15
17
  ResolveTableOptions,
16
18
  ResolveTableResult,
19
+ StartBatchOptions,
17
20
  SyncBucketDataBatch,
18
21
  SyncRulesBucketStorage,
19
- SyncRuleStatus
22
+ SyncRuleStatus,
23
+ TerminateOptions
20
24
  } from '../BucketStorage.js';
21
25
  import { ChecksumCache, FetchPartialBucketChecksum } from '../ChecksumCache.js';
22
26
  import { MongoBucketStorage } from '../MongoBucketStorage.js';
@@ -35,29 +39,38 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
35
39
  }
36
40
  });
37
41
 
42
+ private parsedSyncRulesCache: SqlSyncRules | undefined;
43
+
38
44
  constructor(
39
45
  public readonly factory: MongoBucketStorage,
40
46
  public readonly group_id: number,
41
- public readonly sync_rules: SqlSyncRules,
47
+ private readonly sync_rules: PersistedSyncRulesContent,
42
48
  public readonly slot_name: string
43
49
  ) {
44
50
  this.db = factory.db;
45
51
  }
46
52
 
53
+ getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules {
54
+ this.parsedSyncRulesCache ??= this.sync_rules.parsed(options).sync_rules;
55
+ return this.parsedSyncRulesCache;
56
+ }
57
+
47
58
  async getCheckpoint() {
48
59
  const doc = await this.db.sync_rules.findOne(
49
60
  { _id: this.group_id },
50
61
  {
51
- projection: { last_checkpoint: 1, last_checkpoint_lsn: 1 }
62
+ projection: { last_checkpoint: 1 }
52
63
  }
53
64
  );
54
65
  return {
55
- checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n),
56
- lsn: doc?.last_checkpoint_lsn ?? replication.ZERO_LSN
66
+ checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n)
57
67
  };
58
68
  }
59
69
 
60
- async startBatch(options: {}, callback: (batch: BucketStorageBatch) => Promise<void>): Promise<FlushedResult | null> {
70
+ async startBatch(
71
+ options: StartBatchOptions,
72
+ callback: (batch: BucketStorageBatch) => Promise<void>
73
+ ): Promise<FlushedResult | null> {
61
74
  const doc = await this.db.sync_rules.findOne(
62
75
  {
63
76
  _id: this.group_id
@@ -68,11 +81,11 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
68
81
 
69
82
  const batch = new MongoBucketBatch(
70
83
  this.db,
71
- this.sync_rules,
84
+ this.sync_rules.parsed(options).sync_rules,
72
85
  this.group_id,
73
86
  this.slot_name,
74
87
  checkpoint_lsn,
75
- doc?.no_checkpoint_before ?? null
88
+ doc?.no_checkpoint_before ?? options.zeroLSN
76
89
  );
77
90
  try {
78
91
  await callback(batch);
@@ -90,11 +103,15 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
90
103
  }
91
104
 
92
105
  async resolveTable(options: ResolveTableOptions): Promise<ResolveTableResult> {
93
- const { group_id, connection_id, connection_tag, relation } = options;
106
+ const { group_id, connection_id, connection_tag, entity_descriptor } = options;
94
107
 
95
- const { schema, name: table, relationId, replicationColumns } = relation;
108
+ const { schema, name: table, objectId, replicationColumns } = entity_descriptor;
96
109
 
97
- const columns = replicationColumns.map((column) => ({ name: column.name, type_oid: column.typeOid }));
110
+ const columns = replicationColumns.map((column) => ({
111
+ name: column.name,
112
+ type: column.type,
113
+ type_oid: column.typeId
114
+ }));
98
115
  let result: ResolveTableResult | null = null;
99
116
  await this.db.client.withSession(async (session) => {
100
117
  const col = this.db.source_tables;
@@ -102,7 +119,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
102
119
  {
103
120
  group_id: group_id,
104
121
  connection_id: connection_id,
105
- relation_id: relationId,
122
+ relation_id: objectId,
106
123
  schema_name: schema,
107
124
  table_name: table,
108
125
  replica_id_columns2: columns
@@ -114,7 +131,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
114
131
  _id: new bson.ObjectId(),
115
132
  group_id: group_id,
116
133
  connection_id: connection_id,
117
- relation_id: relationId,
134
+ relation_id: objectId,
118
135
  schema_name: schema,
119
136
  table_name: table,
120
137
  replica_id_columns: null,
@@ -127,7 +144,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
127
144
  const sourceTable = new SourceTable(
128
145
  doc._id,
129
146
  connection_tag,
130
- relationId,
147
+ objectId,
131
148
  schema,
132
149
  table,
133
150
  replicationColumns,
@@ -142,7 +159,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
142
159
  group_id: group_id,
143
160
  connection_id: connection_id,
144
161
  _id: { $ne: doc._id },
145
- $or: [{ relation_id: relationId }, { schema_name: schema, table_name: table }]
162
+ $or: [{ relation_id: objectId }, { schema_name: schema, table_name: table }]
146
163
  },
147
164
  { session }
148
165
  )
@@ -157,7 +174,7 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
157
174
  doc.relation_id ?? 0,
158
175
  doc.schema_name,
159
176
  doc.table_name,
160
- doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid })) ?? [],
177
+ doc.replica_id_columns2?.map((c) => ({ name: c.name, typeOid: c.type_oid, type: c.type })) ?? [],
161
178
  doc.snapshot_done ?? true
162
179
  )
163
180
  )
@@ -386,9 +403,11 @@ export class MongoSyncBucketStorage implements SyncRulesBucketStorage {
386
403
  );
387
404
  }
388
405
 
389
- async terminate() {
390
- await this.clear();
391
-
406
+ async terminate(options?: TerminateOptions) {
407
+ // Default is to clear the storage except when explicitly requested not to.
408
+ if (!options || options?.clearStorage) {
409
+ await this.clear();
410
+ }
392
411
  await this.db.sync_rules.updateOne(
393
412
  {
394
413
  _id: this.group_id
@@ -30,7 +30,7 @@ export class MongoSyncRulesLock implements ReplicationLock {
30
30
  );
31
31
 
32
32
  if (doc == null) {
33
- throw new Error(`Replication slot ${sync_rules.slot_name} is locked by another process`);
33
+ throw new Error(`Sync rules: ${sync_rules.id} have been locked by another process for replication.`);
34
34
  }
35
35
  return new MongoSyncRulesLock(db, sync_rules.id, lockId);
36
36
  }
@@ -1,8 +1,9 @@
1
- import * as bson from 'bson';
2
1
  import { ToastableSqliteRow } from '@powersync/service-sync-rules';
2
+ import * as bson from 'bson';
3
3
 
4
- import * as util from '../../util/util-index.js';
5
4
  import { SaveOptions } from '../BucketStorage.js';
5
+ import { isUUID } from './util.js';
6
+ import { ReplicaId } from './models.js';
6
7
 
7
8
  /**
8
9
  * Maximum number of operations in a batch.
@@ -63,18 +64,15 @@ export class OperationBatch {
63
64
  }
64
65
 
65
66
  export class RecordOperation {
66
- public readonly afterId: bson.UUID | null;
67
- public readonly beforeId: bson.UUID;
67
+ public readonly afterId: ReplicaId | null;
68
+ public readonly beforeId: ReplicaId;
68
69
  public readonly internalBeforeKey: string;
69
70
  public readonly internalAfterKey: string | null;
70
71
  public readonly estimatedSize: number;
71
72
 
72
73
  constructor(public readonly record: SaveOptions) {
73
- const after = record.after;
74
- const afterId = after ? util.getUuidReplicaIdentityBson(after, record.sourceTable.replicaIdColumns!) : null;
75
- const beforeId = record.before
76
- ? util.getUuidReplicaIdentityBson(record.before, record.sourceTable.replicaIdColumns!)
77
- : afterId!;
74
+ const afterId = record.afterReplicaId ?? null;
75
+ const beforeId = record.beforeReplicaId ?? record.afterReplicaId;
78
76
  this.afterId = afterId;
79
77
  this.beforeId = beforeId;
80
78
  this.internalBeforeKey = cacheKey(record.sourceTable.id, beforeId);
@@ -84,8 +82,17 @@ export class RecordOperation {
84
82
  }
85
83
  }
86
84
 
87
- export function cacheKey(table: bson.ObjectId, id: bson.UUID) {
88
- return `${table.toHexString()}.${id.toHexString()}`;
85
+ /**
86
+ * In-memory cache key - must not be persisted.
87
+ */
88
+ export function cacheKey(table: bson.ObjectId, id: ReplicaId) {
89
+ if (isUUID(id)) {
90
+ return `${table.toHexString()}.${id.toHexString()}`;
91
+ } else if (typeof id == 'string') {
92
+ return `${table.toHexString()}.${id}`;
93
+ } else {
94
+ return `${table.toHexString()}.${(bson.serialize({ id: id }) as Buffer).toString('base64')}`;
95
+ }
89
96
  }
90
97
 
91
98
  /**
@@ -13,9 +13,10 @@ import {
13
13
  BucketParameterDocument,
14
14
  CurrentBucket,
15
15
  CurrentDataDocument,
16
- SourceKey
16
+ SourceKey,
17
+ ReplicaId
17
18
  } from './models.js';
18
- import { serializeLookup } from './util.js';
19
+ import { replicaIdToSubkey, serializeLookup } from './util.js';
19
20
  import { logger } from '@powersync/lib-services-framework';
20
21
 
21
22
  /**
@@ -59,7 +60,7 @@ export class PersistedBatch {
59
60
 
60
61
  saveBucketData(options: {
61
62
  op_seq: MongoIdSequence;
62
- sourceKey: bson.UUID;
63
+ sourceKey: ReplicaId;
63
64
  table: SourceTable;
64
65
  evaluated: EvaluatedRow[];
65
66
  before_buckets: CurrentBucket[];
@@ -70,7 +71,7 @@ export class PersistedBatch {
70
71
  remaining_buckets.set(key, b);
71
72
  }
72
73
 
73
- const dchecksum = util.hashDelete(`${options.table.id}/${options.sourceKey}`);
74
+ const dchecksum = util.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey));
74
75
 
75
76
  for (let k of options.evaluated) {
76
77
  const key = currentBucketKey(k);
@@ -134,7 +135,7 @@ export class PersistedBatch {
134
135
 
135
136
  saveParameterData(data: {
136
137
  op_seq: MongoIdSequence;
137
- sourceKey: bson.UUID;
138
+ sourceKey: ReplicaId;
138
139
  sourceTable: SourceTable;
139
140
  evaluated: EvaluatedParameters[];
140
141
  existing_lookups: bson.Binary[];