@dotdo/postgres 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +868 -0
- package/dist/cdc/change-stream.d.ts +44 -0
- package/dist/cdc/change-stream.d.ts.map +1 -0
- package/dist/cdc/change-stream.js +95 -0
- package/dist/cdc/change-stream.js.map +1 -0
- package/dist/cdc/filter.d.ts +58 -0
- package/dist/cdc/filter.d.ts.map +1 -0
- package/dist/cdc/filter.js +520 -0
- package/dist/cdc/filter.js.map +1 -0
- package/dist/cdc/index.d.ts +47 -0
- package/dist/cdc/index.d.ts.map +1 -0
- package/dist/cdc/index.js +50 -0
- package/dist/cdc/index.js.map +1 -0
- package/dist/cdc/resume-token.d.ts +60 -0
- package/dist/cdc/resume-token.d.ts.map +1 -0
- package/dist/cdc/resume-token.js +228 -0
- package/dist/cdc/resume-token.js.map +1 -0
- package/dist/cdc/transport/index.d.ts +7 -0
- package/dist/cdc/transport/index.d.ts.map +1 -0
- package/dist/cdc/transport/index.js +7 -0
- package/dist/cdc/transport/index.js.map +1 -0
- package/dist/cdc/transport/sse.d.ts +120 -0
- package/dist/cdc/transport/sse.d.ts.map +1 -0
- package/dist/cdc/transport/sse.js +590 -0
- package/dist/cdc/transport/sse.js.map +1 -0
- package/dist/cdc/transport/websocket.d.ts +130 -0
- package/dist/cdc/transport/websocket.d.ts.map +1 -0
- package/dist/cdc/transport/websocket.js +688 -0
- package/dist/cdc/transport/websocket.js.map +1 -0
- package/dist/cdc/types.d.ts +306 -0
- package/dist/cdc/types.d.ts.map +1 -0
- package/dist/cdc/types.js +8 -0
- package/dist/cdc/types.js.map +1 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +25 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/memory.d.ts +139 -0
- package/dist/config/memory.d.ts.map +1 -0
- package/dist/config/memory.js +157 -0
- package/dist/config/memory.js.map +1 -0
- package/dist/config/storage.d.ts +157 -0
- package/dist/config/storage.d.ts.map +1 -0
- package/dist/config/storage.js +178 -0
- package/dist/config/storage.js.map +1 -0
- package/dist/config/streaming.d.ts +117 -0
- package/dist/config/streaming.d.ts.map +1 -0
- package/dist/config/streaming.js +132 -0
- package/dist/config/streaming.js.map +1 -0
- package/dist/config/timeouts.d.ts +168 -0
- package/dist/config/timeouts.d.ts.map +1 -0
- package/dist/config/timeouts.js +192 -0
- package/dist/config/timeouts.js.map +1 -0
- package/dist/extensions/config.d.ts +89 -0
- package/dist/extensions/config.d.ts.map +1 -0
- package/dist/extensions/config.js +216 -0
- package/dist/extensions/config.js.map +1 -0
- package/dist/extensions/geo.d.ts +452 -0
- package/dist/extensions/geo.d.ts.map +1 -0
- package/dist/extensions/geo.js +583 -0
- package/dist/extensions/geo.js.map +1 -0
- package/dist/extensions/index.d.ts +167 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +99 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +226 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +456 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/pgmq-lite.d.ts +330 -0
- package/dist/extensions/pgmq-lite.d.ts.map +1 -0
- package/dist/extensions/pgmq-lite.js +648 -0
- package/dist/extensions/pgmq-lite.js.map +1 -0
- package/dist/extensions/plugins.d.ts +260 -0
- package/dist/extensions/plugins.d.ts.map +1 -0
- package/dist/extensions/plugins.js +535 -0
- package/dist/extensions/plugins.js.map +1 -0
- package/dist/extensions/registry.d.ts +93 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +182 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/vector.d.ts +106 -0
- package/dist/extensions/vector.d.ts.map +1 -0
- package/dist/extensions/vector.js +129 -0
- package/dist/extensions/vector.js.map +1 -0
- package/dist/iceberg/analytics.d.ts +279 -0
- package/dist/iceberg/analytics.d.ts.map +1 -0
- package/dist/iceberg/analytics.js +448 -0
- package/dist/iceberg/analytics.js.map +1 -0
- package/dist/iceberg/catalog-api.d.ts +39 -0
- package/dist/iceberg/catalog-api.d.ts.map +1 -0
- package/dist/iceberg/catalog-api.js +388 -0
- package/dist/iceberg/catalog-api.js.map +1 -0
- package/dist/iceberg/catalog.d.ts +401 -0
- package/dist/iceberg/catalog.d.ts.map +1 -0
- package/dist/iceberg/catalog.js +677 -0
- package/dist/iceberg/catalog.js.map +1 -0
- package/dist/iceberg/duckdb-wasm.d.ts +447 -0
- package/dist/iceberg/duckdb-wasm.d.ts.map +1 -0
- package/dist/iceberg/duckdb-wasm.js +600 -0
- package/dist/iceberg/duckdb-wasm.js.map +1 -0
- package/dist/iceberg/index.d.ts +92 -0
- package/dist/iceberg/index.d.ts.map +1 -0
- package/dist/iceberg/index.js +119 -0
- package/dist/iceberg/index.js.map +1 -0
- package/dist/iceberg/metadata.d.ts +214 -0
- package/dist/iceberg/metadata.d.ts.map +1 -0
- package/dist/iceberg/metadata.js +535 -0
- package/dist/iceberg/metadata.js.map +1 -0
- package/dist/iceberg/optimizer.d.ts +296 -0
- package/dist/iceberg/optimizer.d.ts.map +1 -0
- package/dist/iceberg/optimizer.js +889 -0
- package/dist/iceberg/optimizer.js.map +1 -0
- package/dist/iceberg/parquet.d.ts +447 -0
- package/dist/iceberg/parquet.d.ts.map +1 -0
- package/dist/iceberg/parquet.js +1225 -0
- package/dist/iceberg/parquet.js.map +1 -0
- package/dist/iceberg/r2-organization.d.ts +422 -0
- package/dist/iceberg/r2-organization.d.ts.map +1 -0
- package/dist/iceberg/r2-organization.js +672 -0
- package/dist/iceberg/r2-organization.js.map +1 -0
- package/dist/iceberg/scheduler-do-example.d.ts +158 -0
- package/dist/iceberg/scheduler-do-example.d.ts.map +1 -0
- package/dist/iceberg/scheduler-do-example.js +261 -0
- package/dist/iceberg/scheduler-do-example.js.map +1 -0
- package/dist/iceberg/scheduler.d.ts +434 -0
- package/dist/iceberg/scheduler.d.ts.map +1 -0
- package/dist/iceberg/scheduler.js +818 -0
- package/dist/iceberg/scheduler.js.map +1 -0
- package/dist/iceberg/schema.d.ts +149 -0
- package/dist/iceberg/schema.d.ts.map +1 -0
- package/dist/iceberg/schema.js +525 -0
- package/dist/iceberg/schema.js.map +1 -0
- package/dist/iceberg/snapshot-manager.d.ts +406 -0
- package/dist/iceberg/snapshot-manager.d.ts.map +1 -0
- package/dist/iceberg/snapshot-manager.js +934 -0
- package/dist/iceberg/snapshot-manager.js.map +1 -0
- package/dist/iceberg/sql-router.d.ts +194 -0
- package/dist/iceberg/sql-router.d.ts.map +1 -0
- package/dist/iceberg/sql-router.js +180 -0
- package/dist/iceberg/sql-router.js.map +1 -0
- package/dist/iceberg/test-fixtures.d.ts +151 -0
- package/dist/iceberg/test-fixtures.d.ts.map +1 -0
- package/dist/iceberg/test-fixtures.js +446 -0
- package/dist/iceberg/test-fixtures.js.map +1 -0
- package/dist/iceberg/time-travel-api.d.ts +102 -0
- package/dist/iceberg/time-travel-api.d.ts.map +1 -0
- package/dist/iceberg/time-travel-api.js +437 -0
- package/dist/iceberg/time-travel-api.js.map +1 -0
- package/dist/iceberg/time-travel.d.ts +293 -0
- package/dist/iceberg/time-travel.d.ts.map +1 -0
- package/dist/iceberg/time-travel.js +689 -0
- package/dist/iceberg/time-travel.js.map +1 -0
- package/dist/iceberg/transformer.d.ts +356 -0
- package/dist/iceberg/transformer.d.ts.map +1 -0
- package/dist/iceberg/transformer.js +770 -0
- package/dist/iceberg/transformer.js.map +1 -0
- package/dist/iceberg/types.d.ts +318 -0
- package/dist/iceberg/types.d.ts.map +1 -0
- package/dist/iceberg/types.js +9 -0
- package/dist/iceberg/types.js.map +1 -0
- package/dist/iceberg/writer.d.ts +144 -0
- package/dist/iceberg/writer.d.ts.map +1 -0
- package/dist/iceberg/writer.js +452 -0
- package/dist/iceberg/writer.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/lineage/index.d.ts +11 -0
- package/dist/lineage/index.d.ts.map +1 -0
- package/dist/lineage/index.js +11 -0
- package/dist/lineage/index.js.map +1 -0
- package/dist/lineage/integration.d.ts +134 -0
- package/dist/lineage/integration.d.ts.map +1 -0
- package/dist/lineage/integration.js +258 -0
- package/dist/lineage/integration.js.map +1 -0
- package/dist/lineage/tracker.d.ts +189 -0
- package/dist/lineage/tracker.d.ts.map +1 -0
- package/dist/lineage/tracker.js +1352 -0
- package/dist/lineage/tracker.js.map +1 -0
- package/dist/lineage/types.d.ts +318 -0
- package/dist/lineage/types.d.ts.map +1 -0
- package/dist/lineage/types.js +9 -0
- package/dist/lineage/types.js.map +1 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +16 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +397 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +507 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/migration-tooling/external-migration.d.ts +601 -0
- package/dist/migration-tooling/external-migration.d.ts.map +1 -0
- package/dist/migration-tooling/external-migration.js +1612 -0
- package/dist/migration-tooling/external-migration.js.map +1 -0
- package/dist/migration-tooling/index.d.ts +19 -0
- package/dist/migration-tooling/index.d.ts.map +1 -0
- package/dist/migration-tooling/index.js +19 -0
- package/dist/migration-tooling/index.js.map +1 -0
- package/dist/migrations/auto-migrator.d.ts +289 -0
- package/dist/migrations/auto-migrator.d.ts.map +1 -0
- package/dist/migrations/auto-migrator.js +396 -0
- package/dist/migrations/auto-migrator.js.map +1 -0
- package/dist/migrations/bulk-orchestrator.d.ts +403 -0
- package/dist/migrations/bulk-orchestrator.d.ts.map +1 -0
- package/dist/migrations/bulk-orchestrator.js +646 -0
- package/dist/migrations/bulk-orchestrator.js.map +1 -0
- package/dist/migrations/compatibility.d.ts +216 -0
- package/dist/migrations/compatibility.d.ts.map +1 -0
- package/dist/migrations/compatibility.js +651 -0
- package/dist/migrations/compatibility.js.map +1 -0
- package/dist/migrations/do-migrations.d.ts +101 -0
- package/dist/migrations/do-migrations.d.ts.map +1 -0
- package/dist/migrations/do-migrations.js +1060 -0
- package/dist/migrations/do-migrations.js.map +1 -0
- package/dist/migrations/do-migrations.types.d.ts +550 -0
- package/dist/migrations/do-migrations.types.d.ts.map +1 -0
- package/dist/migrations/do-migrations.types.js +15 -0
- package/dist/migrations/do-migrations.types.js.map +1 -0
- package/dist/migrations/drizzle-compat.d.ts +163 -0
- package/dist/migrations/drizzle-compat.d.ts.map +1 -0
- package/dist/migrations/drizzle-compat.js +273 -0
- package/dist/migrations/drizzle-compat.js.map +1 -0
- package/dist/migrations/index.d.ts +109 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration-api.d.ts +161 -0
- package/dist/migrations/migration-api.d.ts.map +1 -0
- package/dist/migrations/migration-api.js +499 -0
- package/dist/migrations/migration-api.js.map +1 -0
- package/dist/migrations/progress-tracker-do.d.ts +195 -0
- package/dist/migrations/progress-tracker-do.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-do.js +339 -0
- package/dist/migrations/progress-tracker-do.js.map +1 -0
- package/dist/migrations/progress-tracker-kv.d.ts +103 -0
- package/dist/migrations/progress-tracker-kv.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-kv.js +231 -0
- package/dist/migrations/progress-tracker-kv.js.map +1 -0
- package/dist/migrations/progress-tracker.d.ts +320 -0
- package/dist/migrations/progress-tracker.d.ts.map +1 -0
- package/dist/migrations/progress-tracker.js +443 -0
- package/dist/migrations/progress-tracker.js.map +1 -0
- package/dist/migrations/registry.d.ts +231 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +376 -0
- package/dist/migrations/registry.js.map +1 -0
- package/dist/migrations/runner.d.ts +197 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +1167 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/migrations/schema-generator.d.ts +111 -0
- package/dist/migrations/schema-generator.d.ts.map +1 -0
- package/dist/migrations/schema-generator.js +335 -0
- package/dist/migrations/schema-generator.js.map +1 -0
- package/dist/migrations/testing.d.ts +321 -0
- package/dist/migrations/testing.d.ts.map +1 -0
- package/dist/migrations/testing.js +645 -0
- package/dist/migrations/testing.js.map +1 -0
- package/dist/migrations/types.d.ts +503 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +11 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/migrations/validator.d.ts +215 -0
- package/dist/migrations/validator.d.ts.map +1 -0
- package/dist/migrations/validator.js +494 -0
- package/dist/migrations/validator.js.map +1 -0
- package/dist/observability/alerting.d.ts +116 -0
- package/dist/observability/alerting.d.ts.map +1 -0
- package/dist/observability/alerting.js +353 -0
- package/dist/observability/alerting.js.map +1 -0
- package/dist/observability/analytics-engine.d.ts +357 -0
- package/dist/observability/analytics-engine.d.ts.map +1 -0
- package/dist/observability/analytics-engine.js +430 -0
- package/dist/observability/analytics-engine.js.map +1 -0
- package/dist/observability/cost-metrics.d.ts +269 -0
- package/dist/observability/cost-metrics.d.ts.map +1 -0
- package/dist/observability/cost-metrics.js +560 -0
- package/dist/observability/cost-metrics.js.map +1 -0
- package/dist/observability/cross-do-tracing.d.ts +305 -0
- package/dist/observability/cross-do-tracing.d.ts.map +1 -0
- package/dist/observability/cross-do-tracing.js +431 -0
- package/dist/observability/cross-do-tracing.js.map +1 -0
- package/dist/observability/error-rate-collector.d.ts +163 -0
- package/dist/observability/error-rate-collector.d.ts.map +1 -0
- package/dist/observability/error-rate-collector.js +306 -0
- package/dist/observability/error-rate-collector.js.map +1 -0
- package/dist/observability/exporters.d.ts +231 -0
- package/dist/observability/exporters.d.ts.map +1 -0
- package/dist/observability/exporters.js +479 -0
- package/dist/observability/exporters.js.map +1 -0
- package/dist/observability/health-check.d.ts +106 -0
- package/dist/observability/health-check.d.ts.map +1 -0
- package/dist/observability/health-check.js +243 -0
- package/dist/observability/health-check.js.map +1 -0
- package/dist/observability/index.d.ts +297 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +455 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/instrumentation.d.ts +222 -0
- package/dist/observability/instrumentation.d.ts.map +1 -0
- package/dist/observability/instrumentation.js +532 -0
- package/dist/observability/instrumentation.js.map +1 -0
- package/dist/observability/memory-metrics.d.ts +227 -0
- package/dist/observability/memory-metrics.d.ts.map +1 -0
- package/dist/observability/memory-metrics.js +688 -0
- package/dist/observability/memory-metrics.js.map +1 -0
- package/dist/observability/metrics-endpoint.d.ts +91 -0
- package/dist/observability/metrics-endpoint.d.ts.map +1 -0
- package/dist/observability/metrics-endpoint.js +246 -0
- package/dist/observability/metrics-endpoint.js.map +1 -0
- package/dist/observability/metrics.d.ts +88 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +253 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/observability-features.d.ts +488 -0
- package/dist/observability/observability-features.d.ts.map +1 -0
- package/dist/observability/observability-features.js +773 -0
- package/dist/observability/observability-features.js.map +1 -0
- package/dist/observability/prometheus.d.ts +39 -0
- package/dist/observability/prometheus.d.ts.map +1 -0
- package/dist/observability/prometheus.js +120 -0
- package/dist/observability/prometheus.js.map +1 -0
- package/dist/observability/propagation.d.ts +126 -0
- package/dist/observability/propagation.d.ts.map +1 -0
- package/dist/observability/propagation.js +234 -0
- package/dist/observability/propagation.js.map +1 -0
- package/dist/observability/query-latency.d.ts +243 -0
- package/dist/observability/query-latency.d.ts.map +1 -0
- package/dist/observability/query-latency.js +292 -0
- package/dist/observability/query-latency.js.map +1 -0
- package/dist/observability/query-performance.d.ts +169 -0
- package/dist/observability/query-performance.d.ts.map +1 -0
- package/dist/observability/query-performance.js +290 -0
- package/dist/observability/query-performance.js.map +1 -0
- package/dist/observability/storage-tier-metrics.d.ts +174 -0
- package/dist/observability/storage-tier-metrics.d.ts.map +1 -0
- package/dist/observability/storage-tier-metrics.js +306 -0
- package/dist/observability/storage-tier-metrics.js.map +1 -0
- package/dist/observability/tier-cost-optimizer.d.ts +155 -0
- package/dist/observability/tier-cost-optimizer.d.ts.map +1 -0
- package/dist/observability/tier-cost-optimizer.js +536 -0
- package/dist/observability/tier-cost-optimizer.js.map +1 -0
- package/dist/observability/tracer.d.ts +149 -0
- package/dist/observability/tracer.d.ts.map +1 -0
- package/dist/observability/tracer.js +435 -0
- package/dist/observability/tracer.js.map +1 -0
- package/dist/observability/types.d.ts +402 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +103 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/pglite/workers-pglite.d.ts +138 -0
- package/dist/pglite/workers-pglite.d.ts.map +1 -0
- package/dist/pglite/workers-pglite.js +143 -0
- package/dist/pglite/workers-pglite.js.map +1 -0
- package/dist/pglite-assets/pglite.data +0 -0
- package/dist/pglite-assets/pglite.wasm +0 -0
- package/dist/playground/index.d.ts +52 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +55 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/keyboard-shortcuts.d.ts +116 -0
- package/dist/playground/keyboard-shortcuts.d.ts.map +1 -0
- package/dist/playground/keyboard-shortcuts.js +588 -0
- package/dist/playground/keyboard-shortcuts.js.map +1 -0
- package/dist/playground/playground.d.ts +82 -0
- package/dist/playground/playground.d.ts.map +1 -0
- package/dist/playground/playground.js +271 -0
- package/dist/playground/playground.js.map +1 -0
- package/dist/playground/query-executor.d.ts +115 -0
- package/dist/playground/query-executor.d.ts.map +1 -0
- package/dist/playground/query-executor.js +558 -0
- package/dist/playground/query-executor.js.map +1 -0
- package/dist/playground/query-history.d.ts +92 -0
- package/dist/playground/query-history.d.ts.map +1 -0
- package/dist/playground/query-history.js +259 -0
- package/dist/playground/query-history.js.map +1 -0
- package/dist/playground/result-formatter.d.ts +59 -0
- package/dist/playground/result-formatter.d.ts.map +1 -0
- package/dist/playground/result-formatter.js +341 -0
- package/dist/playground/result-formatter.js.map +1 -0
- package/dist/playground/sample-datasets.d.ts +77 -0
- package/dist/playground/sample-datasets.d.ts.map +1 -0
- package/dist/playground/sample-datasets.js +641 -0
- package/dist/playground/sample-datasets.js.map +1 -0
- package/dist/playground/sample-queries.d.ts +73 -0
- package/dist/playground/sample-queries.d.ts.map +1 -0
- package/dist/playground/sample-queries.js +1095 -0
- package/dist/playground/sample-queries.js.map +1 -0
- package/dist/playground/schema-explorer.d.ts +55 -0
- package/dist/playground/schema-explorer.d.ts.map +1 -0
- package/dist/playground/schema-explorer.js +473 -0
- package/dist/playground/schema-explorer.js.map +1 -0
- package/dist/playground/types.d.ts +430 -0
- package/dist/playground/types.d.ts.map +1 -0
- package/dist/playground/types.js +10 -0
- package/dist/playground/types.js.map +1 -0
- package/dist/readonly/cache-reader.d.ts +145 -0
- package/dist/readonly/cache-reader.d.ts.map +1 -0
- package/dist/readonly/cache-reader.js +198 -0
- package/dist/readonly/cache-reader.js.map +1 -0
- package/dist/readonly/config.d.ts +74 -0
- package/dist/readonly/config.d.ts.map +1 -0
- package/dist/readonly/config.js +67 -0
- package/dist/readonly/config.js.map +1 -0
- package/dist/readonly/index.d.ts +22 -0
- package/dist/readonly/index.d.ts.map +1 -0
- package/dist/readonly/index.js +17 -0
- package/dist/readonly/index.js.map +1 -0
- package/dist/readonly/pglite-wrapper.d.ts +82 -0
- package/dist/readonly/pglite-wrapper.d.ts.map +1 -0
- package/dist/readonly/pglite-wrapper.js +123 -0
- package/dist/readonly/pglite-wrapper.js.map +1 -0
- package/dist/readonly/worker.d.ts +142 -0
- package/dist/readonly/worker.d.ts.map +1 -0
- package/dist/readonly/worker.js +187 -0
- package/dist/readonly/worker.js.map +1 -0
- package/dist/readonly/write-blocker.d.ts +47 -0
- package/dist/readonly/write-blocker.d.ts.map +1 -0
- package/dist/readonly/write-blocker.js +136 -0
- package/dist/readonly/write-blocker.js.map +1 -0
- package/dist/recovery/disaster-recovery.d.ts +326 -0
- package/dist/recovery/disaster-recovery.d.ts.map +1 -0
- package/dist/recovery/disaster-recovery.js +799 -0
- package/dist/recovery/disaster-recovery.js.map +1 -0
- package/dist/recovery/index.d.ts +12 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +12 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/recovery/parquet-parser.d.ts +321 -0
- package/dist/recovery/parquet-parser.d.ts.map +1 -0
- package/dist/recovery/parquet-parser.js +797 -0
- package/dist/recovery/parquet-parser.js.map +1 -0
- package/dist/retention/index.d.ts +50 -0
- package/dist/retention/index.d.ts.map +1 -0
- package/dist/retention/index.js +50 -0
- package/dist/retention/index.js.map +1 -0
- package/dist/retention/policy.d.ts +344 -0
- package/dist/retention/policy.d.ts.map +1 -0
- package/dist/retention/policy.js +472 -0
- package/dist/retention/policy.js.map +1 -0
- package/dist/retention/purger.d.ts +187 -0
- package/dist/retention/purger.d.ts.map +1 -0
- package/dist/retention/purger.js +411 -0
- package/dist/retention/purger.js.map +1 -0
- package/dist/rls/auth-integration.d.ts +280 -0
- package/dist/rls/auth-integration.d.ts.map +1 -0
- package/dist/rls/auth-integration.js +399 -0
- package/dist/rls/auth-integration.js.map +1 -0
- package/dist/rls/generator.d.ts +249 -0
- package/dist/rls/generator.d.ts.map +1 -0
- package/dist/rls/generator.js +495 -0
- package/dist/rls/generator.js.map +1 -0
- package/dist/rls/index.d.ts +26 -0
- package/dist/rls/index.d.ts.map +1 -0
- package/dist/rls/index.js +58 -0
- package/dist/rls/index.js.map +1 -0
- package/dist/rls/policy.d.ts +116 -0
- package/dist/rls/policy.d.ts.map +1 -0
- package/dist/rls/policy.js +77 -0
- package/dist/rls/policy.js.map +1 -0
- package/dist/rls/validator.d.ts +155 -0
- package/dist/rls/validator.d.ts.map +1 -0
- package/dist/rls/validator.js +792 -0
- package/dist/rls/validator.js.map +1 -0
- package/dist/routing/adaptive-router.d.ts +317 -0
- package/dist/routing/adaptive-router.d.ts.map +1 -0
- package/dist/routing/adaptive-router.js +554 -0
- package/dist/routing/adaptive-router.js.map +1 -0
- package/dist/routing/circuit-breaker.d.ts +339 -0
- package/dist/routing/circuit-breaker.d.ts.map +1 -0
- package/dist/routing/circuit-breaker.js +620 -0
- package/dist/routing/circuit-breaker.js.map +1 -0
- package/dist/routing/cost-metrics.d.ts +133 -0
- package/dist/routing/cost-metrics.d.ts.map +1 -0
- package/dist/routing/cost-metrics.js +259 -0
- package/dist/routing/cost-metrics.js.map +1 -0
- package/dist/routing/do-connection-pool.d.ts +243 -0
- package/dist/routing/do-connection-pool.d.ts.map +1 -0
- package/dist/routing/do-connection-pool.js +572 -0
- package/dist/routing/do-connection-pool.js.map +1 -0
- package/dist/routing/index.d.ts +59 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +59 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/query-complexity-estimator.d.ts +73 -0
- package/dist/routing/query-complexity-estimator.d.ts.map +1 -0
- package/dist/routing/query-complexity-estimator.js +327 -0
- package/dist/routing/query-complexity-estimator.js.map +1 -0
- package/dist/routing/request-coalescing.d.ts +178 -0
- package/dist/routing/request-coalescing.d.ts.map +1 -0
- package/dist/routing/request-coalescing.js +325 -0
- package/dist/routing/request-coalescing.js.map +1 -0
- package/dist/routing/runtime-router.d.ts +107 -0
- package/dist/routing/runtime-router.d.ts.map +1 -0
- package/dist/routing/runtime-router.js +246 -0
- package/dist/routing/runtime-router.js.map +1 -0
- package/dist/routing/tenant-router.d.ts +848 -0
- package/dist/routing/tenant-router.d.ts.map +1 -0
- package/dist/routing/tenant-router.js +1056 -0
- package/dist/routing/tenant-router.js.map +1 -0
- package/dist/routing/websocket-pool.d.ts +119 -0
- package/dist/routing/websocket-pool.d.ts.map +1 -0
- package/dist/routing/websocket-pool.js +436 -0
- package/dist/routing/websocket-pool.js.map +1 -0
- package/dist/storage/cache-layer.d.ts +159 -0
- package/dist/storage/cache-layer.d.ts.map +1 -0
- package/dist/storage/cache-layer.js +245 -0
- package/dist/storage/cache-layer.js.map +1 -0
- package/dist/storage/cost-aware-tiering.d.ts +258 -0
- package/dist/storage/cost-aware-tiering.d.ts.map +1 -0
- package/dist/storage/cost-aware-tiering.js +526 -0
- package/dist/storage/cost-aware-tiering.js.map +1 -0
- package/dist/storage/index.d.ts +87 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +78 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/interfaces.d.ts +856 -0
- package/dist/storage/interfaces.d.ts.map +1 -0
- package/dist/storage/interfaces.js +69 -0
- package/dist/storage/interfaces.js.map +1 -0
- package/dist/storage/r2-layer.d.ts +226 -0
- package/dist/storage/r2-layer.d.ts.map +1 -0
- package/dist/storage/r2-layer.js +307 -0
- package/dist/storage/r2-layer.js.map +1 -0
- package/dist/storage/r2-overflow.d.ts +344 -0
- package/dist/storage/r2-overflow.d.ts.map +1 -0
- package/dist/storage/r2-overflow.js +730 -0
- package/dist/storage/r2-overflow.js.map +1 -0
- package/dist/storage/r2-page-vfs.d.ts +374 -0
- package/dist/storage/r2-page-vfs.d.ts.map +1 -0
- package/dist/storage/r2-page-vfs.js +754 -0
- package/dist/storage/r2-page-vfs.js.map +1 -0
- package/dist/storage/swr-cache.d.ts +181 -0
- package/dist/storage/swr-cache.d.ts.map +1 -0
- package/dist/storage/swr-cache.js +295 -0
- package/dist/storage/swr-cache.js.map +1 -0
- package/dist/storage/tiered-orchestrator.d.ts +951 -0
- package/dist/storage/tiered-orchestrator.d.ts.map +1 -0
- package/dist/storage/tiered-orchestrator.js +1731 -0
- package/dist/storage/tiered-orchestrator.js.map +1 -0
- package/dist/storage/tiered-vfs-swr.d.ts +279 -0
- package/dist/storage/tiered-vfs-swr.d.ts.map +1 -0
- package/dist/storage/tiered-vfs-swr.js +584 -0
- package/dist/storage/tiered-vfs-swr.js.map +1 -0
- package/dist/storage/tiered-vfs.d.ts +405 -0
- package/dist/storage/tiered-vfs.d.ts.map +1 -0
- package/dist/storage/tiered-vfs.js +833 -0
- package/dist/storage/tiered-vfs.js.map +1 -0
- package/dist/streaming/backpressure-controller.d.ts +173 -0
- package/dist/streaming/backpressure-controller.d.ts.map +1 -0
- package/dist/streaming/backpressure-controller.js +344 -0
- package/dist/streaming/backpressure-controller.js.map +1 -0
- package/dist/streaming/buffer-pool.d.ts +241 -0
- package/dist/streaming/buffer-pool.d.ts.map +1 -0
- package/dist/streaming/buffer-pool.js +381 -0
- package/dist/streaming/buffer-pool.js.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts +272 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.js +408 -0
- package/dist/streaming/cdc-iceberg-connector.js.map +1 -0
- package/dist/streaming/index.d.ts +111 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +128 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/live-cdc-stream.d.ts +400 -0
- package/dist/streaming/live-cdc-stream.d.ts.map +1 -0
- package/dist/streaming/live-cdc-stream.js +703 -0
- package/dist/streaming/live-cdc-stream.js.map +1 -0
- package/dist/streaming/memory-bounded-stream.d.ts +207 -0
- package/dist/streaming/memory-bounded-stream.d.ts.map +1 -0
- package/dist/streaming/memory-bounded-stream.js +340 -0
- package/dist/streaming/memory-bounded-stream.js.map +1 -0
- package/dist/streaming/query-streamer.d.ts +379 -0
- package/dist/streaming/query-streamer.d.ts.map +1 -0
- package/dist/streaming/query-streamer.js +495 -0
- package/dist/streaming/query-streamer.js.map +1 -0
- package/dist/streaming/response-streaming.d.ts +203 -0
- package/dist/streaming/response-streaming.d.ts.map +1 -0
- package/dist/streaming/response-streaming.js +449 -0
- package/dist/streaming/response-streaming.js.map +1 -0
- package/dist/types/branded.d.ts +859 -0
- package/dist/types/branded.d.ts.map +1 -0
- package/dist/types/branded.js +891 -0
- package/dist/types/branded.js.map +1 -0
- package/dist/types/utilities.d.ts +757 -0
- package/dist/types/utilities.d.ts.map +1 -0
- package/dist/types/utilities.js +447 -0
- package/dist/types/utilities.js.map +1 -0
- package/dist/wal/replay-engine.d.ts +344 -0
- package/dist/wal/replay-engine.d.ts.map +1 -0
- package/dist/wal/replay-engine.js +975 -0
- package/dist/wal/replay-engine.js.map +1 -0
- package/dist/worker/__mocks__/capnweb.d.ts +13 -0
- package/dist/worker/__mocks__/capnweb.d.ts.map +1 -0
- package/dist/worker/__mocks__/capnweb.js +15 -0
- package/dist/worker/__mocks__/capnweb.js.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts +31 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.js +33 -0
- package/dist/worker/__mocks__/cloudflare-workers.js.map +1 -0
- package/dist/worker/__mocks__/pglite.data.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.data.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.data.js +20 -0
- package/dist/worker/__mocks__/pglite.data.js.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.js +30 -0
- package/dist/worker/__mocks__/pglite.wasm.js.map +1 -0
- package/dist/worker/auth-rate-limiter.d.ts +270 -0
- package/dist/worker/auth-rate-limiter.d.ts.map +1 -0
- package/dist/worker/auth-rate-limiter.js +332 -0
- package/dist/worker/auth-rate-limiter.js.map +1 -0
- package/dist/worker/auth.d.ts +345 -0
- package/dist/worker/auth.d.ts.map +1 -0
- package/dist/worker/auth.js +837 -0
- package/dist/worker/auth.js.map +1 -0
- package/dist/worker/cdc-backpressure.d.ts +338 -0
- package/dist/worker/cdc-backpressure.d.ts.map +1 -0
- package/dist/worker/cdc-backpressure.js +619 -0
- package/dist/worker/cdc-backpressure.js.map +1 -0
- package/dist/worker/cdc-sse.d.ts +277 -0
- package/dist/worker/cdc-sse.d.ts.map +1 -0
- package/dist/worker/cdc-sse.js +528 -0
- package/dist/worker/cdc-sse.js.map +1 -0
- package/dist/worker/cdc-websocket.d.ts +252 -0
- package/dist/worker/cdc-websocket.d.ts.map +1 -0
- package/dist/worker/cdc-websocket.js +940 -0
- package/dist/worker/cdc-websocket.js.map +1 -0
- package/dist/worker/cdc.d.ts +95 -0
- package/dist/worker/cdc.d.ts.map +1 -0
- package/dist/worker/cdc.js +211 -0
- package/dist/worker/cdc.js.map +1 -0
- package/dist/worker/concerns/auth-concern.d.ts +50 -0
- package/dist/worker/concerns/auth-concern.d.ts.map +1 -0
- package/dist/worker/concerns/auth-concern.js +131 -0
- package/dist/worker/concerns/auth-concern.js.map +1 -0
- package/dist/worker/concerns/cdc-concern.d.ts +99 -0
- package/dist/worker/concerns/cdc-concern.d.ts.map +1 -0
- package/dist/worker/concerns/cdc-concern.js +137 -0
- package/dist/worker/concerns/cdc-concern.js.map +1 -0
- package/dist/worker/concerns/index.d.ts +22 -0
- package/dist/worker/concerns/index.d.ts.map +1 -0
- package/dist/worker/concerns/index.js +13 -0
- package/dist/worker/concerns/index.js.map +1 -0
- package/dist/worker/concerns/query-execution-concern.d.ts +104 -0
- package/dist/worker/concerns/query-execution-concern.d.ts.map +1 -0
- package/dist/worker/concerns/query-execution-concern.js +95 -0
- package/dist/worker/concerns/query-execution-concern.js.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts +78 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.js +240 -0
- package/dist/worker/concerns/storage-orchestration-concern.js.map +1 -0
- package/dist/worker/do-auth-manager.d.ts +108 -0
- package/dist/worker/do-auth-manager.d.ts.map +1 -0
- package/dist/worker/do-auth-manager.js +212 -0
- package/dist/worker/do-auth-manager.js.map +1 -0
- package/dist/worker/do-pglite-manager.d.ts +137 -0
- package/dist/worker/do-pglite-manager.d.ts.map +1 -0
- package/dist/worker/do-pglite-manager.js +228 -0
- package/dist/worker/do-pglite-manager.js.map +1 -0
- package/dist/worker/do.d.ts +556 -0
- package/dist/worker/do.d.ts.map +1 -0
- package/dist/worker/do.js +1441 -0
- package/dist/worker/do.js.map +1 -0
- package/dist/worker/entry.d.ts +23 -0
- package/dist/worker/entry.d.ts.map +1 -0
- package/dist/worker/entry.js +362 -0
- package/dist/worker/entry.js.map +1 -0
- package/dist/worker/errors.d.ts +106 -0
- package/dist/worker/errors.d.ts.map +1 -0
- package/dist/worker/errors.js +178 -0
- package/dist/worker/errors.js.map +1 -0
- package/dist/worker/health-check-manager.d.ts +141 -0
- package/dist/worker/health-check-manager.d.ts.map +1 -0
- package/dist/worker/health-check-manager.js +145 -0
- package/dist/worker/health-check-manager.js.map +1 -0
- package/dist/worker/index.d.ts +60 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +67 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/memory-pressure.d.ts +892 -0
- package/dist/worker/memory-pressure.d.ts.map +1 -0
- package/dist/worker/memory-pressure.js +1990 -0
- package/dist/worker/memory-pressure.js.map +1 -0
- package/dist/worker/migration-manager.d.ts +153 -0
- package/dist/worker/migration-manager.d.ts.map +1 -0
- package/dist/worker/migration-manager.js +461 -0
- package/dist/worker/migration-manager.js.map +1 -0
- package/dist/worker/plugin-manager.d.ts +147 -0
- package/dist/worker/plugin-manager.d.ts.map +1 -0
- package/dist/worker/plugin-manager.js +408 -0
- package/dist/worker/plugin-manager.js.map +1 -0
- package/dist/worker/proxy.d.ts +330 -0
- package/dist/worker/proxy.d.ts.map +1 -0
- package/dist/worker/proxy.js +504 -0
- package/dist/worker/proxy.js.map +1 -0
- package/dist/worker/query-execution-manager.d.ts +107 -0
- package/dist/worker/query-execution-manager.d.ts.map +1 -0
- package/dist/worker/query-execution-manager.js +155 -0
- package/dist/worker/query-execution-manager.js.map +1 -0
- package/dist/worker/query-executor.d.ts +163 -0
- package/dist/worker/query-executor.d.ts.map +1 -0
- package/dist/worker/query-executor.js +413 -0
- package/dist/worker/query-executor.js.map +1 -0
- package/dist/worker/query-stats-manager.d.ts +117 -0
- package/dist/worker/query-stats-manager.d.ts.map +1 -0
- package/dist/worker/query-stats-manager.js +162 -0
- package/dist/worker/query-stats-manager.js.map +1 -0
- package/dist/worker/result-handler.d.ts +192 -0
- package/dist/worker/result-handler.d.ts.map +1 -0
- package/dist/worker/result-handler.js +346 -0
- package/dist/worker/result-handler.js.map +1 -0
- package/dist/worker/routes.d.ts +135 -0
- package/dist/worker/routes.d.ts.map +1 -0
- package/dist/worker/routes.js +460 -0
- package/dist/worker/routes.js.map +1 -0
- package/dist/worker/rpc-methods-manager.d.ts +142 -0
- package/dist/worker/rpc-methods-manager.d.ts.map +1 -0
- package/dist/worker/rpc-methods-manager.js +195 -0
- package/dist/worker/rpc-methods-manager.js.map +1 -0
- package/dist/worker/rpc.d.ts +259 -0
- package/dist/worker/rpc.d.ts.map +1 -0
- package/dist/worker/rpc.js +398 -0
- package/dist/worker/rpc.js.map +1 -0
- package/dist/worker/schema-version.d.ts +209 -0
- package/dist/worker/schema-version.d.ts.map +1 -0
- package/dist/worker/schema-version.js +450 -0
- package/dist/worker/schema-version.js.map +1 -0
- package/dist/worker/session-manager.d.ts +282 -0
- package/dist/worker/session-manager.d.ts.map +1 -0
- package/dist/worker/session-manager.js +523 -0
- package/dist/worker/session-manager.js.map +1 -0
- package/dist/worker/shutdown-manager.d.ts +188 -0
- package/dist/worker/shutdown-manager.d.ts.map +1 -0
- package/dist/worker/shutdown-manager.js +347 -0
- package/dist/worker/shutdown-manager.js.map +1 -0
- package/dist/worker/sql-transform.d.ts +61 -0
- package/dist/worker/sql-transform.d.ts.map +1 -0
- package/dist/worker/sql-transform.js +312 -0
- package/dist/worker/sql-transform.js.map +1 -0
- package/dist/worker/types.d.ts +738 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +6 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/user-routes.d.ts +76 -0
- package/dist/worker/user-routes.d.ts.map +1 -0
- package/dist/worker/user-routes.js +188 -0
- package/dist/worker/user-routes.js.map +1 -0
- package/dist/worker/wal-facade.d.ts +138 -0
- package/dist/worker/wal-facade.d.ts.map +1 -0
- package/dist/worker/wal-facade.js +184 -0
- package/dist/worker/wal-facade.js.map +1 -0
- package/dist/worker/wal-r2.d.ts +271 -0
- package/dist/worker/wal-r2.d.ts.map +1 -0
- package/dist/worker/wal-r2.js +689 -0
- package/dist/worker/wal-r2.js.map +1 -0
- package/dist/worker/wal-replay.d.ts +361 -0
- package/dist/worker/wal-replay.d.ts.map +1 -0
- package/dist/worker/wal-replay.js +628 -0
- package/dist/worker/wal-replay.js.map +1 -0
- package/dist/worker/wal-retention.d.ts +389 -0
- package/dist/worker/wal-retention.d.ts.map +1 -0
- package/dist/worker/wal-retention.js +763 -0
- package/dist/worker/wal-retention.js.map +1 -0
- package/dist/worker/wal.d.ts +278 -0
- package/dist/worker/wal.d.ts.map +1 -0
- package/dist/worker/wal.js +467 -0
- package/dist/worker/wal.js.map +1 -0
- package/dist/worker/websocket.d.ts +85 -0
- package/dist/worker/websocket.d.ts.map +1 -0
- package/dist/worker/websocket.js +227 -0
- package/dist/worker/websocket.js.map +1 -0
- package/package.json +108 -0
- package/src/cdc/change-stream.ts +137 -0
- package/src/cdc/filter.ts +646 -0
- package/src/cdc/index.ts +112 -0
- package/src/cdc/resume-token.ts +280 -0
- package/src/cdc/transport/index.ts +7 -0
- package/src/cdc/transport/sse.ts +723 -0
- package/src/cdc/transport/websocket.ts +873 -0
- package/src/cdc/types.ts +346 -0
- package/src/config/index.ts +25 -0
- package/src/config/memory.ts +177 -0
- package/src/config/storage.ts +204 -0
- package/src/config/streaming.ts +147 -0
- package/src/config/timeouts.ts +221 -0
- package/src/extensions/config.test.ts +187 -0
- package/src/extensions/config.ts +278 -0
- package/src/extensions/geo.test.ts +455 -0
- package/src/extensions/geo.ts +858 -0
- package/src/extensions/index.test.ts +259 -0
- package/src/extensions/index.ts +227 -0
- package/src/extensions/loader.test.ts +555 -0
- package/src/extensions/loader.ts +588 -0
- package/src/extensions/pgmq-lite.test.ts +727 -0
- package/src/extensions/pgmq-lite.ts +770 -0
- package/src/extensions/plugins.test.ts +528 -0
- package/src/extensions/plugins.ts +718 -0
- package/src/extensions/registry.test.ts +202 -0
- package/src/extensions/registry.ts +267 -0
- package/src/extensions/vector.test.ts +195 -0
- package/src/extensions/vector.ts +217 -0
- package/src/iceberg/SCHEDULER.md +580 -0
- package/src/iceberg/analytics.test.ts +703 -0
- package/src/iceberg/analytics.ts +727 -0
- package/src/iceberg/catalog-api.test.ts +838 -0
- package/src/iceberg/catalog-api.ts +520 -0
- package/src/iceberg/catalog.test.ts +680 -0
- package/src/iceberg/catalog.ts +1007 -0
- package/src/iceberg/iceberg.test.ts +705 -0
- package/src/iceberg/index.ts +406 -0
- package/src/iceberg/metadata.test.ts +632 -0
- package/src/iceberg/metadata.ts +649 -0
- package/src/iceberg/optimizer.test.ts +868 -0
- package/src/iceberg/optimizer.ts +1287 -0
- package/src/iceberg/parquet.test.ts +899 -0
- package/src/iceberg/parquet.ts +1640 -0
- package/src/iceberg/r2-organization.test.ts +615 -0
- package/src/iceberg/r2-organization.ts +951 -0
- package/src/iceberg/scheduler-do-example.ts +364 -0
- package/src/iceberg/scheduler.test.ts +861 -0
- package/src/iceberg/scheduler.ts +1201 -0
- package/src/iceberg/schema.test.ts +547 -0
- package/src/iceberg/schema.ts +616 -0
- package/src/iceberg/snapshot-manager.test.ts +919 -0
- package/src/iceberg/snapshot-manager.ts +1369 -0
- package/src/iceberg/sql-router.test.ts +334 -0
- package/src/iceberg/sql-router.ts +337 -0
- package/src/iceberg/test-fixtures.ts +605 -0
- package/src/iceberg/time-travel-api.test.ts +1029 -0
- package/src/iceberg/time-travel-api.ts +731 -0
- package/src/iceberg/time-travel.test.ts +1218 -0
- package/src/iceberg/time-travel.ts +1052 -0
- package/src/iceberg/transformer.test.ts +689 -0
- package/src/iceberg/transformer.ts +1029 -0
- package/src/iceberg/types.ts +373 -0
- package/src/iceberg/writer.test.ts +716 -0
- package/src/iceberg/writer.ts +590 -0
- package/src/index.ts +212 -0
- package/src/lineage/index.ts +42 -0
- package/src/lineage/integration.ts +334 -0
- package/src/lineage/tracker.ts +1618 -0
- package/src/lineage/types.ts +354 -0
- package/src/middleware/index.ts +36 -0
- package/src/middleware/rate-limit-concurrent.test.ts +794 -0
- package/src/middleware/rate-limit.test.ts +1568 -0
- package/src/middleware/rate-limit.ts +840 -0
- package/src/migration-tooling/external-migration.test.ts +1864 -0
- package/src/migration-tooling/external-migration.ts +2355 -0
- package/src/migration-tooling/index.ts +19 -0
- package/src/migrations/ARCHITECTURE.md +474 -0
- package/src/migrations/PROGRESS_TRACKING.md +485 -0
- package/src/migrations/auto-migrator.test.ts +732 -0
- package/src/migrations/auto-migrator.ts +531 -0
- package/src/migrations/bulk-orchestrator.test.ts +801 -0
- package/src/migrations/bulk-orchestrator.ts +1039 -0
- package/src/migrations/compatibility.test.ts +958 -0
- package/src/migrations/compatibility.ts +902 -0
- package/src/migrations/do-migrations.test.ts +2620 -0
- package/src/migrations/do-migrations.ts +1289 -0
- package/src/migrations/do-migrations.types.ts +715 -0
- package/src/migrations/drizzle-compat.test.ts +210 -0
- package/src/migrations/drizzle-compat.ts +337 -0
- package/src/migrations/index.ts +334 -0
- package/src/migrations/migration-api.test.ts +438 -0
- package/src/migrations/migration-api.ts +704 -0
- package/src/migrations/progress-tracker-do.ts +518 -0
- package/src/migrations/progress-tracker-kv.ts +305 -0
- package/src/migrations/progress-tracker.test.ts +937 -0
- package/src/migrations/progress-tracker.ts +665 -0
- package/src/migrations/registry.test.ts +331 -0
- package/src/migrations/registry.ts +468 -0
- package/src/migrations/rollback.test.ts +644 -0
- package/src/migrations/runner.test.ts +807 -0
- package/src/migrations/runner.test.ts.backup +759 -0
- package/src/migrations/runner.ts +1459 -0
- package/src/migrations/schema-generator.test.ts +649 -0
- package/src/migrations/schema-generator.ts +513 -0
- package/src/migrations/testing.ts +1037 -0
- package/src/migrations/types.ts +573 -0
- package/src/migrations/validator.test.ts +660 -0
- package/src/migrations/validator.ts +741 -0
- package/src/observability/alerting.test.ts +1133 -0
- package/src/observability/alerting.ts +455 -0
- package/src/observability/analytics-engine.ts +733 -0
- package/src/observability/cost-metrics.ts +804 -0
- package/src/observability/cross-do-tracing.test.ts +516 -0
- package/src/observability/cross-do-tracing.ts +588 -0
- package/src/observability/dashboards/postgres-do-overview.json +1656 -0
- package/src/observability/error-rate-collector.test.ts +977 -0
- package/src/observability/error-rate-collector.ts +518 -0
- package/src/observability/exporters.test.ts +365 -0
- package/src/observability/exporters.ts +650 -0
- package/src/observability/health-check.test.ts +353 -0
- package/src/observability/health-check.ts +341 -0
- package/src/observability/index.test.ts +298 -0
- package/src/observability/index.ts +885 -0
- package/src/observability/instrumentation.test.ts +428 -0
- package/src/observability/instrumentation.ts +788 -0
- package/src/observability/memory-metrics.test.ts +355 -0
- package/src/observability/memory-metrics.ts +990 -0
- package/src/observability/metrics-endpoint.test.ts +402 -0
- package/src/observability/metrics-endpoint.ts +374 -0
- package/src/observability/metrics.test.ts +291 -0
- package/src/observability/metrics.ts +315 -0
- package/src/observability/observability-features.ts +1296 -0
- package/src/observability/prometheus.test.ts +292 -0
- package/src/observability/prometheus.ts +170 -0
- package/src/observability/propagation.test.ts +417 -0
- package/src/observability/propagation.ts +294 -0
- package/src/observability/query-latency.ts +586 -0
- package/src/observability/query-performance.test.ts +406 -0
- package/src/observability/query-performance.ts +491 -0
- package/src/observability/storage-tier-metrics.test.ts +633 -0
- package/src/observability/storage-tier-metrics.ts +570 -0
- package/src/observability/tier-cost-optimizer.ts +740 -0
- package/src/observability/tracer.test.ts +346 -0
- package/src/observability/tracer.ts +585 -0
- package/src/observability/types.test.ts +726 -0
- package/src/observability/types.ts +434 -0
- package/src/pglite/auto-demotion.test.ts +477 -0
- package/src/pglite/auto-demotion.ts +385 -0
- package/src/pglite/auto-promotion.test.ts +824 -0
- package/src/pglite/auto-promotion.ts +547 -0
- package/src/pglite/cache-layer.test.ts +469 -0
- package/src/pglite/cache-layer.ts +271 -0
- package/src/pglite/cold-start-manager.ts +1260 -0
- package/src/pglite/cold-start-optimizer.test.ts +937 -0
- package/src/pglite/cold-start-optimizer.ts +1895 -0
- package/src/pglite/dovfs-adapter.ts +1122 -0
- package/src/pglite/dovfs.ts +1258 -0
- package/src/pglite/etag-cache.test.ts +844 -0
- package/src/pglite/etag-cache.ts +526 -0
- package/src/pglite/index.ts +442 -0
- package/src/pglite/init.test.ts +455 -0
- package/src/pglite/init.ts +574 -0
- package/src/pglite/lifecycle.test.ts +599 -0
- package/src/pglite/lifecycle.ts +704 -0
- package/src/pglite/parallel-loader.test.ts +586 -0
- package/src/pglite/parallel-loader.ts +481 -0
- package/src/pglite/production-pglite.test.ts +666 -0
- package/src/pglite/production-pglite.ts +537 -0
- package/src/pglite/query-executor.ts +614 -0
- package/src/pglite/r2-layer.test.ts +501 -0
- package/src/pglite/r2-layer.ts +322 -0
- package/src/pglite/tiered-init.test.ts +725 -0
- package/src/pglite/tiered-init.ts +556 -0
- package/src/pglite/tiered-vfs.test.ts +726 -0
- package/src/pglite/tiered-vfs.ts +33 -0
- package/src/pglite/tiering-stats.test.ts +531 -0
- package/src/pglite/tiering-stats.ts +407 -0
- package/src/pglite/transaction-hooks.ts +343 -0
- package/src/pglite/warm-loader.test.ts +1701 -0
- package/src/pglite/warm-loader.ts +528 -0
- package/src/pglite/workers-pglite.ts +224 -0
- package/src/pglite-assets/pglite.data +0 -0
- package/src/pglite-assets/pglite.wasm +0 -0
- package/src/pglite.d.ts +47 -0
- package/src/playground/index.ts +137 -0
- package/src/playground/keyboard-shortcuts.ts +677 -0
- package/src/playground/playground.ts +323 -0
- package/src/playground/query-executor.ts +669 -0
- package/src/playground/query-history.ts +328 -0
- package/src/playground/result-formatter.ts +420 -0
- package/src/playground/sample-datasets.ts +674 -0
- package/src/playground/sample-queries.ts +1168 -0
- package/src/playground/schema-explorer.ts +558 -0
- package/src/playground/types.ts +518 -0
- package/src/readonly/cache-reader.test.ts +460 -0
- package/src/readonly/cache-reader.ts +313 -0
- package/src/readonly/config.test.ts +187 -0
- package/src/readonly/config.ts +128 -0
- package/src/readonly/index.ts +50 -0
- package/src/readonly/pglite-wrapper.test.ts +278 -0
- package/src/readonly/pglite-wrapper.ts +184 -0
- package/src/readonly/worker.test.ts +533 -0
- package/src/readonly/worker.ts +341 -0
- package/src/readonly/write-blocker.test.ts +459 -0
- package/src/readonly/write-blocker.ts +175 -0
- package/src/recovery/disaster-recovery.test.ts +618 -0
- package/src/recovery/disaster-recovery.ts +1181 -0
- package/src/recovery/index.ts +43 -0
- package/src/recovery/parquet-parser.ts +974 -0
- package/src/retention/index.ts +74 -0
- package/src/retention/policy.test.ts +571 -0
- package/src/retention/policy.ts +774 -0
- package/src/retention/purger.test.ts +465 -0
- package/src/retention/purger.ts +558 -0
- package/src/rls/auth-integration.test.ts +752 -0
- package/src/rls/auth-integration.ts +533 -0
- package/src/rls/generator.test.ts +829 -0
- package/src/rls/generator.ts +573 -0
- package/src/rls/index.ts +128 -0
- package/src/rls/policy.ts +208 -0
- package/src/rls/rls.test.ts +1071 -0
- package/src/rls/validator.test.ts +930 -0
- package/src/rls/validator.ts +895 -0
- package/src/routing/adaptive-router.test.ts +884 -0
- package/src/routing/adaptive-router.ts +845 -0
- package/src/routing/circuit-breaker.test.ts +1505 -0
- package/src/routing/circuit-breaker.ts +852 -0
- package/src/routing/cost-metrics.test.ts +565 -0
- package/src/routing/cost-metrics.ts +408 -0
- package/src/routing/do-connection-pool.test.ts +1109 -0
- package/src/routing/do-connection-pool.ts +828 -0
- package/src/routing/index.ts +158 -0
- package/src/routing/query-complexity-estimator.test.ts +356 -0
- package/src/routing/query-complexity-estimator.ts +444 -0
- package/src/routing/request-coalescing.test.ts +738 -0
- package/src/routing/request-coalescing.ts +475 -0
- package/src/routing/runtime-router.test.ts +436 -0
- package/src/routing/runtime-router.ts +357 -0
- package/src/routing/tenant-router.test.ts +2493 -0
- package/src/routing/tenant-router.ts +1908 -0
- package/src/routing/websocket-pool.test.ts +551 -0
- package/src/routing/websocket-pool.ts +577 -0
- package/src/storage/access-pattern-tracker.test.ts +874 -0
- package/src/storage/cache-layer.test.ts +560 -0
- package/src/storage/cache-layer.ts +328 -0
- package/src/storage/cost-aware-tiering.test.ts +652 -0
- package/src/storage/cost-aware-tiering.ts +794 -0
- package/src/storage/do-sqlite-blobs.test.ts +937 -0
- package/src/storage/index.ts +272 -0
- package/src/storage/interfaces.ts +974 -0
- package/src/storage/r2-layer.test.ts +653 -0
- package/src/storage/r2-layer.ts +434 -0
- package/src/storage/r2-overflow.ts +920 -0
- package/src/storage/r2-page-vfs.test.ts +2348 -0
- package/src/storage/r2-page-vfs.ts +1054 -0
- package/src/storage/swr-cache.test.ts +832 -0
- package/src/storage/swr-cache.ts +398 -0
- package/src/storage/swr-tiered-integration.test.ts +617 -0
- package/src/storage/tiered-orchestrator.test.ts +2441 -0
- package/src/storage/tiered-orchestrator.ts +2081 -0
- package/src/storage/tiered-vfs-swr.test.ts +736 -0
- package/src/storage/tiered-vfs-swr.ts +735 -0
- package/src/storage/tiered-vfs.test.ts +793 -0
- package/src/storage/tiered-vfs.ts +1082 -0
- package/src/streaming/backpressure-controller.ts +452 -0
- package/src/streaming/buffer-pool.ts +484 -0
- package/src/streaming/cdc-iceberg-connector.ts +605 -0
- package/src/streaming/index.ts +225 -0
- package/src/streaming/live-cdc-stream.ts +985 -0
- package/src/streaming/memory-bounded-stream.ts +443 -0
- package/src/streaming/query-streamer.ts +662 -0
- package/src/streaming/response-streaming.ts +557 -0
- package/src/types/branded.ts +1075 -0
- package/src/types/branded.ts.backup +273 -0
- package/src/types/utilities.ts +1023 -0
- package/src/types/wasm.d.ts +30 -0
- package/src/validation/typed-errors.test.ts +420 -0
- package/src/wal/replay-engine.ts +1264 -0
- package/src/worker/__mocks__/capnweb.ts +15 -0
- package/src/worker/__mocks__/pglite.data.ts +22 -0
- package/src/worker/__mocks__/pglite.wasm.ts +33 -0
- package/src/worker/auth-rate-limiter.test.ts +272 -0
- package/src/worker/auth-rate-limiter.ts +448 -0
- package/src/worker/auth.security-red.test.ts +1236 -0
- package/src/worker/auth.security.test.ts +822 -0
- package/src/worker/auth.test.ts +469 -0
- package/src/worker/auth.ts +1104 -0
- package/src/worker/cdc-backpressure.test.ts +726 -0
- package/src/worker/cdc-backpressure.ts +866 -0
- package/src/worker/cdc-sse.test.ts +780 -0
- package/src/worker/cdc-sse.ts +728 -0
- package/src/worker/cdc-websocket.ts +1229 -0
- package/src/worker/cdc-ws.test.ts +1009 -0
- package/src/worker/cdc.test.ts +327 -0
- package/src/worker/cdc.ts +289 -0
- package/src/worker/concerns/auth-concern.ts +179 -0
- package/src/worker/concerns/cdc-concern.ts +247 -0
- package/src/worker/concerns/index.ts +58 -0
- package/src/worker/concerns/query-execution-concern.ts +194 -0
- package/src/worker/concerns/storage-orchestration-concern.ts +373 -0
- package/src/worker/discriminated-types.test.ts +280 -0
- package/src/worker/do-auth-manager.ts +257 -0
- package/src/worker/do-decomposition.test.ts +1236 -0
- package/src/worker/do-pglite-manager.ts +302 -0
- package/src/worker/do.test.ts +2254 -0
- package/src/worker/do.ts +1878 -0
- package/src/worker/entry.ts +417 -0
- package/src/worker/errors.ts +285 -0
- package/src/worker/health-check-manager.test.ts +261 -0
- package/src/worker/health-check-manager.ts +231 -0
- package/src/worker/index.ts +389 -0
- package/src/worker/memory-pressure.test.ts +1460 -0
- package/src/worker/memory-pressure.ts +2650 -0
- package/src/worker/migration-manager.ts +582 -0
- package/src/worker/neon-compat.test.ts +332 -0
- package/src/worker/plugin-manager.ts +485 -0
- package/src/worker/postgres.do-rpc.d.ts +76 -0
- package/src/worker/proxy.ts +694 -0
- package/src/worker/query-execution-manager.test.ts +303 -0
- package/src/worker/query-execution-manager.ts +219 -0
- package/src/worker/query-executor.test.ts +282 -0
- package/src/worker/query-executor.ts +560 -0
- package/src/worker/query-stats-manager.ts +229 -0
- package/src/worker/result-handler.test.ts +364 -0
- package/src/worker/result-handler.ts +510 -0
- package/src/worker/routes.test.ts +795 -0
- package/src/worker/routes.ts +650 -0
- package/src/worker/rpc-methods-manager.test.ts +326 -0
- package/src/worker/rpc-methods-manager.ts +276 -0
- package/src/worker/rpc.ts +524 -0
- package/src/worker/schema-version.ts +605 -0
- package/src/worker/session-manager.test.ts +506 -0
- package/src/worker/session-manager.ts +732 -0
- package/src/worker/shutdown-manager.ts +469 -0
- package/src/worker/sql-transform.test.ts +286 -0
- package/src/worker/sql-transform.ts +368 -0
- package/src/worker/supabase-compat.test.ts +621 -0
- package/src/worker/types.test.ts +292 -0
- package/src/worker/types.ts +873 -0
- package/src/worker/user-routes.test.ts +703 -0
- package/src/worker/user-routes.ts +303 -0
- package/src/worker/wal-facade.ts +235 -0
- package/src/worker/wal-r2.test.ts +570 -0
- package/src/worker/wal-r2.ts +930 -0
- package/src/worker/wal-replay.test.ts +845 -0
- package/src/worker/wal-replay.ts +897 -0
- package/src/worker/wal-retention.test.ts +758 -0
- package/src/worker/wal-retention.ts +1075 -0
- package/src/worker/wal.test.ts +618 -0
- package/src/worker/wal.ts +697 -0
- package/src/worker/websocket.test.ts +296 -0
- package/src/worker/websocket.ts +284 -0
|
@@ -0,0 +1,1009 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RED PHASE: Flaky CDC WebSocket Transport Tests
|
|
3
|
+
* Task: postgres-dnid - Fix flaky CDC WebSocket transport tests
|
|
4
|
+
*
|
|
5
|
+
* These tests are designed to EXPOSE timing-related flakiness in the CDC WebSocket transport.
|
|
6
|
+
* They test:
|
|
7
|
+
* 1. Timing-related race conditions
|
|
8
|
+
* 2. Reconnection logic under various conditions
|
|
9
|
+
* 3. Message ordering guarantees
|
|
10
|
+
* 4. Connection state management
|
|
11
|
+
*
|
|
12
|
+
* Expected: These tests should initially FAIL to identify the flaky behavior.
|
|
13
|
+
*/
|
|
14
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
15
|
+
import {
|
|
16
|
+
CDCWebSocketHandler,
|
|
17
|
+
createCDCWebSocketHandler,
|
|
18
|
+
} from './cdc-websocket'
|
|
19
|
+
import { CDCManager } from './cdc'
|
|
20
|
+
import type { WSMessage, CDCWebSocketConfig } from './types'
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Mock Infrastructure
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
interface MockWebSocket {
|
|
27
|
+
id: string
|
|
28
|
+
send: ReturnType<typeof vi.fn>
|
|
29
|
+
close: ReturnType<typeof vi.fn>
|
|
30
|
+
readyState: number
|
|
31
|
+
serializeAttachment: ReturnType<typeof vi.fn>
|
|
32
|
+
deserializeAttachment: ReturnType<typeof vi.fn>
|
|
33
|
+
// Simulate WebSocket state transitions
|
|
34
|
+
simulateClose: (code: number, reason: string) => void
|
|
35
|
+
simulateError: (error: Error) => void
|
|
36
|
+
setReadyState: (state: number) => void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const WS_CONNECTING = 0
|
|
40
|
+
const WS_OPEN = 1
|
|
41
|
+
const WS_CLOSING = 2
|
|
42
|
+
const WS_CLOSED = 3
|
|
43
|
+
|
|
44
|
+
let mockWebSocketIdCounter = 0
|
|
45
|
+
|
|
46
|
+
const createMockWebSocket = (id?: string): MockWebSocket => {
|
|
47
|
+
const wsId = id ?? `ws-${++mockWebSocketIdCounter}`
|
|
48
|
+
let readyState = WS_OPEN
|
|
49
|
+
|
|
50
|
+
const ws: MockWebSocket = {
|
|
51
|
+
id: wsId,
|
|
52
|
+
send: vi.fn(),
|
|
53
|
+
close: vi.fn(),
|
|
54
|
+
get readyState() {
|
|
55
|
+
return readyState
|
|
56
|
+
},
|
|
57
|
+
serializeAttachment: vi.fn(),
|
|
58
|
+
deserializeAttachment: vi.fn(() => ({ subscriptions: [] })),
|
|
59
|
+
simulateClose: (code: number, reason: string) => {
|
|
60
|
+
readyState = WS_CLOSED
|
|
61
|
+
ws.close(code, reason)
|
|
62
|
+
},
|
|
63
|
+
simulateError: (_error: Error) => {
|
|
64
|
+
readyState = WS_CLOSING
|
|
65
|
+
},
|
|
66
|
+
setReadyState: (state: number) => {
|
|
67
|
+
readyState = state
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
return ws
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const createMockState = () => {
|
|
74
|
+
const webSockets: MockWebSocket[] = []
|
|
75
|
+
return {
|
|
76
|
+
id: { toString: () => 'test-do-id' },
|
|
77
|
+
acceptWebSocket: vi.fn((ws: MockWebSocket) => {
|
|
78
|
+
webSockets.push(ws)
|
|
79
|
+
return ws
|
|
80
|
+
}),
|
|
81
|
+
getWebSockets: vi.fn(() => webSockets),
|
|
82
|
+
storage: {
|
|
83
|
+
get: vi.fn(),
|
|
84
|
+
put: vi.fn(),
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const createMockExecutor = () => ({
|
|
90
|
+
executeQuery: vi.fn(async () => ({
|
|
91
|
+
rows: [{ id: 1 }],
|
|
92
|
+
fields: [{ name: 'id', dataTypeID: 23 }],
|
|
93
|
+
rowCount: 1,
|
|
94
|
+
durationMs: 1.5,
|
|
95
|
+
})),
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const createMockBroadcaster = () => ({
|
|
99
|
+
broadcast: vi.fn(),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Helper to parse sent messages
|
|
103
|
+
const getSentMessages = (ws: MockWebSocket): WSMessage[] => {
|
|
104
|
+
return ws.send.mock.calls.map((call: [string]) => JSON.parse(call[0]))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Helper to get last sent message
|
|
108
|
+
const getLastSentMessage = (ws: MockWebSocket): WSMessage | undefined => {
|
|
109
|
+
const messages = getSentMessages(ws)
|
|
110
|
+
return messages[messages.length - 1]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Helper to wait for async operations (works with both real and fake timers)
|
|
114
|
+
const flushPromises = async () => {
|
|
115
|
+
// Use queueMicrotask for microtask-based flushing that works with fake timers
|
|
116
|
+
await new Promise(resolve => queueMicrotask(resolve))
|
|
117
|
+
// Also process any pending promise jobs
|
|
118
|
+
await Promise.resolve()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Helper to advance timers and flush (compatible with vi.useFakeTimers())
|
|
122
|
+
// Uses advanceTimersByTimeAsync to only advance by the specified amount,
|
|
123
|
+
// not run ALL timers (which could cause infinite loops with setInterval)
|
|
124
|
+
const advanceTimersAndFlush = async (ms: number) => {
|
|
125
|
+
// Advance fake timers by the specified amount (runs timers that become due)
|
|
126
|
+
await vi.advanceTimersByTimeAsync(ms)
|
|
127
|
+
// Flush any remaining microtasks
|
|
128
|
+
await flushPromises()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Helper to handle WebSocket upgrade in Node.js test environment.
|
|
133
|
+
* In Cloudflare Workers, Response status 101 is valid.
|
|
134
|
+
* In Node.js, we need to catch the error and verify acceptWebSocket was called.
|
|
135
|
+
*/
|
|
136
|
+
const safeHandleUpgrade = (
|
|
137
|
+
handler: CDCWebSocketHandler,
|
|
138
|
+
mockState: ReturnType<typeof createMockState>,
|
|
139
|
+
ws: MockWebSocket
|
|
140
|
+
): void => {
|
|
141
|
+
const mockPair = { 0: createMockWebSocket(), 1: ws }
|
|
142
|
+
const request = new Request('http://localhost/cdc', {
|
|
143
|
+
headers: { Upgrade: 'websocket' },
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const response = handler.handleUpgrade(request, mockPair as any)
|
|
148
|
+
// In real Cloudflare Workers, this would return 101
|
|
149
|
+
if (response.status === 101) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
} catch (e) {
|
|
153
|
+
// Expected in Node.js - status 101 not allowed in fetch Response
|
|
154
|
+
// Verify acceptWebSocket was called
|
|
155
|
+
if (mockState.acceptWebSocket.mock.calls.length === 0) {
|
|
156
|
+
throw e
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Test Suites
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
describe('CDC WebSocket Transport - Flaky Tests', () => {
|
|
166
|
+
let handler: CDCWebSocketHandler
|
|
167
|
+
let mockState: ReturnType<typeof createMockState>
|
|
168
|
+
let mockExecutor: ReturnType<typeof createMockExecutor>
|
|
169
|
+
let timers: ReturnType<typeof vi.useFakeTimers> | null = null
|
|
170
|
+
|
|
171
|
+
beforeEach(() => {
|
|
172
|
+
vi.clearAllMocks()
|
|
173
|
+
mockWebSocketIdCounter = 0
|
|
174
|
+
mockState = createMockState()
|
|
175
|
+
mockExecutor = createMockExecutor()
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
afterEach(async () => {
|
|
179
|
+
// CRITICAL: Clean up timers to prevent leaks
|
|
180
|
+
if (timers) {
|
|
181
|
+
vi.useRealTimers()
|
|
182
|
+
timers = null
|
|
183
|
+
}
|
|
184
|
+
// Allow any pending microtasks to complete
|
|
185
|
+
await flushPromises()
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// ==========================================================================
|
|
189
|
+
// 1. Timing-Related Race Conditions
|
|
190
|
+
// ==========================================================================
|
|
191
|
+
|
|
192
|
+
describe('Timing-Related Race Conditions', () => {
|
|
193
|
+
it('should handle heartbeat timeout during active message processing', async () => {
|
|
194
|
+
/**
|
|
195
|
+
* FLAKY SCENARIO: Heartbeat timer fires while a long-running query is being processed.
|
|
196
|
+
* The heartbeat check might incorrectly close the connection.
|
|
197
|
+
*/
|
|
198
|
+
timers = vi.useFakeTimers()
|
|
199
|
+
|
|
200
|
+
const config: CDCWebSocketConfig = {
|
|
201
|
+
heartbeatInterval: 100,
|
|
202
|
+
heartbeatTimeout: 50,
|
|
203
|
+
}
|
|
204
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
205
|
+
|
|
206
|
+
const ws = createMockWebSocket()
|
|
207
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
208
|
+
|
|
209
|
+
// Simulate slow query that takes longer than heartbeat timeout
|
|
210
|
+
mockExecutor.executeQuery.mockImplementation(async () => {
|
|
211
|
+
// Simulate query taking 200ms (longer than heartbeat interval)
|
|
212
|
+
await new Promise(resolve => setTimeout(resolve, 200))
|
|
213
|
+
return { rows: [], fields: [], rowCount: 0, durationMs: 200 }
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
// Start a query
|
|
217
|
+
const queryPromise = handler.handleMessage(ws as any, JSON.stringify({
|
|
218
|
+
type: 'query',
|
|
219
|
+
id: 'slow-query-1',
|
|
220
|
+
payload: { sql: 'SELECT pg_sleep(1)' },
|
|
221
|
+
}))
|
|
222
|
+
|
|
223
|
+
// Advance past heartbeat interval + timeout
|
|
224
|
+
await advanceTimersAndFlush(160)
|
|
225
|
+
|
|
226
|
+
// Complete the query
|
|
227
|
+
await advanceTimersAndFlush(50)
|
|
228
|
+
await queryPromise
|
|
229
|
+
|
|
230
|
+
// Connection should still be active after slow query completes
|
|
231
|
+
expect(ws.readyState).toBe(WS_OPEN)
|
|
232
|
+
expect(ws.close).not.toHaveBeenCalled()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('should not race between heartbeat timer and explicit close', async () => {
|
|
236
|
+
/**
|
|
237
|
+
* FLAKY SCENARIO: Client closes connection exactly when heartbeat timer fires.
|
|
238
|
+
* Could cause double-close or accessing closed connection state.
|
|
239
|
+
*/
|
|
240
|
+
timers = vi.useFakeTimers()
|
|
241
|
+
|
|
242
|
+
const config: CDCWebSocketConfig = {
|
|
243
|
+
heartbeatInterval: 100,
|
|
244
|
+
heartbeatTimeout: 50,
|
|
245
|
+
}
|
|
246
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
247
|
+
|
|
248
|
+
const ws = createMockWebSocket()
|
|
249
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
250
|
+
|
|
251
|
+
// Advance to just before heartbeat
|
|
252
|
+
await advanceTimersAndFlush(99)
|
|
253
|
+
|
|
254
|
+
// Explicitly close the connection
|
|
255
|
+
ws.simulateClose(1000, 'Client closing')
|
|
256
|
+
handler.handleClose(ws as any, 1000, 'Client closing')
|
|
257
|
+
|
|
258
|
+
// Now advance past heartbeat - timer should not cause errors
|
|
259
|
+
await advanceTimersAndFlush(10)
|
|
260
|
+
|
|
261
|
+
// Should not throw or cause issues
|
|
262
|
+
expect(handler.getConnectedCount()).toBe(0)
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('should handle rapid subscribe/unsubscribe cycles', async () => {
|
|
266
|
+
/**
|
|
267
|
+
* FLAKY SCENARIO: Rapid subscription changes can cause race conditions
|
|
268
|
+
* in subscription tracking.
|
|
269
|
+
*/
|
|
270
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
271
|
+
|
|
272
|
+
const ws = createMockWebSocket()
|
|
273
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
274
|
+
ws.send.mockClear()
|
|
275
|
+
|
|
276
|
+
// Rapid subscribe/unsubscribe cycles
|
|
277
|
+
const operations: Promise<void>[] = []
|
|
278
|
+
const subscriptionIds: string[] = []
|
|
279
|
+
|
|
280
|
+
for (let i = 0; i < 10; i++) {
|
|
281
|
+
// Subscribe
|
|
282
|
+
operations.push(handler.handleMessage(ws as any, JSON.stringify({
|
|
283
|
+
type: 'subscribe',
|
|
284
|
+
id: `sub-${i}`,
|
|
285
|
+
payload: { table: 'users' },
|
|
286
|
+
})))
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
await Promise.all(operations)
|
|
290
|
+
|
|
291
|
+
// Collect subscription IDs from responses
|
|
292
|
+
const messages = getSentMessages(ws)
|
|
293
|
+
for (const msg of messages) {
|
|
294
|
+
if (msg.type === 'subscribed' && msg.payload) {
|
|
295
|
+
const payload = msg.payload as { subscriptionId: string }
|
|
296
|
+
subscriptionIds.push(payload.subscriptionId)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Now unsubscribe all rapidly
|
|
301
|
+
ws.send.mockClear()
|
|
302
|
+
const unsubOps: Promise<void>[] = []
|
|
303
|
+
for (const subId of subscriptionIds) {
|
|
304
|
+
unsubOps.push(handler.handleMessage(ws as any, JSON.stringify({
|
|
305
|
+
type: 'unsubscribe',
|
|
306
|
+
id: `unsub-${subId}`,
|
|
307
|
+
payload: { subscriptionId: subId },
|
|
308
|
+
})))
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
await Promise.all(unsubOps)
|
|
312
|
+
|
|
313
|
+
// All subscriptions should be removed
|
|
314
|
+
expect(handler.getSubscriptionCount()).toBe(0)
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it('should handle messages arriving during connection close', async () => {
|
|
318
|
+
/**
|
|
319
|
+
* FLAKY SCENARIO: Messages arrive after close has been initiated but
|
|
320
|
+
* before state is fully cleaned up.
|
|
321
|
+
*/
|
|
322
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
323
|
+
|
|
324
|
+
const ws = createMockWebSocket()
|
|
325
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
326
|
+
|
|
327
|
+
// Subscribe to a table
|
|
328
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
329
|
+
type: 'subscribe',
|
|
330
|
+
id: 'sub-1',
|
|
331
|
+
payload: { table: 'users' },
|
|
332
|
+
}))
|
|
333
|
+
|
|
334
|
+
// Start closing
|
|
335
|
+
ws.setReadyState(WS_CLOSING)
|
|
336
|
+
|
|
337
|
+
// Try to send another message during close
|
|
338
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
339
|
+
type: 'subscribe',
|
|
340
|
+
id: 'sub-2',
|
|
341
|
+
payload: { table: 'orders' },
|
|
342
|
+
}))
|
|
343
|
+
|
|
344
|
+
// Complete close
|
|
345
|
+
ws.simulateClose(1000, 'Normal closure')
|
|
346
|
+
handler.handleClose(ws as any, 1000, 'Normal closure')
|
|
347
|
+
|
|
348
|
+
// Should not throw and state should be clean
|
|
349
|
+
expect(handler.getConnectedCount()).toBe(0)
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
// ==========================================================================
|
|
354
|
+
// 2. Reconnection Logic
|
|
355
|
+
// ==========================================================================
|
|
356
|
+
|
|
357
|
+
describe('Reconnection Logic', () => {
|
|
358
|
+
it('should restore subscriptions on reconnect', async () => {
|
|
359
|
+
/**
|
|
360
|
+
* FLAKY SCENARIO: Subscription restoration during reconnect might miss
|
|
361
|
+
* subscriptions if they are being modified concurrently.
|
|
362
|
+
*/
|
|
363
|
+
timers = vi.useFakeTimers()
|
|
364
|
+
|
|
365
|
+
const config: CDCWebSocketConfig = {
|
|
366
|
+
reconnectDelay: 100,
|
|
367
|
+
maxReconnectAttempts: 3,
|
|
368
|
+
}
|
|
369
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
370
|
+
|
|
371
|
+
// First connection
|
|
372
|
+
const ws1 = createMockWebSocket('ws-1')
|
|
373
|
+
safeHandleUpgrade(handler, mockState, ws1)
|
|
374
|
+
|
|
375
|
+
// Get connection ID from welcome message
|
|
376
|
+
const welcome1 = getLastSentMessage(ws1) as any
|
|
377
|
+
expect(welcome1?.type).toBe('welcome')
|
|
378
|
+
const connectionId = welcome1?.payload?.connectionId
|
|
379
|
+
|
|
380
|
+
// Subscribe to tables
|
|
381
|
+
await handler.handleMessage(ws1 as any, JSON.stringify({
|
|
382
|
+
type: 'subscribe',
|
|
383
|
+
id: 'sub-1',
|
|
384
|
+
payload: { table: 'users' },
|
|
385
|
+
}))
|
|
386
|
+
|
|
387
|
+
const subResponse = getLastSentMessage(ws1) as any
|
|
388
|
+
const subscriptionId = subResponse?.payload?.subscriptionId
|
|
389
|
+
|
|
390
|
+
// Close first connection
|
|
391
|
+
ws1.simulateClose(1006, 'Abnormal closure')
|
|
392
|
+
handler.handleClose(ws1 as any, 1006, 'Abnormal closure')
|
|
393
|
+
|
|
394
|
+
// Second connection - reconnect
|
|
395
|
+
const ws2 = createMockWebSocket('ws-2')
|
|
396
|
+
safeHandleUpgrade(handler, mockState, ws2)
|
|
397
|
+
ws2.send.mockClear()
|
|
398
|
+
|
|
399
|
+
// Attempt reconnection with previous connection ID
|
|
400
|
+
await handler.handleMessage(ws2 as any, JSON.stringify({
|
|
401
|
+
type: 'reconnect',
|
|
402
|
+
id: 'reconnect-1',
|
|
403
|
+
payload: {
|
|
404
|
+
connectionId: connectionId,
|
|
405
|
+
subscriptionIds: [subscriptionId],
|
|
406
|
+
},
|
|
407
|
+
}))
|
|
408
|
+
|
|
409
|
+
// Should receive welcome with restored subscriptions
|
|
410
|
+
const messages = getSentMessages(ws2)
|
|
411
|
+
const welcomeMsg = messages.find(m => m.type === 'welcome')
|
|
412
|
+
expect(welcomeMsg).toBeDefined()
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
it('should handle reconnect with stale connection ID', async () => {
|
|
416
|
+
/**
|
|
417
|
+
* FLAKY SCENARIO: Reconnect request uses a connection ID that has
|
|
418
|
+
* already been cleaned up.
|
|
419
|
+
*/
|
|
420
|
+
timers = vi.useFakeTimers()
|
|
421
|
+
|
|
422
|
+
const config: CDCWebSocketConfig = {
|
|
423
|
+
reconnectDelay: 100,
|
|
424
|
+
maxReconnectAttempts: 3,
|
|
425
|
+
}
|
|
426
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
427
|
+
|
|
428
|
+
// First connection
|
|
429
|
+
const ws1 = createMockWebSocket('ws-1')
|
|
430
|
+
safeHandleUpgrade(handler, mockState, ws1)
|
|
431
|
+
|
|
432
|
+
const welcome1 = getLastSentMessage(ws1) as any
|
|
433
|
+
const oldConnectionId = welcome1?.payload?.connectionId
|
|
434
|
+
|
|
435
|
+
// Close first connection
|
|
436
|
+
ws1.simulateClose(1006, 'Abnormal closure')
|
|
437
|
+
handler.handleClose(ws1 as any, 1006, 'Abnormal closure')
|
|
438
|
+
|
|
439
|
+
// Wait for cleanup timeout to expire
|
|
440
|
+
await advanceTimersAndFlush(config.reconnectDelay! * config.maxReconnectAttempts! + 100)
|
|
441
|
+
|
|
442
|
+
// New connection - reconnect with stale ID
|
|
443
|
+
const ws2 = createMockWebSocket('ws-2')
|
|
444
|
+
safeHandleUpgrade(handler, mockState, ws2)
|
|
445
|
+
ws2.send.mockClear()
|
|
446
|
+
|
|
447
|
+
// Attempt reconnection with stale connection ID
|
|
448
|
+
await handler.handleMessage(ws2 as any, JSON.stringify({
|
|
449
|
+
type: 'reconnect',
|
|
450
|
+
id: 'reconnect-1',
|
|
451
|
+
payload: {
|
|
452
|
+
connectionId: oldConnectionId,
|
|
453
|
+
subscriptionIds: ['stale-sub-id'],
|
|
454
|
+
},
|
|
455
|
+
}))
|
|
456
|
+
|
|
457
|
+
// Should still work (graceful degradation) - just won't restore subscriptions
|
|
458
|
+
const messages = getSentMessages(ws2)
|
|
459
|
+
expect(messages.some(m => m.type === 'welcome' || m.type === 'error')).toBe(true)
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
it('should buffer changes during reconnection window', async () => {
|
|
463
|
+
/**
|
|
464
|
+
* FLAKY SCENARIO: Changes that occur during the reconnection window
|
|
465
|
+
* should be buffered and delivered on reconnect.
|
|
466
|
+
*/
|
|
467
|
+
timers = vi.useFakeTimers()
|
|
468
|
+
|
|
469
|
+
const config: CDCWebSocketConfig = {
|
|
470
|
+
reconnectDelay: 100,
|
|
471
|
+
maxReconnectAttempts: 3,
|
|
472
|
+
bufferChanges: true,
|
|
473
|
+
maxBufferedChanges: 100,
|
|
474
|
+
}
|
|
475
|
+
const broadcaster = createMockBroadcaster()
|
|
476
|
+
const cdcManager = new CDCManager(broadcaster as any)
|
|
477
|
+
|
|
478
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, cdcManager, config)
|
|
479
|
+
|
|
480
|
+
// First connection
|
|
481
|
+
const ws1 = createMockWebSocket('ws-1')
|
|
482
|
+
safeHandleUpgrade(handler, mockState, ws1)
|
|
483
|
+
|
|
484
|
+
const welcome1 = getLastSentMessage(ws1) as any
|
|
485
|
+
const connectionId = welcome1?.payload?.connectionId
|
|
486
|
+
|
|
487
|
+
// Subscribe
|
|
488
|
+
await handler.handleMessage(ws1 as any, JSON.stringify({
|
|
489
|
+
type: 'subscribe',
|
|
490
|
+
id: 'sub-1',
|
|
491
|
+
payload: { table: 'users' },
|
|
492
|
+
}))
|
|
493
|
+
|
|
494
|
+
const subResponse = getLastSentMessage(ws1) as any
|
|
495
|
+
const subscriptionId = subResponse?.payload?.subscriptionId
|
|
496
|
+
|
|
497
|
+
// Close connection
|
|
498
|
+
ws1.simulateClose(1006, 'Abnormal closure')
|
|
499
|
+
handler.handleClose(ws1 as any, 1006, 'Abnormal closure')
|
|
500
|
+
|
|
501
|
+
// Broadcast changes during reconnection window
|
|
502
|
+
handler.broadcastChange({
|
|
503
|
+
table: 'users',
|
|
504
|
+
operation: 'INSERT',
|
|
505
|
+
newRow: { id: 1, name: 'Alice' },
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
handler.broadcastChange({
|
|
509
|
+
table: 'users',
|
|
510
|
+
operation: 'INSERT',
|
|
511
|
+
newRow: { id: 2, name: 'Bob' },
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
// Reconnect
|
|
515
|
+
const ws2 = createMockWebSocket('ws-2')
|
|
516
|
+
safeHandleUpgrade(handler, mockState, ws2)
|
|
517
|
+
ws2.send.mockClear()
|
|
518
|
+
|
|
519
|
+
await handler.handleMessage(ws2 as any, JSON.stringify({
|
|
520
|
+
type: 'reconnect',
|
|
521
|
+
id: 'reconnect-1',
|
|
522
|
+
payload: {
|
|
523
|
+
connectionId: connectionId,
|
|
524
|
+
subscriptionIds: [subscriptionId],
|
|
525
|
+
},
|
|
526
|
+
}))
|
|
527
|
+
|
|
528
|
+
// Should receive buffered changes
|
|
529
|
+
// Note: This test may fail if buffering is not implemented correctly
|
|
530
|
+
const messages = getSentMessages(ws2)
|
|
531
|
+
expect(messages.length).toBeGreaterThan(0)
|
|
532
|
+
})
|
|
533
|
+
|
|
534
|
+
it('should handle concurrent reconnect attempts', async () => {
|
|
535
|
+
/**
|
|
536
|
+
* FLAKY SCENARIO: Multiple reconnect attempts arrive simultaneously,
|
|
537
|
+
* potentially causing state corruption.
|
|
538
|
+
*/
|
|
539
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
540
|
+
|
|
541
|
+
// Initial connection
|
|
542
|
+
const ws1 = createMockWebSocket('ws-1')
|
|
543
|
+
safeHandleUpgrade(handler, mockState, ws1)
|
|
544
|
+
|
|
545
|
+
const welcome1 = getLastSentMessage(ws1) as any
|
|
546
|
+
const connectionId = welcome1?.payload?.connectionId
|
|
547
|
+
|
|
548
|
+
// Close first connection
|
|
549
|
+
ws1.simulateClose(1006, 'Abnormal closure')
|
|
550
|
+
handler.handleClose(ws1 as any, 1006, 'Abnormal closure')
|
|
551
|
+
|
|
552
|
+
// Multiple concurrent reconnect attempts
|
|
553
|
+
const reconnectPromises: Promise<void>[] = []
|
|
554
|
+
|
|
555
|
+
for (let i = 0; i < 3; i++) {
|
|
556
|
+
const ws = createMockWebSocket(`ws-reconnect-${i}`)
|
|
557
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
558
|
+
|
|
559
|
+
reconnectPromises.push(handler.handleMessage(ws as any, JSON.stringify({
|
|
560
|
+
type: 'reconnect',
|
|
561
|
+
id: `reconnect-${i}`,
|
|
562
|
+
payload: { connectionId },
|
|
563
|
+
})))
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// All should complete without errors
|
|
567
|
+
await expect(Promise.all(reconnectPromises)).resolves.not.toThrow()
|
|
568
|
+
|
|
569
|
+
// Handler should be in a consistent state
|
|
570
|
+
expect(handler.getConnectedCount()).toBeGreaterThan(0)
|
|
571
|
+
})
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
// ==========================================================================
|
|
575
|
+
// 3. Message Ordering Guarantees
|
|
576
|
+
// ==========================================================================
|
|
577
|
+
|
|
578
|
+
describe('Message Ordering Guarantees', () => {
|
|
579
|
+
it('should deliver changes in order', async () => {
|
|
580
|
+
/**
|
|
581
|
+
* FLAKY SCENARIO: Changes should be delivered in the order they occurred,
|
|
582
|
+
* but async processing might reorder them.
|
|
583
|
+
*/
|
|
584
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
585
|
+
|
|
586
|
+
const ws = createMockWebSocket()
|
|
587
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
588
|
+
|
|
589
|
+
// Subscribe
|
|
590
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
591
|
+
type: 'subscribe',
|
|
592
|
+
id: 'sub-1',
|
|
593
|
+
payload: { table: 'users' },
|
|
594
|
+
}))
|
|
595
|
+
|
|
596
|
+
ws.send.mockClear()
|
|
597
|
+
|
|
598
|
+
// Broadcast multiple changes rapidly
|
|
599
|
+
const changeCount = 10
|
|
600
|
+
for (let i = 0; i < changeCount; i++) {
|
|
601
|
+
handler.broadcastChange({
|
|
602
|
+
table: 'users',
|
|
603
|
+
operation: 'INSERT',
|
|
604
|
+
newRow: { id: i, seq: i },
|
|
605
|
+
})
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Verify order
|
|
609
|
+
const messages = getSentMessages(ws)
|
|
610
|
+
const changeMessages = messages.filter(m => m.type === 'change')
|
|
611
|
+
|
|
612
|
+
expect(changeMessages.length).toBe(changeCount)
|
|
613
|
+
|
|
614
|
+
// Changes should be in order
|
|
615
|
+
for (let i = 0; i < changeMessages.length; i++) {
|
|
616
|
+
const payload = changeMessages[i].payload as { newRow: { seq: number } }
|
|
617
|
+
expect(payload.newRow.seq).toBe(i)
|
|
618
|
+
}
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
it('should not duplicate messages on slow consumers', async () => {
|
|
622
|
+
/**
|
|
623
|
+
* FLAKY SCENARIO: If a consumer is slow, messages might be sent multiple times.
|
|
624
|
+
*/
|
|
625
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
626
|
+
|
|
627
|
+
const ws = createMockWebSocket()
|
|
628
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
629
|
+
|
|
630
|
+
// Subscribe
|
|
631
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
632
|
+
type: 'subscribe',
|
|
633
|
+
id: 'sub-1',
|
|
634
|
+
payload: { table: 'users' },
|
|
635
|
+
}))
|
|
636
|
+
|
|
637
|
+
ws.send.mockClear()
|
|
638
|
+
|
|
639
|
+
// Simulate slow send by making it take time
|
|
640
|
+
let sendCount = 0
|
|
641
|
+
ws.send.mockImplementation(() => {
|
|
642
|
+
sendCount++
|
|
643
|
+
// Simulate slow processing
|
|
644
|
+
})
|
|
645
|
+
|
|
646
|
+
// Broadcast change
|
|
647
|
+
handler.broadcastChange({
|
|
648
|
+
table: 'users',
|
|
649
|
+
operation: 'INSERT',
|
|
650
|
+
newRow: { id: 1 },
|
|
651
|
+
})
|
|
652
|
+
|
|
653
|
+
// Small delay
|
|
654
|
+
await flushPromises()
|
|
655
|
+
|
|
656
|
+
// Broadcast another change
|
|
657
|
+
handler.broadcastChange({
|
|
658
|
+
table: 'users',
|
|
659
|
+
operation: 'INSERT',
|
|
660
|
+
newRow: { id: 2 },
|
|
661
|
+
})
|
|
662
|
+
|
|
663
|
+
// Should only have 2 sends, no duplicates
|
|
664
|
+
expect(sendCount).toBe(2)
|
|
665
|
+
})
|
|
666
|
+
|
|
667
|
+
it('should maintain ordering across multiple subscribers', async () => {
|
|
668
|
+
/**
|
|
669
|
+
* FLAKY SCENARIO: Multiple subscribers should all receive messages in
|
|
670
|
+
* the same order.
|
|
671
|
+
*/
|
|
672
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
673
|
+
|
|
674
|
+
// Create multiple WebSocket connections
|
|
675
|
+
const webSockets: MockWebSocket[] = []
|
|
676
|
+
for (let i = 0; i < 3; i++) {
|
|
677
|
+
const ws = createMockWebSocket(`ws-${i}`)
|
|
678
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
679
|
+
|
|
680
|
+
// Subscribe
|
|
681
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
682
|
+
type: 'subscribe',
|
|
683
|
+
id: `sub-${i}`,
|
|
684
|
+
payload: { table: 'users' },
|
|
685
|
+
}))
|
|
686
|
+
|
|
687
|
+
ws.send.mockClear()
|
|
688
|
+
webSockets.push(ws)
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Broadcast changes
|
|
692
|
+
const changeCount = 5
|
|
693
|
+
for (let i = 0; i < changeCount; i++) {
|
|
694
|
+
handler.broadcastChange({
|
|
695
|
+
table: 'users',
|
|
696
|
+
operation: 'INSERT',
|
|
697
|
+
newRow: { id: i, seq: i },
|
|
698
|
+
})
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// All subscribers should have received changes in the same order
|
|
702
|
+
const allOrders: number[][] = webSockets.map(ws => {
|
|
703
|
+
const messages = getSentMessages(ws)
|
|
704
|
+
const changeMessages = messages.filter(m => m.type === 'change')
|
|
705
|
+
return changeMessages.map(m => {
|
|
706
|
+
const payload = m.payload as { newRow: { seq: number } }
|
|
707
|
+
return payload.newRow.seq
|
|
708
|
+
})
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
// All orders should be identical
|
|
712
|
+
const expectedOrder = Array.from({ length: changeCount }, (_, i) => i)
|
|
713
|
+
for (const order of allOrders) {
|
|
714
|
+
expect(order).toEqual(expectedOrder)
|
|
715
|
+
}
|
|
716
|
+
})
|
|
717
|
+
})
|
|
718
|
+
|
|
719
|
+
// ==========================================================================
|
|
720
|
+
// 4. Connection State Management
|
|
721
|
+
// ==========================================================================
|
|
722
|
+
|
|
723
|
+
describe('Connection State Management', () => {
|
|
724
|
+
it('should handle WebSocket close during subscription', async () => {
|
|
725
|
+
/**
|
|
726
|
+
* FLAKY SCENARIO: WebSocket closes exactly while a subscription is being
|
|
727
|
+
* processed, leaving orphaned state.
|
|
728
|
+
*/
|
|
729
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
730
|
+
|
|
731
|
+
const ws = createMockWebSocket()
|
|
732
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
733
|
+
|
|
734
|
+
// Start subscription
|
|
735
|
+
const subscribePromise = handler.handleMessage(ws as any, JSON.stringify({
|
|
736
|
+
type: 'subscribe',
|
|
737
|
+
id: 'sub-1',
|
|
738
|
+
payload: { table: 'users' },
|
|
739
|
+
}))
|
|
740
|
+
|
|
741
|
+
// Close during subscription processing
|
|
742
|
+
ws.simulateClose(1006, 'Abnormal closure')
|
|
743
|
+
handler.handleClose(ws as any, 1006, 'Abnormal closure')
|
|
744
|
+
|
|
745
|
+
// Should complete without errors
|
|
746
|
+
await subscribePromise
|
|
747
|
+
|
|
748
|
+
// State should be clean
|
|
749
|
+
expect(handler.getConnectedCount()).toBe(0)
|
|
750
|
+
expect(handler.getSubscriptionCount()).toBe(0)
|
|
751
|
+
})
|
|
752
|
+
|
|
753
|
+
it('should clean up all resources on connection close', async () => {
|
|
754
|
+
/**
|
|
755
|
+
* FLAKY SCENARIO: Resources (timers, subscriptions, state) should be
|
|
756
|
+
* fully cleaned up, even under concurrent operations.
|
|
757
|
+
*/
|
|
758
|
+
timers = vi.useFakeTimers()
|
|
759
|
+
|
|
760
|
+
const config: CDCWebSocketConfig = {
|
|
761
|
+
heartbeatInterval: 100,
|
|
762
|
+
heartbeatTimeout: 50,
|
|
763
|
+
}
|
|
764
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
765
|
+
|
|
766
|
+
const ws = createMockWebSocket()
|
|
767
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
768
|
+
|
|
769
|
+
// Create subscriptions
|
|
770
|
+
for (let i = 0; i < 5; i++) {
|
|
771
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
772
|
+
type: 'subscribe',
|
|
773
|
+
id: `sub-${i}`,
|
|
774
|
+
payload: { table: `table-${i}` },
|
|
775
|
+
}))
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
expect(handler.getSubscriptionCount()).toBe(5)
|
|
779
|
+
|
|
780
|
+
// Close connection
|
|
781
|
+
ws.simulateClose(1000, 'Normal closure')
|
|
782
|
+
handler.handleClose(ws as any, 1000, 'Normal closure')
|
|
783
|
+
|
|
784
|
+
// All resources should be cleaned up
|
|
785
|
+
expect(handler.getSubscriptionCount()).toBe(0)
|
|
786
|
+
expect(handler.getConnectedCount()).toBe(0)
|
|
787
|
+
|
|
788
|
+
// Heartbeat timer should not fire after close
|
|
789
|
+
const sendCallsBefore = ws.send.mock.calls.length
|
|
790
|
+
await advanceTimersAndFlush(200)
|
|
791
|
+
const sendCallsAfter = ws.send.mock.calls.length
|
|
792
|
+
|
|
793
|
+
expect(sendCallsAfter).toBe(sendCallsBefore)
|
|
794
|
+
})
|
|
795
|
+
|
|
796
|
+
it('should handle error during message send', async () => {
|
|
797
|
+
/**
|
|
798
|
+
* FLAKY SCENARIO: If send() throws, should not corrupt connection state.
|
|
799
|
+
*/
|
|
800
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
801
|
+
|
|
802
|
+
const ws = createMockWebSocket()
|
|
803
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
804
|
+
|
|
805
|
+
// Subscribe
|
|
806
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
807
|
+
type: 'subscribe',
|
|
808
|
+
id: 'sub-1',
|
|
809
|
+
payload: { table: 'users' },
|
|
810
|
+
}))
|
|
811
|
+
|
|
812
|
+
ws.send.mockClear()
|
|
813
|
+
|
|
814
|
+
// Make send throw
|
|
815
|
+
ws.send.mockImplementation(() => {
|
|
816
|
+
throw new Error('Network error')
|
|
817
|
+
})
|
|
818
|
+
|
|
819
|
+
// Should not throw
|
|
820
|
+
expect(() => {
|
|
821
|
+
handler.broadcastChange({
|
|
822
|
+
table: 'users',
|
|
823
|
+
operation: 'INSERT',
|
|
824
|
+
newRow: { id: 1 },
|
|
825
|
+
})
|
|
826
|
+
}).not.toThrow()
|
|
827
|
+
|
|
828
|
+
// Handler should still be functional
|
|
829
|
+
expect(handler.getConnectedCount()).toBe(1)
|
|
830
|
+
})
|
|
831
|
+
|
|
832
|
+
it('should handle multiple connections from same client', async () => {
|
|
833
|
+
/**
|
|
834
|
+
* FLAKY SCENARIO: Same client opens multiple connections, causing
|
|
835
|
+
* potential state confusion.
|
|
836
|
+
*/
|
|
837
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
838
|
+
|
|
839
|
+
const connections: MockWebSocket[] = []
|
|
840
|
+
const connectionIds: string[] = []
|
|
841
|
+
|
|
842
|
+
// Open multiple connections
|
|
843
|
+
for (let i = 0; i < 3; i++) {
|
|
844
|
+
const ws = createMockWebSocket(`ws-same-client-${i}`)
|
|
845
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
846
|
+
|
|
847
|
+
const welcome = getLastSentMessage(ws) as any
|
|
848
|
+
connectionIds.push(welcome?.payload?.connectionId)
|
|
849
|
+
connections.push(ws)
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// Each connection should have unique ID
|
|
853
|
+
expect(new Set(connectionIds).size).toBe(3)
|
|
854
|
+
|
|
855
|
+
// Subscribe each to different tables
|
|
856
|
+
for (let i = 0; i < connections.length; i++) {
|
|
857
|
+
await handler.handleMessage(connections[i] as any, JSON.stringify({
|
|
858
|
+
type: 'subscribe',
|
|
859
|
+
id: `sub-${i}`,
|
|
860
|
+
payload: { table: `table-${i}` },
|
|
861
|
+
}))
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
expect(handler.getSubscriptionCount()).toBe(3)
|
|
865
|
+
|
|
866
|
+
// Close one connection - should not affect others
|
|
867
|
+
connections[1].simulateClose(1000, 'Normal closure')
|
|
868
|
+
handler.handleClose(connections[1] as any, 1000, 'Normal closure')
|
|
869
|
+
|
|
870
|
+
expect(handler.getConnectedCount()).toBe(2)
|
|
871
|
+
expect(handler.getSubscriptionCount()).toBe(2)
|
|
872
|
+
})
|
|
873
|
+
|
|
874
|
+
it('should timeout queued operations if reconnection fails', async () => {
|
|
875
|
+
/**
|
|
876
|
+
* FLAKY SCENARIO: Operations queued during reconnection should timeout
|
|
877
|
+
* if reconnection ultimately fails.
|
|
878
|
+
*
|
|
879
|
+
* This is a known flaky test - stream closure is not handled properly.
|
|
880
|
+
*/
|
|
881
|
+
timers = vi.useFakeTimers()
|
|
882
|
+
|
|
883
|
+
const config: CDCWebSocketConfig = {
|
|
884
|
+
reconnectDelay: 100,
|
|
885
|
+
maxReconnectAttempts: 2,
|
|
886
|
+
}
|
|
887
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
888
|
+
|
|
889
|
+
const ws = createMockWebSocket()
|
|
890
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
891
|
+
|
|
892
|
+
const welcome = getLastSentMessage(ws) as any
|
|
893
|
+
const connectionId = welcome?.payload?.connectionId
|
|
894
|
+
|
|
895
|
+
// Subscribe
|
|
896
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
897
|
+
type: 'subscribe',
|
|
898
|
+
id: 'sub-1',
|
|
899
|
+
payload: { table: 'users' },
|
|
900
|
+
}))
|
|
901
|
+
|
|
902
|
+
// Close connection
|
|
903
|
+
ws.simulateClose(1006, 'Abnormal closure')
|
|
904
|
+
handler.handleClose(ws as any, 1006, 'Abnormal closure')
|
|
905
|
+
|
|
906
|
+
// Wait for reconnection window to expire
|
|
907
|
+
await advanceTimersAndFlush(config.reconnectDelay! * (config.maxReconnectAttempts! + 1))
|
|
908
|
+
|
|
909
|
+
// Connection state should be fully cleaned up
|
|
910
|
+
expect(handler.getConnectionInfo(connectionId)).toBeNull()
|
|
911
|
+
})
|
|
912
|
+
})
|
|
913
|
+
|
|
914
|
+
// ==========================================================================
|
|
915
|
+
// 5. Edge Cases
|
|
916
|
+
// ==========================================================================
|
|
917
|
+
|
|
918
|
+
describe('Edge Cases', () => {
|
|
919
|
+
it('should handle max subscriptions limit', async () => {
|
|
920
|
+
/**
|
|
921
|
+
* Test that subscription limits are enforced.
|
|
922
|
+
*/
|
|
923
|
+
const config: CDCWebSocketConfig = {
|
|
924
|
+
maxSubscriptions: 5,
|
|
925
|
+
}
|
|
926
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any, undefined, config)
|
|
927
|
+
|
|
928
|
+
const ws = createMockWebSocket()
|
|
929
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
930
|
+
ws.send.mockClear()
|
|
931
|
+
|
|
932
|
+
// Create max subscriptions
|
|
933
|
+
for (let i = 0; i < 5; i++) {
|
|
934
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
935
|
+
type: 'subscribe',
|
|
936
|
+
id: `sub-${i}`,
|
|
937
|
+
payload: { table: `table-${i}` },
|
|
938
|
+
}))
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
const messagesBeforeLimit = getSentMessages(ws)
|
|
942
|
+
const subscribedCount = messagesBeforeLimit.filter(m => m.type === 'subscribed').length
|
|
943
|
+
expect(subscribedCount).toBe(5)
|
|
944
|
+
|
|
945
|
+
ws.send.mockClear()
|
|
946
|
+
|
|
947
|
+
// Try to exceed limit
|
|
948
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
949
|
+
type: 'subscribe',
|
|
950
|
+
id: 'sub-excess',
|
|
951
|
+
payload: { table: 'excess-table' },
|
|
952
|
+
}))
|
|
953
|
+
|
|
954
|
+
const messagesAfterLimit = getSentMessages(ws)
|
|
955
|
+
const errorMsg = messagesAfterLimit.find(m => m.type === 'error')
|
|
956
|
+
expect(errorMsg).toBeDefined()
|
|
957
|
+
expect((errorMsg?.payload as any)?.code).toBe('LIMIT_EXCEEDED')
|
|
958
|
+
})
|
|
959
|
+
|
|
960
|
+
it('should reject invalid message payloads gracefully', async () => {
|
|
961
|
+
/**
|
|
962
|
+
* Test that malformed messages are handled gracefully.
|
|
963
|
+
*/
|
|
964
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
965
|
+
|
|
966
|
+
const ws = createMockWebSocket()
|
|
967
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
968
|
+
ws.send.mockClear()
|
|
969
|
+
|
|
970
|
+
// Missing required fields
|
|
971
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
972
|
+
type: 'subscribe',
|
|
973
|
+
id: 'bad-sub',
|
|
974
|
+
payload: {}, // Missing 'table'
|
|
975
|
+
}))
|
|
976
|
+
|
|
977
|
+
const messages = getSentMessages(ws)
|
|
978
|
+
const errorMsg = messages.find(m => m.type === 'error')
|
|
979
|
+
expect(errorMsg).toBeDefined()
|
|
980
|
+
})
|
|
981
|
+
|
|
982
|
+
it('should handle WebSocket in CONNECTING state', async () => {
|
|
983
|
+
/**
|
|
984
|
+
* FLAKY SCENARIO: Operations arrive before WebSocket is fully open.
|
|
985
|
+
*/
|
|
986
|
+
handler = createCDCWebSocketHandler(mockState as any, mockExecutor as any)
|
|
987
|
+
|
|
988
|
+
const ws = createMockWebSocket()
|
|
989
|
+
ws.setReadyState(WS_CONNECTING)
|
|
990
|
+
safeHandleUpgrade(handler, mockState, ws)
|
|
991
|
+
|
|
992
|
+
// Welcome message should not be sent to CONNECTING socket
|
|
993
|
+
// (depends on implementation - some might queue)
|
|
994
|
+
|
|
995
|
+
ws.setReadyState(WS_OPEN)
|
|
996
|
+
|
|
997
|
+
// Now should be able to subscribe
|
|
998
|
+
await handler.handleMessage(ws as any, JSON.stringify({
|
|
999
|
+
type: 'subscribe',
|
|
1000
|
+
id: 'sub-1',
|
|
1001
|
+
payload: { table: 'users' },
|
|
1002
|
+
}))
|
|
1003
|
+
|
|
1004
|
+
// Should get subscribed response
|
|
1005
|
+
const messages = getSentMessages(ws)
|
|
1006
|
+
expect(messages.some(m => m.type === 'subscribed')).toBe(true)
|
|
1007
|
+
})
|
|
1008
|
+
})
|
|
1009
|
+
})
|