@powersync/service-core 0.0.0-dev-20240725112650 → 0.0.0-dev-20240918082156
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +80 -2
- package/dist/api/RouteAPI.d.ts +68 -0
- package/dist/api/RouteAPI.js +2 -0
- package/dist/api/RouteAPI.js.map +1 -0
- package/dist/api/api-index.d.ts +1 -0
- package/dist/api/api-index.js +1 -0
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/diagnostics.d.ts +4 -4
- package/dist/api/diagnostics.js +11 -65
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/api/schema.d.ts +3 -5
- package/dist/api/schema.js +9 -79
- package/dist/api/schema.js.map +1 -1
- package/dist/auth/KeyStore.d.ts +7 -4
- package/dist/auth/KeyStore.js +1 -1
- package/dist/auth/KeyStore.js.map +1 -1
- package/dist/auth/auth-index.d.ts +0 -1
- package/dist/auth/auth-index.js +0 -1
- package/dist/auth/auth-index.js.map +1 -1
- package/dist/entry/cli-entry.js +3 -2
- package/dist/entry/cli-entry.js.map +1 -1
- package/dist/entry/commands/compact-action.js +12 -8
- package/dist/entry/commands/compact-action.js.map +1 -1
- package/dist/entry/commands/migrate-action.js +4 -5
- package/dist/entry/commands/migrate-action.js.map +1 -1
- package/dist/entry/commands/teardown-action.js +2 -2
- package/dist/entry/commands/teardown-action.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/Metrics.d.ts +2 -2
- package/dist/metrics/Metrics.js +5 -13
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
- package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
- package/dist/migrations/migrations.d.ts +8 -0
- package/dist/migrations/migrations.js +19 -7
- package/dist/migrations/migrations.js.map +1 -1
- package/dist/modules/AbstractModule.d.ts +26 -0
- package/dist/modules/AbstractModule.js +11 -0
- package/dist/modules/AbstractModule.js.map +1 -0
- package/dist/modules/ModuleManager.d.ts +11 -0
- package/dist/modules/ModuleManager.js +32 -0
- package/dist/modules/ModuleManager.js.map +1 -0
- package/dist/modules/modules-index.d.ts +2 -0
- package/dist/modules/modules-index.js +3 -0
- package/dist/modules/modules-index.js.map +1 -0
- package/dist/replication/AbstractReplicationJob.d.ts +38 -0
- package/dist/replication/AbstractReplicationJob.js +51 -0
- package/dist/replication/AbstractReplicationJob.js.map +1 -0
- package/dist/replication/AbstractReplicator.d.ts +53 -0
- package/dist/replication/AbstractReplicator.js +187 -0
- package/dist/replication/AbstractReplicator.js.map +1 -0
- package/dist/replication/ErrorRateLimiter.d.ts +0 -9
- package/dist/replication/ErrorRateLimiter.js +1 -42
- package/dist/replication/ErrorRateLimiter.js.map +1 -1
- package/dist/replication/ReplicationEngine.d.ts +18 -0
- package/dist/replication/ReplicationEngine.js +41 -0
- package/dist/replication/ReplicationEngine.js.map +1 -0
- package/dist/replication/ReplicationModule.d.ts +39 -0
- package/dist/replication/ReplicationModule.js +65 -0
- package/dist/replication/ReplicationModule.js.map +1 -0
- package/dist/replication/replication-index.d.ts +4 -6
- package/dist/replication/replication-index.js +4 -6
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/routes/RouterEngine.d.ts +42 -0
- package/dist/routes/RouterEngine.js +80 -0
- package/dist/routes/RouterEngine.js.map +1 -0
- package/dist/routes/auth.d.ts +2 -2
- package/dist/routes/auth.js +11 -11
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +30 -176
- package/dist/routes/configure-fastify.js +10 -11
- package/dist/routes/configure-fastify.js.map +1 -1
- package/dist/routes/configure-rsocket.d.ts +3 -3
- package/dist/routes/configure-rsocket.js +6 -5
- package/dist/routes/configure-rsocket.js.map +1 -1
- package/dist/routes/endpoints/admin.d.ts +0 -34
- package/dist/routes/endpoints/admin.js +48 -89
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.d.ts +56 -16
- package/dist/routes/endpoints/checkpointing.js +33 -12
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/routes/endpoints/route-endpoints-index.d.ts +0 -1
- package/dist/routes/endpoints/route-endpoints-index.js +0 -1
- package/dist/routes/endpoints/route-endpoints-index.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js +40 -25
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.d.ts +1 -1
- package/dist/routes/endpoints/sync-rules.js +32 -23
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +10 -0
- package/dist/routes/endpoints/sync-stream.js +13 -8
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/routes/router-socket.d.ts +1 -0
- package/dist/routes/router-socket.js +2 -1
- package/dist/routes/router-socket.js.map +1 -1
- package/dist/routes/router.d.ts +6 -2
- package/dist/routes/router.js.map +1 -1
- package/dist/routes/routes-index.d.ts +1 -0
- package/dist/routes/routes-index.js +1 -0
- package/dist/routes/routes-index.js.map +1 -1
- package/dist/runner/teardown.js +47 -76
- package/dist/runner/teardown.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +30 -19
- package/dist/storage/BucketStorage.js +0 -10
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +4 -4
- package/dist/storage/MongoBucketStorage.js +19 -24
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/SourceEntity.d.ts +20 -0
- package/dist/storage/SourceEntity.js +2 -0
- package/dist/storage/SourceEntity.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +4 -5
- package/dist/storage/SourceTable.js +3 -4
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/StorageEngine.d.ts +24 -0
- package/dist/storage/StorageEngine.js +43 -0
- package/dist/storage/StorageEngine.js.map +1 -0
- package/dist/storage/StorageProvider.d.ts +21 -0
- package/dist/storage/StorageProvider.js +2 -0
- package/dist/storage/StorageProvider.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +1 -1
- package/dist/storage/mongo/MongoBucketBatch.js +6 -7
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
- package/dist/storage/mongo/MongoCompactor.js +2 -1
- package/dist/storage/mongo/MongoCompactor.js.map +1 -1
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
- package/dist/storage/mongo/MongoStorageProvider.js +26 -0
- package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +7 -6
- package/dist/storage/mongo/MongoSyncBucketStorage.js +24 -15
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/mongo/OperationBatch.d.ts +7 -3
- package/dist/storage/mongo/OperationBatch.js +16 -7
- package/dist/storage/mongo/OperationBatch.js.map +1 -1
- package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
- package/dist/storage/mongo/PersistedBatch.js +2 -2
- package/dist/storage/mongo/PersistedBatch.js.map +1 -1
- package/dist/storage/mongo/models.d.ts +13 -4
- package/dist/storage/mongo/models.js.map +1 -1
- package/dist/storage/mongo/util.d.ts +12 -1
- package/dist/storage/mongo/util.js +50 -2
- package/dist/storage/mongo/util.js.map +1 -1
- package/dist/storage/storage-index.d.ts +5 -2
- package/dist/storage/storage-index.js +5 -2
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -1
- package/dist/sync/sync.js +36 -10
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +37 -0
- package/dist/system/ServiceContext.js +48 -0
- package/dist/system/ServiceContext.js.map +1 -0
- package/dist/system/system-index.d.ts +1 -1
- package/dist/system/system-index.js +1 -1
- package/dist/system/system-index.js.map +1 -1
- package/dist/util/config/compound-config-collector.d.ts +9 -2
- package/dist/util/config/compound-config-collector.js +14 -23
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
- package/dist/util/config/types.d.ts +6 -4
- package/dist/util/config/types.js.map +1 -1
- package/dist/util/config.d.ts +3 -4
- package/dist/util/config.js +5 -20
- package/dist/util/config.js.map +1 -1
- package/dist/util/protocol-types.d.ts +4 -0
- package/dist/util/protocol-types.js +5 -1
- package/dist/util/protocol-types.js.map +1 -1
- package/dist/util/util-index.d.ts +3 -6
- package/dist/util/util-index.js +3 -6
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +10 -6
- package/dist/util/utils.js +45 -25
- package/dist/util/utils.js.map +1 -1
- package/package.json +5 -7
- package/src/api/RouteAPI.ts +78 -0
- package/src/api/api-index.ts +1 -0
- package/src/api/diagnostics.ts +16 -71
- package/src/api/schema.ts +13 -89
- package/src/auth/KeyStore.ts +9 -6
- package/src/auth/auth-index.ts +0 -1
- package/src/entry/cli-entry.ts +3 -2
- package/src/entry/commands/compact-action.ts +12 -9
- package/src/entry/commands/migrate-action.ts +5 -8
- package/src/entry/commands/teardown-action.ts +2 -2
- package/src/index.ts +5 -2
- package/src/metrics/Metrics.ts +6 -16
- package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
- package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
- package/src/migrations/migrations.ts +24 -8
- package/src/modules/AbstractModule.ts +37 -0
- package/src/modules/ModuleManager.ts +34 -0
- package/src/modules/modules-index.ts +2 -0
- package/src/replication/AbstractReplicationJob.ts +79 -0
- package/src/replication/AbstractReplicator.ts +227 -0
- package/src/replication/ErrorRateLimiter.ts +0 -44
- package/src/replication/ReplicationEngine.ts +43 -0
- package/src/replication/ReplicationModule.ts +101 -0
- package/src/replication/replication-index.ts +4 -6
- package/src/routes/RouterEngine.ts +120 -0
- package/src/routes/auth.ts +21 -12
- package/src/routes/configure-fastify.ts +13 -14
- package/src/routes/configure-rsocket.ts +9 -8
- package/src/routes/endpoints/admin.ts +74 -100
- package/src/routes/endpoints/checkpointing.ts +46 -12
- package/src/routes/endpoints/route-endpoints-index.ts +0 -1
- package/src/routes/endpoints/socket-route.ts +44 -27
- package/src/routes/endpoints/sync-rules.ts +41 -25
- package/src/routes/endpoints/sync-stream.ts +13 -8
- package/src/routes/router-socket.ts +2 -1
- package/src/routes/router.ts +6 -3
- package/src/routes/routes-index.ts +1 -0
- package/src/runner/teardown.ts +50 -88
- package/src/storage/BucketStorage.ts +38 -25
- package/src/storage/MongoBucketStorage.ts +23 -26
- package/src/storage/SourceEntity.ts +22 -0
- package/src/storage/SourceTable.ts +4 -6
- package/src/storage/StorageEngine.ts +55 -0
- package/src/storage/StorageProvider.ts +27 -0
- package/src/storage/mongo/MongoBucketBatch.ts +8 -8
- package/src/storage/mongo/MongoCompactor.ts +2 -1
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +3 -3
- package/src/storage/mongo/MongoStorageProvider.ts +31 -0
- package/src/storage/mongo/MongoSyncBucketStorage.ts +39 -20
- package/src/storage/mongo/MongoSyncRulesLock.ts +1 -1
- package/src/storage/mongo/OperationBatch.ts +18 -11
- package/src/storage/mongo/PersistedBatch.ts +6 -5
- package/src/storage/mongo/models.ts +13 -4
- package/src/storage/mongo/util.ts +49 -4
- package/src/storage/storage-index.ts +5 -2
- package/src/sync/sync.ts +46 -11
- package/src/sync/util.ts +0 -1
- package/src/system/ServiceContext.ts +68 -0
- package/src/system/system-index.ts +1 -1
- package/src/util/config/compound-config-collector.ts +30 -31
- package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
- package/src/util/config/types.ts +6 -5
- package/src/util/config.ts +6 -23
- package/src/util/protocol-types.ts +6 -1
- package/src/util/util-index.ts +3 -6
- package/src/util/utils.ts +55 -39
- package/test/src/__snapshots__/sync.test.ts.snap +7 -7
- package/test/src/auth.test.ts +7 -7
- package/test/src/broadcast_iterable.test.ts +1 -1
- package/test/src/checksum_cache.test.ts +3 -3
- package/test/src/compacting.test.ts +26 -17
- package/test/src/data_storage.test.ts +258 -146
- package/test/src/env.ts +1 -3
- package/test/src/merge_iterable.test.ts +1 -6
- package/test/src/setup.ts +1 -1
- package/test/src/stream_utils.ts +42 -0
- package/test/src/sync.test.ts +52 -31
- package/test/src/util.ts +48 -51
- package/test/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
- package/dist/auth/SupabaseKeyCollector.js +0 -61
- package/dist/auth/SupabaseKeyCollector.js.map +0 -1
- package/dist/replication/PgRelation.d.ts +0 -16
- package/dist/replication/PgRelation.js +0 -26
- package/dist/replication/PgRelation.js.map +0 -1
- package/dist/replication/WalConnection.d.ts +0 -34
- package/dist/replication/WalConnection.js +0 -190
- package/dist/replication/WalConnection.js.map +0 -1
- package/dist/replication/WalStream.d.ts +0 -57
- package/dist/replication/WalStream.js +0 -515
- package/dist/replication/WalStream.js.map +0 -1
- package/dist/replication/WalStreamManager.d.ts +0 -30
- package/dist/replication/WalStreamManager.js +0 -198
- package/dist/replication/WalStreamManager.js.map +0 -1
- package/dist/replication/WalStreamRunner.d.ts +0 -38
- package/dist/replication/WalStreamRunner.js +0 -155
- package/dist/replication/WalStreamRunner.js.map +0 -1
- package/dist/replication/util.d.ts +0 -9
- package/dist/replication/util.js +0 -62
- package/dist/replication/util.js.map +0 -1
- package/dist/routes/endpoints/dev.d.ts +0 -312
- package/dist/routes/endpoints/dev.js +0 -172
- package/dist/routes/endpoints/dev.js.map +0 -1
- package/dist/system/CorePowerSyncSystem.d.ts +0 -23
- package/dist/system/CorePowerSyncSystem.js +0 -52
- package/dist/system/CorePowerSyncSystem.js.map +0 -1
- package/dist/util/PgManager.d.ts +0 -24
- package/dist/util/PgManager.js +0 -55
- package/dist/util/PgManager.js.map +0 -1
- package/dist/util/migration_lib.d.ts +0 -11
- package/dist/util/migration_lib.js +0 -64
- package/dist/util/migration_lib.js.map +0 -1
- package/dist/util/pgwire_utils.d.ts +0 -24
- package/dist/util/pgwire_utils.js +0 -117
- package/dist/util/pgwire_utils.js.map +0 -1
- package/dist/util/populate_test_data.d.ts +0 -8
- package/dist/util/populate_test_data.js +0 -65
- package/dist/util/populate_test_data.js.map +0 -1
- package/src/auth/SupabaseKeyCollector.ts +0 -67
- package/src/replication/PgRelation.ts +0 -42
- package/src/replication/WalConnection.ts +0 -227
- package/src/replication/WalStream.ts +0 -624
- package/src/replication/WalStreamManager.ts +0 -213
- package/src/replication/WalStreamRunner.ts +0 -180
- package/src/replication/util.ts +0 -76
- package/src/routes/endpoints/dev.ts +0 -199
- package/src/system/CorePowerSyncSystem.ts +0 -64
- package/src/util/PgManager.ts +0 -64
- package/src/util/migration_lib.ts +0 -79
- package/src/util/pgwire_utils.ts +0 -139
- package/src/util/populate_test_data.ts +0 -78
- package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
- package/test/src/large_batch.test.ts +0 -194
- package/test/src/pg_test.test.ts +0 -450
- package/test/src/schema_changes.test.ts +0 -545
- package/test/src/slow_tests.test.ts +0 -338
- package/test/src/validation.test.ts +0 -63
- package/test/src/wal_stream.test.ts +0 -319
- 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
|
-
|
|
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
|
-
|
|
28
|
+
sync_stream?: Partial<RouteRegistrationOptions>;
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
export type FastifyServerConfig = {
|
|
33
|
-
|
|
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, ...
|
|
40
|
-
|
|
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
|
-
|
|
44
|
+
sync_stream: {
|
|
46
45
|
routes: [...SYNC_STREAM_ROUTES],
|
|
47
|
-
|
|
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 {
|
|
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
|
-
|
|
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?.
|
|
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
|
-
|
|
90
|
+
service_context
|
|
92
91
|
};
|
|
93
92
|
},
|
|
94
|
-
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.
|
|
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 {
|
|
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
|
-
|
|
14
|
+
service_context: ServiceContext;
|
|
15
15
|
server: http.Server;
|
|
16
|
-
|
|
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 {
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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,
|
|
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
|
|
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
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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:
|
|
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
|
|
94
|
-
|
|
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 {
|
|
101
|
-
|
|
102
|
-
|
|
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(
|
|
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(
|
|
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: [
|
|
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
|
|
97
|
+
const apiHandler = payload.context.service_context.routerEngine!.getAPI();
|
|
131
98
|
|
|
132
|
-
return internal_routes.GetSchemaResponse.encode(await api.getConnectionsSchema(
|
|
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
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
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
|
|
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
|
|
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
|
-
|
|
167
|
-
|
|
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
|
|
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(
|
|
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, {
|
|
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
|
|
206
|
-
if (connectionStatus
|
|
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(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
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
|
|
17
|
-
|
|
18
|
+
const {
|
|
19
|
+
context: { service_context }
|
|
20
|
+
} = payload;
|
|
21
|
+
const apiHandler = service_context.routerEngine!.getAPI();
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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,
|
|
33
|
-
|
|
34
|
-
const
|
|
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(
|
|
70
|
+
write_checkpoint: String(writeCheckpoint)
|
|
37
71
|
};
|
|
38
72
|
}
|
|
39
73
|
});
|
|
@@ -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 {
|
|
14
|
+
handler: async ({ context, params, responder, observer, initialN, signal: upstreamSignal }) => {
|
|
15
|
+
const { service_context } = context;
|
|
16
|
+
const { routerEngine } = service_context;
|
|
16
17
|
|
|
17
|
-
|
|
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
|
|
49
|
+
const {
|
|
50
|
+
storageEngine: { activeBucketStorage }
|
|
51
|
+
} = service_context;
|
|
34
52
|
// Sanity check before we start the stream
|
|
35
|
-
const cp = await
|
|
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
|
-
|
|
49
|
-
|
|
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
|
|
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
|
});
|