@powersync/service-core 0.0.0-dev-20240620165206
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/.probes/.gitkeep +0 -0
- package/CHANGELOG.md +82 -0
- package/LICENSE +67 -0
- package/README.md +3 -0
- package/dist/api/api-index.d.ts +2 -0
- package/dist/api/api-index.js +3 -0
- package/dist/api/api-index.js.map +1 -0
- package/dist/api/diagnostics.d.ts +21 -0
- package/dist/api/diagnostics.js +183 -0
- package/dist/api/diagnostics.js.map +1 -0
- package/dist/api/schema.d.ts +5 -0
- package/dist/api/schema.js +88 -0
- package/dist/api/schema.js.map +1 -0
- package/dist/auth/CachedKeyCollector.d.ts +46 -0
- package/dist/auth/CachedKeyCollector.js +116 -0
- package/dist/auth/CachedKeyCollector.js.map +1 -0
- package/dist/auth/CompoundKeyCollector.d.ts +8 -0
- package/dist/auth/CompoundKeyCollector.js +23 -0
- package/dist/auth/CompoundKeyCollector.js.map +1 -0
- package/dist/auth/JwtPayload.d.ts +10 -0
- package/dist/auth/JwtPayload.js +2 -0
- package/dist/auth/JwtPayload.js.map +1 -0
- package/dist/auth/KeyCollector.d.ts +24 -0
- package/dist/auth/KeyCollector.js +2 -0
- package/dist/auth/KeyCollector.js.map +1 -0
- package/dist/auth/KeySpec.d.ts +26 -0
- package/dist/auth/KeySpec.js +49 -0
- package/dist/auth/KeySpec.js.map +1 -0
- package/dist/auth/KeyStore.d.ts +39 -0
- package/dist/auth/KeyStore.js +131 -0
- package/dist/auth/KeyStore.js.map +1 -0
- package/dist/auth/LeakyBucket.d.ts +39 -0
- package/dist/auth/LeakyBucket.js +57 -0
- package/dist/auth/LeakyBucket.js.map +1 -0
- package/dist/auth/RemoteJWKSCollector.d.ts +24 -0
- package/dist/auth/RemoteJWKSCollector.js +106 -0
- package/dist/auth/RemoteJWKSCollector.js.map +1 -0
- package/dist/auth/StaticKeyCollector.d.ts +14 -0
- package/dist/auth/StaticKeyCollector.js +19 -0
- package/dist/auth/StaticKeyCollector.js.map +1 -0
- package/dist/auth/SupabaseKeyCollector.d.ts +22 -0
- package/dist/auth/SupabaseKeyCollector.js +61 -0
- package/dist/auth/SupabaseKeyCollector.js.map +1 -0
- package/dist/auth/auth-index.d.ts +10 -0
- package/dist/auth/auth-index.js +11 -0
- package/dist/auth/auth-index.js.map +1 -0
- package/dist/db/db-index.d.ts +1 -0
- package/dist/db/db-index.js +2 -0
- package/dist/db/db-index.js.map +1 -0
- package/dist/db/mongo.d.ts +29 -0
- package/dist/db/mongo.js +65 -0
- package/dist/db/mongo.js.map +1 -0
- package/dist/entry/cli-entry.d.ts +15 -0
- package/dist/entry/cli-entry.js +36 -0
- package/dist/entry/cli-entry.js.map +1 -0
- package/dist/entry/commands/config-command.d.ts +10 -0
- package/dist/entry/commands/config-command.js +21 -0
- package/dist/entry/commands/config-command.js.map +1 -0
- package/dist/entry/commands/migrate-action.d.ts +2 -0
- package/dist/entry/commands/migrate-action.js +18 -0
- package/dist/entry/commands/migrate-action.js.map +1 -0
- package/dist/entry/commands/start-action.d.ts +3 -0
- package/dist/entry/commands/start-action.js +15 -0
- package/dist/entry/commands/start-action.js.map +1 -0
- package/dist/entry/commands/teardown-action.d.ts +2 -0
- package/dist/entry/commands/teardown-action.js +17 -0
- package/dist/entry/commands/teardown-action.js.map +1 -0
- package/dist/entry/entry-index.d.ts +5 -0
- package/dist/entry/entry-index.js +6 -0
- package/dist/entry/entry-index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/locks/LockManager.d.ts +10 -0
- package/dist/locks/LockManager.js +7 -0
- package/dist/locks/LockManager.js.map +1 -0
- package/dist/locks/MongoLocks.d.ts +36 -0
- package/dist/locks/MongoLocks.js +81 -0
- package/dist/locks/MongoLocks.js.map +1 -0
- package/dist/locks/locks-index.d.ts +2 -0
- package/dist/locks/locks-index.js +3 -0
- package/dist/locks/locks-index.js.map +1 -0
- package/dist/metrics/Metrics.d.ts +30 -0
- package/dist/metrics/Metrics.js +176 -0
- package/dist/metrics/Metrics.js.map +1 -0
- package/dist/migrations/db/migrations/1684951997326-init.d.ts +3 -0
- package/dist/migrations/db/migrations/1684951997326-init.js +31 -0
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.d.ts +2 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +5 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +3 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +54 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +3 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +27 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -0
- package/dist/migrations/definitions.d.ts +18 -0
- package/dist/migrations/definitions.js +6 -0
- package/dist/migrations/definitions.js.map +1 -0
- package/dist/migrations/executor.d.ts +16 -0
- package/dist/migrations/executor.js +64 -0
- package/dist/migrations/executor.js.map +1 -0
- package/dist/migrations/migrations-index.d.ts +3 -0
- package/dist/migrations/migrations-index.js +4 -0
- package/dist/migrations/migrations-index.js.map +1 -0
- package/dist/migrations/migrations.d.ts +10 -0
- package/dist/migrations/migrations.js +90 -0
- package/dist/migrations/migrations.js.map +1 -0
- package/dist/migrations/store/migration-store.d.ts +11 -0
- package/dist/migrations/store/migration-store.js +46 -0
- package/dist/migrations/store/migration-store.js.map +1 -0
- package/dist/replication/ErrorRateLimiter.d.ts +17 -0
- package/dist/replication/ErrorRateLimiter.js +43 -0
- package/dist/replication/ErrorRateLimiter.js.map +1 -0
- package/dist/replication/PgRelation.d.ts +16 -0
- package/dist/replication/PgRelation.js +26 -0
- package/dist/replication/PgRelation.js.map +1 -0
- package/dist/replication/WalConnection.d.ts +34 -0
- package/dist/replication/WalConnection.js +190 -0
- package/dist/replication/WalConnection.js.map +1 -0
- package/dist/replication/WalStream.d.ts +57 -0
- package/dist/replication/WalStream.js +515 -0
- package/dist/replication/WalStream.js.map +1 -0
- package/dist/replication/WalStreamManager.d.ts +30 -0
- package/dist/replication/WalStreamManager.js +198 -0
- package/dist/replication/WalStreamManager.js.map +1 -0
- package/dist/replication/WalStreamRunner.d.ts +38 -0
- package/dist/replication/WalStreamRunner.js +155 -0
- package/dist/replication/WalStreamRunner.js.map +1 -0
- package/dist/replication/replication-index.d.ts +7 -0
- package/dist/replication/replication-index.js +8 -0
- package/dist/replication/replication-index.js.map +1 -0
- package/dist/replication/util.d.ts +9 -0
- package/dist/replication/util.js +62 -0
- package/dist/replication/util.js.map +1 -0
- package/dist/routes/auth.d.ts +56 -0
- package/dist/routes/auth.js +182 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/endpoints/admin.d.ts +1011 -0
- package/dist/routes/endpoints/admin.js +207 -0
- package/dist/routes/endpoints/admin.js.map +1 -0
- package/dist/routes/endpoints/checkpointing.d.ts +76 -0
- package/dist/routes/endpoints/checkpointing.js +36 -0
- package/dist/routes/endpoints/checkpointing.js.map +1 -0
- package/dist/routes/endpoints/dev.d.ts +312 -0
- package/dist/routes/endpoints/dev.js +172 -0
- package/dist/routes/endpoints/dev.js.map +1 -0
- package/dist/routes/endpoints/route-endpoints-index.d.ts +6 -0
- package/dist/routes/endpoints/route-endpoints-index.js +7 -0
- package/dist/routes/endpoints/route-endpoints-index.js.map +1 -0
- package/dist/routes/endpoints/socket-route.d.ts +2 -0
- package/dist/routes/endpoints/socket-route.js +119 -0
- package/dist/routes/endpoints/socket-route.js.map +1 -0
- package/dist/routes/endpoints/sync-rules.d.ts +174 -0
- package/dist/routes/endpoints/sync-rules.js +202 -0
- package/dist/routes/endpoints/sync-rules.js.map +1 -0
- package/dist/routes/endpoints/sync-stream.d.ts +132 -0
- package/dist/routes/endpoints/sync-stream.js +83 -0
- package/dist/routes/endpoints/sync-stream.js.map +1 -0
- package/dist/routes/hooks.d.ts +10 -0
- package/dist/routes/hooks.js +32 -0
- package/dist/routes/hooks.js.map +1 -0
- package/dist/routes/route-register.d.ts +10 -0
- package/dist/routes/route-register.js +87 -0
- package/dist/routes/route-register.js.map +1 -0
- package/dist/routes/router-socket.d.ts +10 -0
- package/dist/routes/router-socket.js +5 -0
- package/dist/routes/router-socket.js.map +1 -0
- package/dist/routes/router.d.ts +26 -0
- package/dist/routes/router.js +7 -0
- package/dist/routes/router.js.map +1 -0
- package/dist/routes/routes-index.d.ts +6 -0
- package/dist/routes/routes-index.js +7 -0
- package/dist/routes/routes-index.js.map +1 -0
- package/dist/runner/teardown.d.ts +2 -0
- package/dist/runner/teardown.js +94 -0
- package/dist/runner/teardown.js.map +1 -0
- package/dist/storage/BucketStorage.d.ts +307 -0
- package/dist/storage/BucketStorage.js +25 -0
- package/dist/storage/BucketStorage.js.map +1 -0
- package/dist/storage/ChecksumCache.d.ts +50 -0
- package/dist/storage/ChecksumCache.js +234 -0
- package/dist/storage/ChecksumCache.js.map +1 -0
- package/dist/storage/MongoBucketStorage.d.ts +52 -0
- package/dist/storage/MongoBucketStorage.js +409 -0
- package/dist/storage/MongoBucketStorage.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +39 -0
- package/dist/storage/SourceTable.js +50 -0
- package/dist/storage/SourceTable.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +48 -0
- package/dist/storage/mongo/MongoBucketBatch.js +581 -0
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -0
- package/dist/storage/mongo/MongoIdSequence.d.ts +12 -0
- package/dist/storage/mongo/MongoIdSequence.js +21 -0
- package/dist/storage/mongo/MongoIdSequence.js.map +1 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.d.ts +9 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.js +9 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.js.map +1 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +20 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +26 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +29 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.js +391 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -0
- package/dist/storage/mongo/MongoSyncRulesLock.d.ts +16 -0
- package/dist/storage/mongo/MongoSyncRulesLock.js +65 -0
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -0
- package/dist/storage/mongo/OperationBatch.d.ts +26 -0
- package/dist/storage/mongo/OperationBatch.js +101 -0
- package/dist/storage/mongo/OperationBatch.js.map +1 -0
- package/dist/storage/mongo/PersistedBatch.d.ts +46 -0
- package/dist/storage/mongo/PersistedBatch.js +213 -0
- package/dist/storage/mongo/PersistedBatch.js.map +1 -0
- package/dist/storage/mongo/db.d.ts +26 -0
- package/dist/storage/mongo/db.js +35 -0
- package/dist/storage/mongo/db.js.map +1 -0
- package/dist/storage/mongo/models.d.ts +140 -0
- package/dist/storage/mongo/models.js +27 -0
- package/dist/storage/mongo/models.js.map +1 -0
- package/dist/storage/mongo/util.d.ts +26 -0
- package/dist/storage/mongo/util.js +81 -0
- package/dist/storage/mongo/util.js.map +1 -0
- package/dist/storage/storage-index.d.ts +14 -0
- package/dist/storage/storage-index.js +15 -0
- package/dist/storage/storage-index.js.map +1 -0
- package/dist/sync/BroadcastIterable.d.ts +38 -0
- package/dist/sync/BroadcastIterable.js +153 -0
- package/dist/sync/BroadcastIterable.js.map +1 -0
- package/dist/sync/LastValueSink.d.ts +25 -0
- package/dist/sync/LastValueSink.js +84 -0
- package/dist/sync/LastValueSink.js.map +1 -0
- package/dist/sync/merge.d.ts +39 -0
- package/dist/sync/merge.js +175 -0
- package/dist/sync/merge.js.map +1 -0
- package/dist/sync/safeRace.d.ts +1 -0
- package/dist/sync/safeRace.js +91 -0
- package/dist/sync/safeRace.js.map +1 -0
- package/dist/sync/sync-index.d.ts +6 -0
- package/dist/sync/sync-index.js +7 -0
- package/dist/sync/sync-index.js.map +1 -0
- package/dist/sync/sync.d.ts +18 -0
- package/dist/sync/sync.js +259 -0
- package/dist/sync/sync.js.map +1 -0
- package/dist/sync/util.d.ts +26 -0
- package/dist/sync/util.js +73 -0
- package/dist/sync/util.js.map +1 -0
- package/dist/system/CorePowerSyncSystem.d.ts +23 -0
- package/dist/system/CorePowerSyncSystem.js +52 -0
- package/dist/system/CorePowerSyncSystem.js.map +1 -0
- package/dist/system/system-index.d.ts +1 -0
- package/dist/system/system-index.js +2 -0
- package/dist/system/system-index.js.map +1 -0
- package/dist/util/Mutex.d.ts +47 -0
- package/dist/util/Mutex.js +132 -0
- package/dist/util/Mutex.js.map +1 -0
- package/dist/util/PgManager.d.ts +24 -0
- package/dist/util/PgManager.js +55 -0
- package/dist/util/PgManager.js.map +1 -0
- package/dist/util/alerting.d.ts +2 -0
- package/dist/util/alerting.js +8 -0
- package/dist/util/alerting.js.map +1 -0
- package/dist/util/config/collectors/config-collector.d.ts +29 -0
- package/dist/util/config/collectors/config-collector.js +116 -0
- package/dist/util/config/collectors/config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/base64-config-collector.d.ts +6 -0
- package/dist/util/config/collectors/impl/base64-config-collector.js +15 -0
- package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.d.ts +11 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.js +19 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.d.ts +6 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.js +37 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -0
- package/dist/util/config/compound-config-collector.d.ts +32 -0
- package/dist/util/config/compound-config-collector.js +130 -0
- package/dist/util/config/compound-config-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js +17 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js +21 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js +17 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/sync-collector.d.ts +6 -0
- package/dist/util/config/sync-rules/sync-collector.js +3 -0
- package/dist/util/config/sync-rules/sync-collector.js.map +1 -0
- package/dist/util/config/types.d.ts +57 -0
- package/dist/util/config/types.js +7 -0
- package/dist/util/config/types.js.map +1 -0
- package/dist/util/config.d.ts +7 -0
- package/dist/util/config.js +35 -0
- package/dist/util/config.js.map +1 -0
- package/dist/util/env.d.ts +9 -0
- package/dist/util/env.js +26 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/memory-tracking.d.ts +7 -0
- package/dist/util/memory-tracking.js +58 -0
- package/dist/util/memory-tracking.js.map +1 -0
- package/dist/util/migration_lib.d.ts +11 -0
- package/dist/util/migration_lib.js +64 -0
- package/dist/util/migration_lib.js.map +1 -0
- package/dist/util/pgwire_utils.d.ts +24 -0
- package/dist/util/pgwire_utils.js +117 -0
- package/dist/util/pgwire_utils.js.map +1 -0
- package/dist/util/populate_test_data.d.ts +8 -0
- package/dist/util/populate_test_data.js +65 -0
- package/dist/util/populate_test_data.js.map +1 -0
- package/dist/util/protocol-types.d.ts +182 -0
- package/dist/util/protocol-types.js +42 -0
- package/dist/util/protocol-types.js.map +1 -0
- package/dist/util/secs.d.ts +2 -0
- package/dist/util/secs.js +49 -0
- package/dist/util/secs.js.map +1 -0
- package/dist/util/util-index.d.ts +22 -0
- package/dist/util/util-index.js +23 -0
- package/dist/util/util-index.js.map +1 -0
- package/dist/util/utils.d.ts +17 -0
- package/dist/util/utils.js +92 -0
- package/dist/util/utils.js.map +1 -0
- package/package.json +59 -0
- package/src/api/api-index.ts +2 -0
- package/src/api/diagnostics.ts +221 -0
- package/src/api/schema.ts +99 -0
- package/src/auth/CachedKeyCollector.ts +132 -0
- package/src/auth/CompoundKeyCollector.ts +33 -0
- package/src/auth/JwtPayload.ts +11 -0
- package/src/auth/KeyCollector.ts +27 -0
- package/src/auth/KeySpec.ts +67 -0
- package/src/auth/KeyStore.ts +156 -0
- package/src/auth/LeakyBucket.ts +66 -0
- package/src/auth/RemoteJWKSCollector.ts +130 -0
- package/src/auth/StaticKeyCollector.ts +21 -0
- package/src/auth/SupabaseKeyCollector.ts +67 -0
- package/src/auth/auth-index.ts +10 -0
- package/src/db/db-index.ts +1 -0
- package/src/db/mongo.ts +72 -0
- package/src/entry/cli-entry.ts +40 -0
- package/src/entry/commands/config-command.ts +36 -0
- package/src/entry/commands/migrate-action.ts +25 -0
- package/src/entry/commands/start-action.ts +24 -0
- package/src/entry/commands/teardown-action.ts +23 -0
- package/src/entry/entry-index.ts +5 -0
- package/src/index.ts +40 -0
- package/src/locks/LockManager.ts +16 -0
- package/src/locks/MongoLocks.ts +142 -0
- package/src/locks/locks-index.ts +2 -0
- package/src/metrics/Metrics.ts +265 -0
- package/src/migrations/db/migrations/1684951997326-init.ts +33 -0
- package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +5 -0
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +99 -0
- package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +32 -0
- package/src/migrations/definitions.ts +21 -0
- package/src/migrations/executor.ts +87 -0
- package/src/migrations/migrations-index.ts +3 -0
- package/src/migrations/migrations.ts +118 -0
- package/src/migrations/store/migration-store.ts +63 -0
- package/src/replication/ErrorRateLimiter.ts +50 -0
- package/src/replication/PgRelation.ts +42 -0
- package/src/replication/WalConnection.ts +227 -0
- package/src/replication/WalStream.ts +624 -0
- package/src/replication/WalStreamManager.ts +213 -0
- package/src/replication/WalStreamRunner.ts +180 -0
- package/src/replication/replication-index.ts +7 -0
- package/src/replication/util.ts +76 -0
- package/src/routes/auth.ts +215 -0
- package/src/routes/endpoints/admin.ts +237 -0
- package/src/routes/endpoints/checkpointing.ts +41 -0
- package/src/routes/endpoints/dev.ts +199 -0
- package/src/routes/endpoints/route-endpoints-index.ts +6 -0
- package/src/routes/endpoints/socket-route.ts +135 -0
- package/src/routes/endpoints/sync-rules.ts +227 -0
- package/src/routes/endpoints/sync-stream.ts +101 -0
- package/src/routes/hooks.ts +46 -0
- package/src/routes/route-register.ts +104 -0
- package/src/routes/router-socket.ts +13 -0
- package/src/routes/router.ts +46 -0
- package/src/routes/routes-index.ts +6 -0
- package/src/runner/teardown.ts +108 -0
- package/src/storage/BucketStorage.ts +396 -0
- package/src/storage/ChecksumCache.ts +294 -0
- package/src/storage/MongoBucketStorage.ts +519 -0
- package/src/storage/SourceTable.ts +60 -0
- package/src/storage/mongo/MongoBucketBatch.ts +752 -0
- package/src/storage/mongo/MongoIdSequence.ts +24 -0
- package/src/storage/mongo/MongoPersistedSyncRules.ts +16 -0
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +47 -0
- package/src/storage/mongo/MongoSyncBucketStorage.ts +533 -0
- package/src/storage/mongo/MongoSyncRulesLock.ts +81 -0
- package/src/storage/mongo/OperationBatch.ts +115 -0
- package/src/storage/mongo/PersistedBatch.ts +268 -0
- package/src/storage/mongo/db.ts +73 -0
- package/src/storage/mongo/models.ts +162 -0
- package/src/storage/mongo/util.ts +88 -0
- package/src/storage/storage-index.ts +15 -0
- package/src/sync/BroadcastIterable.ts +161 -0
- package/src/sync/LastValueSink.ts +100 -0
- package/src/sync/merge.ts +200 -0
- package/src/sync/safeRace.ts +99 -0
- package/src/sync/sync-index.ts +6 -0
- package/src/sync/sync.ts +319 -0
- package/src/sync/util.ts +98 -0
- package/src/system/CorePowerSyncSystem.ts +64 -0
- package/src/system/system-index.ts +1 -0
- package/src/util/Mutex.ts +159 -0
- package/src/util/PgManager.ts +64 -0
- package/src/util/alerting.ts +9 -0
- package/src/util/config/collectors/config-collector.ts +143 -0
- package/src/util/config/collectors/impl/base64-config-collector.ts +18 -0
- package/src/util/config/collectors/impl/fallback-config-collector.ts +22 -0
- package/src/util/config/collectors/impl/filesystem-config-collector.ts +43 -0
- package/src/util/config/compound-config-collector.ts +176 -0
- package/src/util/config/sync-rules/impl/base64-sync-rules-collector.ts +21 -0
- package/src/util/config/sync-rules/impl/filesystem-sync-rules-collector.ts +26 -0
- package/src/util/config/sync-rules/impl/inline-sync-rules-collector.ts +21 -0
- package/src/util/config/sync-rules/sync-collector.ts +8 -0
- package/src/util/config/types.ts +66 -0
- package/src/util/config.ts +39 -0
- package/src/util/env.ts +30 -0
- package/src/util/memory-tracking.ts +67 -0
- package/src/util/migration_lib.ts +79 -0
- package/src/util/pgwire_utils.ts +139 -0
- package/src/util/populate_test_data.ts +78 -0
- package/src/util/protocol-types.ts +228 -0
- package/src/util/secs.ts +54 -0
- package/src/util/util-index.ts +25 -0
- package/src/util/utils.ts +122 -0
- package/test/src/__snapshots__/pg_test.test.ts.snap +256 -0
- package/test/src/__snapshots__/sync.test.ts.snap +247 -0
- package/test/src/auth.test.ts +342 -0
- package/test/src/broadcast_iterable.test.ts +156 -0
- package/test/src/checksum_cache.test.ts +436 -0
- package/test/src/data_storage.test.ts +1176 -0
- package/test/src/env.ts +8 -0
- package/test/src/large_batch.test.ts +194 -0
- package/test/src/merge_iterable.test.ts +355 -0
- package/test/src/pg_test.test.ts +450 -0
- package/test/src/schema_changes.test.ts +545 -0
- package/test/src/setup.ts +7 -0
- package/test/src/slow_tests.test.ts +257 -0
- package/test/src/sql_functions.test.ts +254 -0
- package/test/src/sql_operators.test.ts +132 -0
- package/test/src/sync.test.ts +293 -0
- package/test/src/sync_rules.test.ts +1053 -0
- package/test/src/util.ts +76 -0
- package/test/src/validation.test.ts +63 -0
- package/test/src/wal_stream.test.ts +319 -0
- package/test/src/wal_stream_utils.ts +147 -0
- package/test/tsconfig.json +20 -0
- package/tsconfig.json +31 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +9 -0
package/test/src/env.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { utils } from '@powersync/lib-services-framework';
|
|
2
|
+
|
|
3
|
+
export const env = utils.collectEnvironmentVariables({
|
|
4
|
+
MONGO_TEST_URL: utils.type.string.default('mongodb://localhost:27017/powersync_test'),
|
|
5
|
+
PG_TEST_URL: utils.type.string.default('postgres://postgres:postgres@localhost:5432/powersync_test'),
|
|
6
|
+
CI: utils.type.boolean.default('false'),
|
|
7
|
+
SLOW_TESTS: utils.type.boolean.default('false')
|
|
8
|
+
});
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { env } from './env.js';
|
|
3
|
+
import { MONGO_STORAGE_FACTORY, StorageFactory, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
4
|
+
import { walStreamTest } from './wal_stream_utils.js';
|
|
5
|
+
import { populateData } from '../../dist/util/populate_test_data.js';
|
|
6
|
+
|
|
7
|
+
describe('batch replication tests - mongodb', function () {
|
|
8
|
+
// These are slow but consistent tests.
|
|
9
|
+
// Not run on every test run, but we do run on CI, or when manually debugging issues.
|
|
10
|
+
if (env.CI || env.SLOW_TESTS) {
|
|
11
|
+
defineBatchTests(MONGO_STORAGE_FACTORY);
|
|
12
|
+
} else {
|
|
13
|
+
// Need something in this file.
|
|
14
|
+
test('no-op', () => {});
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const BASIC_SYNC_RULES = `bucket_definitions:
|
|
19
|
+
global:
|
|
20
|
+
data:
|
|
21
|
+
- SELECT id, description, other FROM "test_data"`;
|
|
22
|
+
|
|
23
|
+
function defineBatchTests(factory: StorageFactory) {
|
|
24
|
+
test(
|
|
25
|
+
'update large record',
|
|
26
|
+
walStreamTest(factory, async (context) => {
|
|
27
|
+
// This test generates a large transaction in MongoDB, despite the replicated data
|
|
28
|
+
// not being that large.
|
|
29
|
+
// If we don't limit transaction size, we could run into this error:
|
|
30
|
+
// > -31800: transaction is too large and will not fit in the storage engine cache
|
|
31
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
32
|
+
const { pool } = context;
|
|
33
|
+
|
|
34
|
+
await pool.query(`CREATE TABLE test_data(id text primary key, description text, other text)`);
|
|
35
|
+
|
|
36
|
+
await context.replicateSnapshot();
|
|
37
|
+
|
|
38
|
+
let operation_count = await populateData({
|
|
39
|
+
num_transactions: 1,
|
|
40
|
+
per_transaction: 80,
|
|
41
|
+
size: 4_000_000,
|
|
42
|
+
connection: TEST_CONNECTION_OPTIONS
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const start = Date.now();
|
|
46
|
+
|
|
47
|
+
context.startStreaming();
|
|
48
|
+
|
|
49
|
+
const checkpoint = await context.getCheckpoint({ timeout: 100_000 });
|
|
50
|
+
const duration = Date.now() - start;
|
|
51
|
+
const used = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
52
|
+
const checksum = await context.storage!.getChecksums(checkpoint, ['global[]']);
|
|
53
|
+
expect(checksum.get('global[]')!.count).toEqual(operation_count);
|
|
54
|
+
const perSecond = Math.round((operation_count / duration) * 1000);
|
|
55
|
+
console.log(`${operation_count} ops in ${duration}ms ${perSecond} ops/s. ${used}MB heap`);
|
|
56
|
+
}),
|
|
57
|
+
{ timeout: 120_000 }
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
test(
|
|
61
|
+
'initial replication performance',
|
|
62
|
+
walStreamTest(factory, async (context) => {
|
|
63
|
+
// Manual test to check initial replication performance and memory usage
|
|
64
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
65
|
+
const { pool } = context;
|
|
66
|
+
|
|
67
|
+
await pool.query(`CREATE TABLE test_data(id text primary key, description text, other text)`);
|
|
68
|
+
|
|
69
|
+
// Some stats (varies a lot):
|
|
70
|
+
// Old 'postgres' driver, using cursor(2)
|
|
71
|
+
// 15 ops in 19559ms 1 ops/s. 354MB RSS, 115MB heap, 137MB external
|
|
72
|
+
// 25 ops in 42984ms 1 ops/s. 377MB RSS, 129MB heap, 137MB external
|
|
73
|
+
// 35 ops in 41337ms 1 ops/s. 365MB RSS, 115MB heap, 137MB external
|
|
74
|
+
|
|
75
|
+
// streaming with pgwire
|
|
76
|
+
// 15 ops in 26423ms 1 ops/s. 379MB RSS, 128MB heap, 182MB external, 165MB ArrayBuffers
|
|
77
|
+
// 35 ops in 78897ms 0 ops/s. 539MB RSS, 52MB heap, 87MB external, 83MB ArrayBuffers
|
|
78
|
+
|
|
79
|
+
let operation_count = await populateData({
|
|
80
|
+
num_transactions: 1,
|
|
81
|
+
per_transaction: 35,
|
|
82
|
+
size: 14_000_000,
|
|
83
|
+
connection: TEST_CONNECTION_OPTIONS
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
global.gc?.();
|
|
87
|
+
|
|
88
|
+
// Note that we could already have high memory usage at this point
|
|
89
|
+
printMemoryUsage();
|
|
90
|
+
|
|
91
|
+
let interval = setInterval(() => {
|
|
92
|
+
printMemoryUsage();
|
|
93
|
+
}, 2000);
|
|
94
|
+
try {
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
|
|
97
|
+
await context.replicateSnapshot();
|
|
98
|
+
await context.storage!.autoActivate();
|
|
99
|
+
context.startStreaming();
|
|
100
|
+
|
|
101
|
+
const checkpoint = await context.getCheckpoint({ timeout: 100_000 });
|
|
102
|
+
const duration = Date.now() - start;
|
|
103
|
+
const checksum = await context.storage!.getChecksums(checkpoint, ['global[]']);
|
|
104
|
+
expect(checksum.get('global[]')!.count).toEqual(operation_count);
|
|
105
|
+
const perSecond = Math.round((operation_count / duration) * 1000);
|
|
106
|
+
console.log(`${operation_count} ops in ${duration}ms ${perSecond} ops/s.`);
|
|
107
|
+
printMemoryUsage();
|
|
108
|
+
} finally {
|
|
109
|
+
clearInterval(interval);
|
|
110
|
+
}
|
|
111
|
+
}),
|
|
112
|
+
{ timeout: 120_000 }
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
test(
|
|
116
|
+
'large number of operations',
|
|
117
|
+
walStreamTest(factory, async (context) => {
|
|
118
|
+
// This just tests performance of a large number of operations inside a transaction.
|
|
119
|
+
await context.updateSyncRules(BASIC_SYNC_RULES);
|
|
120
|
+
const { pool } = context;
|
|
121
|
+
|
|
122
|
+
await pool.query(`CREATE TABLE test_data(id text primary key, description text, other text)`);
|
|
123
|
+
|
|
124
|
+
await context.replicateSnapshot();
|
|
125
|
+
|
|
126
|
+
const numTransactions = 20;
|
|
127
|
+
const perTransaction = 1500;
|
|
128
|
+
let operationCount = 0;
|
|
129
|
+
|
|
130
|
+
const description = 'description';
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < numTransactions; i++) {
|
|
133
|
+
const prefix = `test${i}K`;
|
|
134
|
+
|
|
135
|
+
await pool.query(
|
|
136
|
+
{
|
|
137
|
+
statement: `INSERT INTO test_data(id, description, other) SELECT $1 || i, $2 || i, 'foo' FROM generate_series(1, $3) i`,
|
|
138
|
+
params: [
|
|
139
|
+
{ type: 'varchar', value: prefix },
|
|
140
|
+
{ type: 'varchar', value: description },
|
|
141
|
+
{ type: 'int4', value: perTransaction }
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
statement: `UPDATE test_data SET other = other || '#' WHERE id LIKE $1 || '%'`,
|
|
146
|
+
params: [{ type: 'varchar', value: prefix }]
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
operationCount += perTransaction * 2;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const start = Date.now();
|
|
153
|
+
|
|
154
|
+
context.startStreaming();
|
|
155
|
+
|
|
156
|
+
const checkpoint = await context.getCheckpoint({ timeout: 50_000 });
|
|
157
|
+
const duration = Date.now() - start;
|
|
158
|
+
const used = Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
159
|
+
const checksum = await context.storage!.getChecksums(checkpoint, ['global[]']);
|
|
160
|
+
expect(checksum.get('global[]')!.count).toEqual(operationCount);
|
|
161
|
+
const perSecond = Math.round((operationCount / duration) * 1000);
|
|
162
|
+
// This number depends on the test machine, so we keep the test significantly
|
|
163
|
+
// lower than expected numbers.
|
|
164
|
+
expect(perSecond).toBeGreaterThan(1000);
|
|
165
|
+
console.log(`${operationCount} ops in ${duration}ms ${perSecond} ops/s. ${used}MB heap`);
|
|
166
|
+
|
|
167
|
+
// Truncating is fast (~10k ops/second).
|
|
168
|
+
// We'd need a really large set of data to actually run into limits when truncating,
|
|
169
|
+
// but we just test with the data we have here.
|
|
170
|
+
const truncateStart = Date.now();
|
|
171
|
+
await pool.query(`TRUNCATE test_data`);
|
|
172
|
+
|
|
173
|
+
const checkpoint2 = await context.getCheckpoint({ timeout: 20_000 });
|
|
174
|
+
const truncateDuration = Date.now() - truncateStart;
|
|
175
|
+
|
|
176
|
+
const checksum2 = await context.storage!.getChecksums(checkpoint2, ['global[]']);
|
|
177
|
+
const truncateCount = checksum2.get('global[]')!.count - checksum.get('global[]')!.count;
|
|
178
|
+
expect(truncateCount).toEqual(numTransactions * perTransaction);
|
|
179
|
+
const truncatePerSecond = Math.round((truncateCount / truncateDuration) * 1000);
|
|
180
|
+
console.log(`Truncated ${truncateCount} ops in ${truncateDuration}ms ${truncatePerSecond} ops/s. ${used}MB heap`);
|
|
181
|
+
}),
|
|
182
|
+
{ timeout: 90_000 }
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
function printMemoryUsage() {
|
|
186
|
+
const memoryUsage = process.memoryUsage();
|
|
187
|
+
|
|
188
|
+
const rss = Math.round(memoryUsage.rss / 1024 / 1024);
|
|
189
|
+
const heap = Math.round(memoryUsage.heapUsed / 1024 / 1024);
|
|
190
|
+
const external = Math.round(memoryUsage.external / 1024 / 1024);
|
|
191
|
+
const arrayBuffers = Math.round(memoryUsage.arrayBuffers / 1024 / 1024);
|
|
192
|
+
console.log(`${rss}MB RSS, ${heap}MB heap, ${external}MB external, ${arrayBuffers}MB ArrayBuffers`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import * as timers from 'timers/promises';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import {
|
|
4
|
+
FixedMergeAsyncIterable,
|
|
5
|
+
mergeAsyncIterables,
|
|
6
|
+
mergeAsyncIterablesNew,
|
|
7
|
+
mergeAsyncIterablesOld
|
|
8
|
+
} from '../../src/sync/merge.js';
|
|
9
|
+
|
|
10
|
+
type MergeIteratorFunction = <T>(source: AsyncIterable<T>[]) => AsyncIterable<T>;
|
|
11
|
+
|
|
12
|
+
describe('merge iterables', () => {
|
|
13
|
+
makeTests((source) => mergeAsyncIterablesNew(source));
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('merge iterables - legacy implementation', () => {
|
|
17
|
+
makeTests((source) => mergeAsyncIterablesOld(source));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function makeTests(mergeIterables: MergeIteratorFunction) {
|
|
21
|
+
test('iterable should not pre-emptively continue (1)', async () => {
|
|
22
|
+
// Test that the generator stops after the first yield
|
|
23
|
+
let afterYield = false;
|
|
24
|
+
let inFinally = false;
|
|
25
|
+
const a = async function* (): AsyncGenerator<number, void> {
|
|
26
|
+
try {
|
|
27
|
+
yield 1;
|
|
28
|
+
afterYield = true;
|
|
29
|
+
throw new Error('foobar');
|
|
30
|
+
} finally {
|
|
31
|
+
inFinally = true;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const merged = mergeIterables([a()]);
|
|
36
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
37
|
+
const r = await iter.next();
|
|
38
|
+
expect(r).toEqual({ value: 1, done: false });
|
|
39
|
+
await iter.return!();
|
|
40
|
+
expect(afterYield).toEqual(false);
|
|
41
|
+
expect(inFinally).toEqual(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('iterable should not pre-emptively continue (2)', async () => {
|
|
45
|
+
// Test that the generator stops after the first yield
|
|
46
|
+
// Equivalent to the above test, but using `for await` instead of manually iterating.
|
|
47
|
+
let afterYield = false;
|
|
48
|
+
let inFinally = false;
|
|
49
|
+
const a = async function* (): AsyncGenerator<number, void> {
|
|
50
|
+
try {
|
|
51
|
+
yield 1;
|
|
52
|
+
afterYield = true;
|
|
53
|
+
throw new Error('foobar');
|
|
54
|
+
} finally {
|
|
55
|
+
inFinally = true;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const merged = mergeIterables([a()]);
|
|
60
|
+
|
|
61
|
+
for await (let r of merged) {
|
|
62
|
+
expect(r).toEqual(1);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
expect(afterYield).toEqual(false);
|
|
67
|
+
expect(inFinally).toEqual(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('iterable should cleanup', async () => {
|
|
71
|
+
// Test that the generator is exhauseted
|
|
72
|
+
let afterYield = false;
|
|
73
|
+
let inFinally = false;
|
|
74
|
+
const a = async function* (): AsyncGenerator<number, void> {
|
|
75
|
+
try {
|
|
76
|
+
yield 1;
|
|
77
|
+
afterYield = true;
|
|
78
|
+
} finally {
|
|
79
|
+
inFinally = true;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const merged = mergeIterables([a()]);
|
|
84
|
+
|
|
85
|
+
for await (let r of merged) {
|
|
86
|
+
expect(r).toEqual(1);
|
|
87
|
+
}
|
|
88
|
+
expect(afterYield).toEqual(true);
|
|
89
|
+
expect(inFinally).toEqual(true);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('multiple iterables should cleanup', async () => {
|
|
93
|
+
// Test that the generator is exhauseted
|
|
94
|
+
let afterYieldA = false;
|
|
95
|
+
let inFinallyA = false;
|
|
96
|
+
let afterYieldB = false;
|
|
97
|
+
let inFinallyB = false;
|
|
98
|
+
const a = async function* (): AsyncGenerator<string, void> {
|
|
99
|
+
try {
|
|
100
|
+
yield 'a';
|
|
101
|
+
afterYieldA = true;
|
|
102
|
+
} finally {
|
|
103
|
+
inFinallyA = true;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const b = async function* (): AsyncGenerator<string, void> {
|
|
107
|
+
try {
|
|
108
|
+
yield 'b';
|
|
109
|
+
afterYieldB = true;
|
|
110
|
+
} finally {
|
|
111
|
+
inFinallyB = true;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const merged = mergeIterables([a(), b()]);
|
|
116
|
+
|
|
117
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
118
|
+
expect(await iter.next()).toEqual({ value: 'a', done: false });
|
|
119
|
+
expect(await iter.next()).toEqual({ value: 'b', done: false });
|
|
120
|
+
expect(await iter.next()).toEqual({ value: undefined, done: true });
|
|
121
|
+
|
|
122
|
+
expect(afterYieldA).toEqual(true);
|
|
123
|
+
expect(inFinallyA).toEqual(true);
|
|
124
|
+
expect(afterYieldB).toEqual(true);
|
|
125
|
+
expect(inFinallyB).toEqual(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('merging two (1)', async () => {
|
|
129
|
+
let aDone = false;
|
|
130
|
+
let bDone = false;
|
|
131
|
+
let aReached = false;
|
|
132
|
+
let bReached = false;
|
|
133
|
+
|
|
134
|
+
const a = async function* (): AsyncGenerator<string, void> {
|
|
135
|
+
try {
|
|
136
|
+
yield 'a';
|
|
137
|
+
await timers.setTimeout(0);
|
|
138
|
+
// Should reach this
|
|
139
|
+
aReached = true;
|
|
140
|
+
throw new Error('a');
|
|
141
|
+
} finally {
|
|
142
|
+
// Should reach this
|
|
143
|
+
aDone = true;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const b = async function* (): AsyncGenerator<string, void> {
|
|
147
|
+
try {
|
|
148
|
+
yield 'b';
|
|
149
|
+
// Should not reach this
|
|
150
|
+
bReached = true;
|
|
151
|
+
await timers.setTimeout(1);
|
|
152
|
+
throw new Error('b');
|
|
153
|
+
} finally {
|
|
154
|
+
// Should reach this
|
|
155
|
+
bDone = true;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const merged = mergeIterables([a(), b()]);
|
|
160
|
+
|
|
161
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
162
|
+
expect(await iter.next()).toEqual({ value: 'a', done: false });
|
|
163
|
+
expect(await iter.next()).toEqual({ value: 'b', done: false });
|
|
164
|
+
await iter.return!();
|
|
165
|
+
|
|
166
|
+
await timers.setTimeout(2);
|
|
167
|
+
|
|
168
|
+
expect(aDone).toEqual(true);
|
|
169
|
+
expect(bDone).toEqual(true);
|
|
170
|
+
expect(aReached).toEqual(true);
|
|
171
|
+
expect(bReached).toEqual(false);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('ending one iterator early', async () => {
|
|
175
|
+
let aDone = false;
|
|
176
|
+
let bDone = false;
|
|
177
|
+
let b2Reached = false;
|
|
178
|
+
let b3Reached = false;
|
|
179
|
+
|
|
180
|
+
const a = async function* (): AsyncGenerator<string, void> {
|
|
181
|
+
try {
|
|
182
|
+
yield 'a';
|
|
183
|
+
} finally {
|
|
184
|
+
aDone = true;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const b = async function* (): AsyncGenerator<string, void> {
|
|
188
|
+
try {
|
|
189
|
+
yield 'b1';
|
|
190
|
+
// This point should be reached, even if the value is not used
|
|
191
|
+
b2Reached = true;
|
|
192
|
+
yield 'b2';
|
|
193
|
+
// This point should not be reached
|
|
194
|
+
b3Reached = true;
|
|
195
|
+
yield 'b3';
|
|
196
|
+
} finally {
|
|
197
|
+
bDone = true;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const merged = mergeIterables([a(), b()]);
|
|
202
|
+
|
|
203
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
204
|
+
expect(await iter.next()).toEqual({ value: 'a', done: false });
|
|
205
|
+
expect(await iter.next()).toEqual({ value: 'b1', done: false });
|
|
206
|
+
expect(await iter.next()).toEqual({ value: undefined, done: true });
|
|
207
|
+
|
|
208
|
+
await timers.setTimeout(2);
|
|
209
|
+
|
|
210
|
+
expect(aDone).toEqual(true);
|
|
211
|
+
expect(bDone).toEqual(true);
|
|
212
|
+
expect(b2Reached).toEqual(true);
|
|
213
|
+
expect(b3Reached).toEqual(false);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test('propagating errors from source', async () => {
|
|
217
|
+
// An error in one source iterator should:
|
|
218
|
+
// 1. Propagate to the merged iterator.
|
|
219
|
+
// 2. Return the other source iterator(s).
|
|
220
|
+
let bDone = false;
|
|
221
|
+
let bError = null;
|
|
222
|
+
let b2Reached = false;
|
|
223
|
+
let b3Reached = false;
|
|
224
|
+
|
|
225
|
+
const a = async function* (): AsyncGenerator<string, void> {
|
|
226
|
+
yield 'a';
|
|
227
|
+
await timers.setTimeout(0);
|
|
228
|
+
throw new Error('aError');
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const b = async function* (): AsyncGenerator<string, void> {
|
|
232
|
+
try {
|
|
233
|
+
yield 'b1';
|
|
234
|
+
await timers.setTimeout(0);
|
|
235
|
+
// This point should be reached, even if the value is not used
|
|
236
|
+
b2Reached = true;
|
|
237
|
+
yield 'b2';
|
|
238
|
+
await timers.setTimeout(0);
|
|
239
|
+
// This point should not be reached
|
|
240
|
+
b3Reached = true;
|
|
241
|
+
yield 'b3';
|
|
242
|
+
} catch (e) {
|
|
243
|
+
bError = e;
|
|
244
|
+
} finally {
|
|
245
|
+
bDone = true;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const merged = mergeIterables([a(), b()]);
|
|
250
|
+
|
|
251
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
252
|
+
expect(await iter.next()).toEqual({ value: 'a', done: false });
|
|
253
|
+
expect(await iter.next()).toEqual({ value: 'b1', done: false });
|
|
254
|
+
let error = null;
|
|
255
|
+
try {
|
|
256
|
+
await iter.next();
|
|
257
|
+
} catch (e) {
|
|
258
|
+
error = e;
|
|
259
|
+
}
|
|
260
|
+
expect(error).toEqual(new Error('aError'));
|
|
261
|
+
|
|
262
|
+
await timers.setTimeout(2);
|
|
263
|
+
|
|
264
|
+
expect(bDone).toEqual(true);
|
|
265
|
+
expect(bError).toEqual(null);
|
|
266
|
+
expect(b2Reached).toEqual(true);
|
|
267
|
+
expect(b3Reached).toEqual(false);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test('propagating errors from result', async () => {
|
|
271
|
+
// We cannot trigger this using a `for await` loop,
|
|
272
|
+
// only by using the iterator directly.
|
|
273
|
+
// Skipped since the old iterator doesn't implement this.
|
|
274
|
+
let aReached = false;
|
|
275
|
+
let aFinally = false;
|
|
276
|
+
let aError = null;
|
|
277
|
+
|
|
278
|
+
const a = async function* (): AsyncGenerator<number, void> {
|
|
279
|
+
try {
|
|
280
|
+
yield 1;
|
|
281
|
+
aReached = true;
|
|
282
|
+
} catch (e) {
|
|
283
|
+
aError = e;
|
|
284
|
+
} finally {
|
|
285
|
+
aFinally = true;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const merged = mergeIterables([a()]);
|
|
290
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
291
|
+
const r = await iter.next();
|
|
292
|
+
expect(r).toEqual({ value: 1, done: false });
|
|
293
|
+
let iterError = null;
|
|
294
|
+
try {
|
|
295
|
+
await iter.throw!(new Error('loop error'));
|
|
296
|
+
} catch (e) {
|
|
297
|
+
iterError = e;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
expect(iterError).toEqual(new Error('loop error'));
|
|
301
|
+
expect(aReached).toEqual(false);
|
|
302
|
+
expect(aFinally).toEqual(true);
|
|
303
|
+
expect(aError).toEqual(new Error('loop error'));
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('do not block return', async () => {
|
|
307
|
+
let aDone = false;
|
|
308
|
+
let bDone = false;
|
|
309
|
+
let b2Reached = false;
|
|
310
|
+
let b2Timedout = false;
|
|
311
|
+
let b3Reached = false;
|
|
312
|
+
|
|
313
|
+
const a = async function* (): AsyncGenerator<string, void> {
|
|
314
|
+
try {
|
|
315
|
+
yield 'a';
|
|
316
|
+
} finally {
|
|
317
|
+
aDone = true;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const b = async function* (): AsyncGenerator<string, void> {
|
|
321
|
+
try {
|
|
322
|
+
yield 'b1';
|
|
323
|
+
// This point should be reached, even if the value is not used
|
|
324
|
+
b2Reached = true;
|
|
325
|
+
// The final iter.next() should not wait for this to complete
|
|
326
|
+
await timers.setTimeout(50);
|
|
327
|
+
b2Timedout = true;
|
|
328
|
+
yield 'b2';
|
|
329
|
+
// This point should not be reached
|
|
330
|
+
b3Reached = true;
|
|
331
|
+
} finally {
|
|
332
|
+
bDone = true;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const merged = mergeIterables([a(), b()]);
|
|
337
|
+
|
|
338
|
+
const iter = merged[Symbol.asyncIterator]();
|
|
339
|
+
expect(await iter.next()).toEqual({ value: 'a', done: false });
|
|
340
|
+
expect(await iter.next()).toEqual({ value: 'b1', done: false });
|
|
341
|
+
expect(await iter.next()).toEqual({ value: undefined, done: true });
|
|
342
|
+
|
|
343
|
+
expect(aDone).toEqual(true);
|
|
344
|
+
expect(b2Reached).toEqual(true);
|
|
345
|
+
expect(b2Reached).toEqual(true);
|
|
346
|
+
expect(b2Timedout).toEqual(false);
|
|
347
|
+
expect(bDone).toEqual(false);
|
|
348
|
+
|
|
349
|
+
await timers.setTimeout(60);
|
|
350
|
+
|
|
351
|
+
expect(b2Timedout).toEqual(true);
|
|
352
|
+
expect(bDone).toEqual(true);
|
|
353
|
+
expect(b3Reached).toEqual(false);
|
|
354
|
+
});
|
|
355
|
+
}
|