@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
@@ -5,7 +5,6 @@ import * as system from '../system/system-index.js';
5
5
 
6
6
  import { ADMIN_ROUTES } from './endpoints/admin.js';
7
7
  import { CHECKPOINT_ROUTES } from './endpoints/checkpointing.js';
8
- import { DEV_ROUTES } from './endpoints/dev.js';
9
8
  import { SYNC_RULES_ROUTES } from './endpoints/sync-rules.js';
10
9
  import { SYNC_STREAM_ROUTES } from './endpoints/sync-stream.js';
11
10
  import { createRequestQueueHook, CreateRequestQueueParams } from './hooks.js';
@@ -17,7 +16,7 @@ import { RouteDefinition } from './router.js';
17
16
  */
18
17
  export type RouteRegistrationOptions = {
19
18
  routes: RouteDefinition[];
20
- queueOptions: CreateRequestQueueParams;
19
+ queue_options: CreateRequestQueueParams;
21
20
  };
22
21
 
23
22
  /**
@@ -26,25 +25,25 @@ export type RouteRegistrationOptions = {
26
25
  */
27
26
  export type RouteDefinitions = {
28
27
  api?: Partial<RouteRegistrationOptions>;
29
- syncStream?: Partial<RouteRegistrationOptions>;
28
+ sync_stream?: Partial<RouteRegistrationOptions>;
30
29
  };
31
30
 
32
31
  export type FastifyServerConfig = {
33
- system: system.CorePowerSyncSystem;
32
+ service_context: system.ServiceContext;
34
33
  routes?: RouteDefinitions;
35
34
  };
36
35
 
37
36
  export const DEFAULT_ROUTE_OPTIONS = {
38
37
  api: {
39
- routes: [...ADMIN_ROUTES, ...CHECKPOINT_ROUTES, ...DEV_ROUTES, ...SYNC_RULES_ROUTES],
40
- queueOptions: {
38
+ routes: [...ADMIN_ROUTES, ...CHECKPOINT_ROUTES, ...SYNC_RULES_ROUTES],
39
+ queue_options: {
41
40
  concurrency: 10,
42
41
  max_queue_depth: 20
43
42
  }
44
43
  },
45
- syncStream: {
44
+ sync_stream: {
46
45
  routes: [...SYNC_STREAM_ROUTES],
47
- queueOptions: {
46
+ queue_options: {
48
47
  concurrency: 200,
49
48
  max_queue_depth: 0
50
49
  }
@@ -56,7 +55,7 @@ export const DEFAULT_ROUTE_OPTIONS = {
56
55
  * concurrency queue limits or override routes.
57
56
  */
58
57
  export function configureFastifyServer(server: fastify.FastifyInstance, options: FastifyServerConfig) {
59
- const { system, routes = DEFAULT_ROUTE_OPTIONS } = options;
58
+ const { service_context, routes = DEFAULT_ROUTE_OPTIONS } = options;
60
59
  /**
61
60
  * Fastify creates an encapsulated context for each `.register` call.
62
61
  * Creating a separate context here to separate the concurrency limits for Admin APIs
@@ -69,7 +68,7 @@ export function configureFastifyServer(server: fastify.FastifyInstance, options:
69
68
  async () => {
70
69
  return {
71
70
  user_id: undefined,
72
- system: system
71
+ service_context
73
72
  };
74
73
  },
75
74
  routes.api?.routes ?? DEFAULT_ROUTE_OPTIONS.api.routes
@@ -77,7 +76,7 @@ export function configureFastifyServer(server: fastify.FastifyInstance, options:
77
76
  // Limit the active concurrent requests
78
77
  childContext.addHook(
79
78
  'onRequest',
80
- createRequestQueueHook(routes.api?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.api.queueOptions)
79
+ createRequestQueueHook(routes.api?.queue_options ?? DEFAULT_ROUTE_OPTIONS.api.queue_options)
81
80
  );
82
81
  });
83
82
 
@@ -88,15 +87,15 @@ export function configureFastifyServer(server: fastify.FastifyInstance, options:
88
87
  async () => {
89
88
  return {
90
89
  user_id: undefined,
91
- system: system
90
+ service_context
92
91
  };
93
92
  },
94
- routes.syncStream?.routes ?? DEFAULT_ROUTE_OPTIONS.syncStream.routes
93
+ routes.sync_stream?.routes ?? DEFAULT_ROUTE_OPTIONS.sync_stream.routes
95
94
  );
96
95
  // Limit the active concurrent requests
97
96
  childContext.addHook(
98
97
  'onRequest',
99
- createRequestQueueHook(routes.syncStream?.queueOptions ?? DEFAULT_ROUTE_OPTIONS.syncStream.queueOptions)
98
+ createRequestQueueHook(routes.sync_stream?.queue_options ?? DEFAULT_ROUTE_OPTIONS.sync_stream.queue_options)
100
99
  );
101
100
  });
102
101
  }
@@ -4,26 +4,26 @@ import * as http from 'http';
4
4
  import { errors, logger } from '@powersync/lib-services-framework';
5
5
  import { ReactiveSocketRouter, RSocketRequestMeta } from '@powersync/service-rsocket-router';
6
6
 
7
- import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
7
+ import { ServiceContext } from '../system/ServiceContext.js';
8
8
  import { generateContext, getTokenFromHeader } from './auth.js';
9
9
  import { syncStreamReactive } from './endpoints/socket-route.js';
10
10
  import { RSocketContextMeta, SocketRouteGenerator } from './router-socket.js';
11
11
  import { Context } from './router.js';
12
12
 
13
13
  export type RSockerRouterConfig = {
14
- system: CorePowerSyncSystem;
14
+ service_context: ServiceContext;
15
15
  server: http.Server;
16
- routeGenerators?: SocketRouteGenerator[];
16
+ route_generators?: SocketRouteGenerator[];
17
17
  };
18
18
 
19
19
  export const DEFAULT_SOCKET_ROUTES = [syncStreamReactive];
20
20
 
21
21
  export function configureRSocket(router: ReactiveSocketRouter<Context>, options: RSockerRouterConfig) {
22
- const { routeGenerators = DEFAULT_SOCKET_ROUTES, server, system } = options;
22
+ const { route_generators = DEFAULT_SOCKET_ROUTES, server, service_context } = options;
23
23
 
24
24
  router.applyWebSocketEndpoints(server, {
25
25
  contextProvider: async (data: Buffer) => {
26
- const { token } = RSocketContextMeta.decode(deserialize(data) as any);
26
+ const { token, user_agent } = RSocketContextMeta.decode(deserialize(data) as any);
27
27
 
28
28
  if (!token) {
29
29
  throw new errors.AuthorizationError('No token provided');
@@ -32,15 +32,16 @@ export function configureRSocket(router: ReactiveSocketRouter<Context>, options:
32
32
  try {
33
33
  const extracted_token = getTokenFromHeader(token);
34
34
  if (extracted_token != null) {
35
- const { context, errors: token_errors } = await generateContext(system, extracted_token);
35
+ const { context, errors: token_errors } = await generateContext(options.service_context, extracted_token);
36
36
  if (context?.token_payload == null) {
37
37
  throw new errors.AuthorizationError(token_errors ?? 'Authentication required');
38
38
  }
39
39
  return {
40
40
  token,
41
+ user_agent,
41
42
  ...context,
42
43
  token_errors: token_errors,
43
- system
44
+ service_context
44
45
  };
45
46
  } else {
46
47
  throw new errors.AuthorizationError('No token provided');
@@ -50,7 +51,7 @@ export function configureRSocket(router: ReactiveSocketRouter<Context>, options:
50
51
  throw ex;
51
52
  }
52
53
  },
53
- endpoints: routeGenerators.map((generator) => generator(router)),
54
+ endpoints: route_generators.map((generator) => generator(router)),
54
55
  metaDecoder: async (meta: Buffer) => {
55
56
  return RSocketRequestMeta.decode(deserialize(meta) as any);
56
57
  },
@@ -1,35 +1,11 @@
1
1
  import { errors, router, schema } from '@powersync/lib-services-framework';
2
- import { SqlSyncRules, SqliteValue, StaticSchema, isJsonValue, toSyncRulesValue } from '@powersync/service-sync-rules';
2
+ import { SqlSyncRules, StaticSchema } from '@powersync/service-sync-rules';
3
3
  import { internal_routes } from '@powersync/service-types';
4
4
 
5
5
  import * as api from '../../api/api-index.js';
6
- import * as util from '../../util/util-index.js';
7
-
8
- import { routeDefinition } from '../router.js';
9
- import { PersistedSyncRulesContent } from '../../storage/BucketStorage.js';
6
+ import * as storage from '../../storage/storage-index.js';
10
7
  import { authApi } from '../auth.js';
11
-
12
- const demoCredentials = routeDefinition({
13
- path: '/api/admin/v1/demo-credentials',
14
- method: router.HTTPMethod.POST,
15
- authorize: authApi,
16
- validator: schema.createTsCodecValidator(internal_routes.DemoCredentialsRequest, {
17
- allowAdditional: true
18
- }),
19
- handler: async (payload) => {
20
- const connection = payload.context.system.config.connection;
21
- if (connection == null || !connection.demo_database) {
22
- return internal_routes.DemoCredentialsResponse.encode({});
23
- }
24
-
25
- const uri = util.buildDemoPgUri(connection);
26
- return internal_routes.DemoCredentialsResponse.encode({
27
- credentials: {
28
- postgres_uri: uri
29
- }
30
- });
31
- }
32
- });
8
+ import { routeDefinition } from '../router.js';
33
9
 
34
10
  export const executeSql = routeDefinition({
35
11
  path: '/api/admin/v1/execute-sql',
@@ -37,47 +13,27 @@ export const executeSql = routeDefinition({
37
13
  authorize: authApi,
38
14
  validator: schema.createTsCodecValidator(internal_routes.ExecuteSqlRequest, { allowAdditional: true }),
39
15
  handler: async (payload) => {
40
- const connection = payload.context.system.config.connection;
41
- if (connection == null || !connection.debug_api) {
42
- return internal_routes.ExecuteSqlResponse.encode({
43
- results: {
44
- columns: [],
45
- rows: []
46
- },
47
- success: false,
48
- error: 'SQL querying is not enabled'
49
- });
50
- }
51
-
52
- const pool = payload.context.system.requirePgPool();
53
-
54
- const { query, args } = payload.params.sql;
16
+ const {
17
+ params: {
18
+ sql: { query, args }
19
+ }
20
+ } = payload;
55
21
 
56
- try {
57
- const result = await pool.query({
58
- statement: query,
59
- params: args.map(util.autoParameter)
60
- });
22
+ const apiHandler = payload.context.service_context.routerEngine!.getAPI();
61
23
 
62
- return internal_routes.ExecuteSqlResponse.encode({
63
- success: true,
64
- results: {
65
- columns: result.columns.map((c) => c.name),
66
- rows: result.rows.map((row) => {
67
- return row.map((value) => mapColumnValue(toSyncRulesValue(value)));
68
- })
69
- }
70
- });
71
- } catch (e) {
24
+ const sourceConfig = await apiHandler.getSourceConfig();
25
+ if (!sourceConfig.debug_api) {
72
26
  return internal_routes.ExecuteSqlResponse.encode({
73
27
  results: {
74
28
  columns: [],
75
29
  rows: []
76
30
  },
77
31
  success: false,
78
- error: e.message
32
+ error: 'SQL querying is not enabled'
79
33
  });
80
34
  }
35
+
36
+ return internal_routes.ExecuteSqlResponse.encode(await apiHandler.executeQuery(query, args));
81
37
  }
82
38
  });
83
39
 
@@ -87,34 +43,45 @@ export const diagnostics = routeDefinition({
87
43
  authorize: authApi,
88
44
  validator: schema.createTsCodecValidator(internal_routes.DiagnosticsRequest, { allowAdditional: true }),
89
45
  handler: async (payload) => {
46
+ const { context } = payload;
47
+ const { service_context } = context;
90
48
  const include_content = payload.params.sync_rules_content ?? false;
91
- const system = payload.context.system;
92
49
 
93
- const status = await api.getConnectionStatus(system);
94
- if (status == null) {
50
+ const apiHandler = service_context.routerEngine!.getAPI();
51
+
52
+ const status = await apiHandler.getConnectionStatus();
53
+ if (!status) {
95
54
  return internal_routes.DiagnosticsResponse.encode({
96
55
  connections: []
97
56
  });
98
57
  }
99
58
 
100
- const { storage } = system;
101
- const active = await storage.getActiveSyncRulesContent();
102
- const next = await storage.getNextSyncRulesContent();
59
+ const {
60
+ storageEngine: { activeBucketStorage }
61
+ } = service_context;
62
+ const active = await activeBucketStorage.getActiveSyncRulesContent();
63
+ const next = await activeBucketStorage.getNextSyncRulesContent();
103
64
 
104
- const active_status = await api.getSyncRulesStatus(active, system, {
65
+ const active_status = await api.getSyncRulesStatus(activeBucketStorage, apiHandler, active, {
105
66
  include_content,
106
67
  check_connection: status.connected,
107
68
  live_status: true
108
69
  });
109
70
 
110
- const next_status = await api.getSyncRulesStatus(next, system, {
71
+ const next_status = await api.getSyncRulesStatus(activeBucketStorage, apiHandler, next, {
111
72
  include_content,
112
73
  check_connection: status.connected,
113
74
  live_status: true
114
75
  });
115
76
 
116
77
  return internal_routes.DiagnosticsResponse.encode({
117
- connections: [status],
78
+ connections: [
79
+ {
80
+ ...status,
81
+ // TODO update this in future
82
+ postgres_uri: status.uri
83
+ }
84
+ ],
118
85
  active_sync_rules: active_status,
119
86
  deploying_sync_rules: next_status
120
87
  });
@@ -127,9 +94,9 @@ export const getSchema = routeDefinition({
127
94
  authorize: authApi,
128
95
  validator: schema.createTsCodecValidator(internal_routes.GetSchemaRequest, { allowAdditional: true }),
129
96
  handler: async (payload) => {
130
- const system = payload.context.system;
97
+ const apiHandler = payload.context.service_context.routerEngine!.getAPI();
131
98
 
132
- return internal_routes.GetSchemaResponse.encode(await api.getConnectionsSchema(system));
99
+ return internal_routes.GetSchemaResponse.encode(await api.getConnectionsSchema(apiHandler));
133
100
  }
134
101
  });
135
102
 
@@ -139,15 +106,19 @@ export const reprocess = routeDefinition({
139
106
  authorize: authApi,
140
107
  validator: schema.createTsCodecValidator(internal_routes.ReprocessRequest, { allowAdditional: true }),
141
108
  handler: async (payload) => {
142
- const system = payload.context.system;
143
-
144
- const storage = system.storage;
145
- const next = await storage.getNextSyncRules();
109
+ const {
110
+ context: { service_context }
111
+ } = payload;
112
+ const {
113
+ storageEngine: { activeBucketStorage }
114
+ } = service_context;
115
+ const apiHandler = service_context.routerEngine!.getAPI();
116
+ const next = await activeBucketStorage.getNextSyncRules(apiHandler.getParseSyncRulesOptions());
146
117
  if (next != null) {
147
118
  throw new Error(`Busy processing sync rules - cannot reprocess`);
148
119
  }
149
120
 
150
- const active = await storage.getActiveSyncRules();
121
+ const active = await activeBucketStorage.getActiveSyncRules(apiHandler.getParseSyncRulesOptions());
151
122
  if (active == null) {
152
123
  throw new errors.JourneyError({
153
124
  status: 422,
@@ -156,15 +127,18 @@ export const reprocess = routeDefinition({
156
127
  });
157
128
  }
158
129
 
159
- const new_rules = await storage.updateSyncRules({
130
+ const new_rules = await activeBucketStorage.updateSyncRules({
160
131
  content: active.sync_rules.content
161
132
  });
162
133
 
134
+ const baseConfig = await apiHandler.getSourceConfig();
135
+
163
136
  return internal_routes.ReprocessResponse.encode({
164
137
  connections: [
165
138
  {
166
- tag: system.config.connection!.tag,
167
- id: system.config.connection!.id,
139
+ // Previously the connection was asserted with `!`
140
+ tag: baseConfig!.tag!,
141
+ id: baseConfig!.id,
168
142
  slot_name: new_rules.slot_name
169
143
  }
170
144
  ]
@@ -178,14 +152,16 @@ export const validate = routeDefinition({
178
152
  authorize: authApi,
179
153
  validator: schema.createTsCodecValidator(internal_routes.ValidateRequest, { allowAdditional: true }),
180
154
  handler: async (payload) => {
181
- const system = payload.context.system;
182
-
155
+ const {
156
+ context: { service_context }
157
+ } = payload;
183
158
  const content = payload.params.sync_rules;
159
+ const apiHandler = service_context.routerEngine!.getAPI();
184
160
 
185
- const schemaData = await api.getConnectionsSchema(system);
161
+ const schemaData = await api.getConnectionsSchema(apiHandler);
186
162
  const schema = new StaticSchema(schemaData.connections);
187
163
 
188
- const sync_rules: PersistedSyncRulesContent = {
164
+ const sync_rules: storage.PersistedSyncRulesContent = {
189
165
  // Dummy values
190
166
  id: 0,
191
167
  slot_name: '',
@@ -193,7 +169,10 @@ export const validate = routeDefinition({
193
169
  parsed() {
194
170
  return {
195
171
  ...this,
196
- sync_rules: SqlSyncRules.fromYaml(content, { throwOnError: false, schema })
172
+ sync_rules: SqlSyncRules.fromYaml(content, {
173
+ ...apiHandler.getParseSyncRulesOptions(),
174
+ schema
175
+ })
197
176
  };
198
177
  },
199
178
  sync_rules_content: content,
@@ -202,19 +181,24 @@ export const validate = routeDefinition({
202
181
  }
203
182
  };
204
183
 
205
- const connectionStatus = await api.getConnectionStatus(system);
206
- if (connectionStatus == null) {
184
+ const connectionStatus = await apiHandler.getConnectionStatus();
185
+ if (!connectionStatus) {
207
186
  return internal_routes.ValidateResponse.encode({
208
187
  errors: [{ level: 'fatal', message: 'No connection configured' }],
209
188
  connections: []
210
189
  });
211
190
  }
212
191
 
213
- const status = (await api.getSyncRulesStatus(sync_rules, system, {
214
- include_content: false,
215
- check_connection: connectionStatus?.connected,
216
- live_status: false
217
- }))!;
192
+ const status = (await api.getSyncRulesStatus(
193
+ service_context.storageEngine.activeBucketStorage,
194
+ apiHandler,
195
+ sync_rules,
196
+ {
197
+ include_content: false,
198
+ check_connection: connectionStatus.connected,
199
+ live_status: false
200
+ }
201
+ ))!;
218
202
 
219
203
  if (connectionStatus == null) {
220
204
  status.errors.push({ level: 'fatal', message: 'No connection configured' });
@@ -224,14 +208,4 @@ export const validate = routeDefinition({
224
208
  }
225
209
  });
226
210
 
227
- function mapColumnValue(value: SqliteValue) {
228
- if (typeof value == 'bigint') {
229
- return Number(value);
230
- } else if (isJsonValue(value)) {
231
- return value;
232
- } else {
233
- return null;
234
- }
235
- }
236
-
237
- export const ADMIN_ROUTES = [demoCredentials, executeSql, diagnostics, getSchema, reprocess, validate];
211
+ export const ADMIN_ROUTES = [executeSql, diagnostics, getSchema, reprocess, validate];
@@ -1,11 +1,13 @@
1
1
  import * as t from 'ts-codec';
2
- import { router, schema } from '@powersync/lib-services-framework';
2
+ import { logger, router, schema } from '@powersync/lib-services-framework';
3
3
 
4
4
  import * as util from '../../util/util-index.js';
5
5
  import { authUser } from '../auth.js';
6
6
  import { routeDefinition } from '../router.js';
7
7
 
8
- const WriteCheckpointRequest = t.object({});
8
+ const WriteCheckpointRequest = t.object({
9
+ client_id: t.string.optional()
10
+ });
9
11
 
10
12
  export const writeCheckpoint = routeDefinition({
11
13
  path: '/write-checkpoint.json',
@@ -13,13 +15,33 @@ export const writeCheckpoint = routeDefinition({
13
15
  authorize: authUser,
14
16
  validator: schema.createTsCodecValidator(WriteCheckpointRequest, { allowAdditional: true }),
15
17
  handler: async (payload) => {
16
- const system = payload.context.system;
17
- const storage = system.storage;
18
+ const {
19
+ context: { service_context }
20
+ } = payload;
21
+ const apiHandler = service_context.routerEngine!.getAPI();
18
22
 
19
- const checkpoint = await util.getClientCheckpoint(system.requirePgPool(), storage);
20
- return {
21
- checkpoint
22
- };
23
+ // This old API needs a persisted checkpoint id.
24
+ // Since we don't use LSNs anymore, the only way to get that is to wait.
25
+ const start = Date.now();
26
+
27
+ const head = await apiHandler.getReplicationHead();
28
+
29
+ const timeout = 50_000;
30
+
31
+ logger.info(`Waiting for LSN checkpoint: ${head}`);
32
+ while (Date.now() - start < timeout) {
33
+ const cp = await service_context.storageEngine.activeBucketStorage.getActiveCheckpoint();
34
+ if (!cp.hasSyncRules()) {
35
+ throw new Error('No sync rules available');
36
+ }
37
+ if (cp.lsn && cp.lsn >= head) {
38
+ logger.info(`Got write checkpoint: ${head} : ${cp.checkpoint}`);
39
+ return { checkpoint: cp.checkpoint };
40
+ }
41
+
42
+ await new Promise((resolve) => setTimeout(resolve, 30));
43
+ }
44
+ throw new Error('Timeout while waiting for checkpoint');
23
45
  }
24
46
  });
25
47
 
@@ -29,11 +51,23 @@ export const writeCheckpoint2 = routeDefinition({
29
51
  authorize: authUser,
30
52
  validator: schema.createTsCodecValidator(WriteCheckpointRequest, { allowAdditional: true }),
31
53
  handler: async (payload) => {
32
- const { user_id, system } = payload.context;
33
- const storage = system.storage;
34
- const write_checkpoint = await util.createWriteCheckpoint(system.requirePgPool(), storage, user_id!);
54
+ const { user_id, service_context } = payload.context;
55
+
56
+ const apiHandler = service_context.routerEngine!.getAPI();
57
+
58
+ const client_id = payload.params.client_id;
59
+ const full_user_id = util.checkpointUserId(user_id, client_id);
60
+
61
+ const currentCheckpoint = await apiHandler.getReplicationHead();
62
+ const {
63
+ storageEngine: { activeBucketStorage }
64
+ } = service_context;
65
+
66
+ const writeCheckpoint = await activeBucketStorage.createWriteCheckpoint(full_user_id, { '1': currentCheckpoint });
67
+ logger.info(`Write checkpoint 2: ${JSON.stringify({ currentCheckpoint, id: String(full_user_id) })}`);
68
+
35
69
  return {
36
- write_checkpoint: String(write_checkpoint)
70
+ write_checkpoint: String(writeCheckpoint)
37
71
  };
38
72
  }
39
73
  });
@@ -1,6 +1,5 @@
1
1
  export * from './admin.js';
2
2
  export * from './checkpointing.js';
3
- export * from './dev.js';
4
3
  export * from './socket-route.js';
5
4
  export * from './sync-rules.js';
6
5
  export * from './sync-stream.js';
@@ -11,10 +11,28 @@ import { SyncRoutes } from './sync-stream.js';
11
11
  export const syncStreamReactive: SocketRouteGenerator = (router) =>
12
12
  router.reactiveStream<util.StreamingSyncRequest, any>(SyncRoutes.STREAM, {
13
13
  validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
14
- handler: async ({ context, params, responder, observer, initialN }) => {
15
- const { system } = context;
14
+ handler: async ({ context, params, responder, observer, initialN, signal: upstreamSignal }) => {
15
+ const { service_context } = context;
16
+ const { routerEngine } = service_context;
16
17
 
17
- if (system.closed) {
18
+ // Create our own controller that we can abort directly
19
+ const controller = new AbortController();
20
+ upstreamSignal.addEventListener('abort', () => {
21
+ controller.abort();
22
+ });
23
+ if (upstreamSignal.aborted) {
24
+ controller.abort();
25
+ }
26
+ const signal = controller.signal;
27
+
28
+ let requestedN = initialN;
29
+ const disposer = observer.registerListener({
30
+ request(n) {
31
+ requestedN += n;
32
+ }
33
+ });
34
+
35
+ if (routerEngine!.closed) {
18
36
  responder.onError(
19
37
  new errors.JourneyError({
20
38
  status: 503,
@@ -26,13 +44,13 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
26
44
  return;
27
45
  }
28
46
 
29
- const controller = new AbortController();
30
-
31
47
  const syncParams = new RequestParameters(context.token_payload!, params.parameters ?? {});
32
48
 
33
- const storage = system.storage;
49
+ const {
50
+ storageEngine: { activeBucketStorage }
51
+ } = service_context;
34
52
  // Sanity check before we start the stream
35
- const cp = await storage.getActiveCheckpoint();
53
+ const cp = await activeBucketStorage.getActiveCheckpoint();
36
54
  if (!cp.hasSyncRules()) {
37
55
  responder.onError(
38
56
  new errors.JourneyError({
@@ -45,25 +63,16 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
45
63
  return;
46
64
  }
47
65
 
48
- let requestedN = initialN;
49
- const disposer = observer.registerListener({
50
- request(n) {
51
- requestedN += n;
52
- },
53
- cancel: () => {
54
- controller.abort();
55
- }
56
- });
57
-
58
- const removeStopHandler = system.addStopHandler(() => {
59
- observer.triggerCancel();
66
+ const removeStopHandler = routerEngine!.addStopHandler(() => {
67
+ controller.abort();
60
68
  });
61
69
 
62
70
  Metrics.getInstance().concurrent_connections.add(1);
63
71
  const tracker = new sync.RequestTracker();
64
72
  try {
65
73
  for await (const data of sync.streamResponse({
66
- storage,
74
+ storage: activeBucketStorage,
75
+ parseOptions: routerEngine!.getAPI().getParseSyncRulesOptions(),
67
76
  params: {
68
77
  ...params,
69
78
  binary_data: true // always true for web sockets
@@ -75,8 +84,11 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
75
84
  keep_alive: false
76
85
  },
77
86
  tracker,
78
- signal: controller.signal
87
+ signal
79
88
  })) {
89
+ if (signal.aborted) {
90
+ break;
91
+ }
80
92
  if (data == null) {
81
93
  // Empty value just to flush iterator memory
82
94
  continue;
@@ -93,7 +105,7 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
93
105
  tracker.addDataSynced(serialized.length);
94
106
  }
95
107
 
96
- if (requestedN <= 0) {
108
+ if (requestedN <= 0 && !signal.aborted) {
97
109
  await new Promise<void>((resolve) => {
98
110
  const l = observer.registerListener({
99
111
  request() {
@@ -101,14 +113,17 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
101
113
  // Management of updating the total requested items is done above
102
114
  resolve();
103
115
  l();
116
+ signal.removeEventListener('abort', onAbort);
104
117
  }
105
- },
106
- cancel: () => {
107
- // Don't wait here if the request is cancelled
108
- resolve();
109
- l();
110
118
  }
111
119
  });
120
+ const onAbort = () => {
121
+ // Don't wait here if the request is cancelled
122
+ resolve();
123
+ l();
124
+ signal.removeEventListener('abort', onAbort);
125
+ };
126
+ signal.addEventListener('abort', onAbort);
112
127
  });
113
128
  }
114
129
  }
@@ -124,6 +139,8 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
124
139
  disposer();
125
140
  logger.info(`Sync stream complete`, {
126
141
  user_id: syncParams.user_id,
142
+ client_id: params.client_id,
143
+ user_agent: context.user_agent,
127
144
  operations_synced: tracker.operationsSynced,
128
145
  data_synced_bytes: tracker.dataSyncedBytes
129
146
  });