@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,794 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RED Phase Tests for Concurrent Request Rate Limiting
|
|
3
|
+
* Task: postgres-1odt.1 - [RED] Add concurrent request rate limit tests
|
|
4
|
+
*
|
|
5
|
+
* These tests verify rate limiting behavior under concurrent request conditions.
|
|
6
|
+
* The tests are designed to fail initially (RED phase of TDD) because:
|
|
7
|
+
* 1. The in-memory storage implementation lacks atomic operations
|
|
8
|
+
* 2. Race conditions exist in the current sliding window algorithm
|
|
9
|
+
* 3. No proper mutex/locking mechanism exists for concurrent access
|
|
10
|
+
*
|
|
11
|
+
* Once the GREEN phase (postgres-1odt.2) implements proper concurrency handling,
|
|
12
|
+
* these tests should pass.
|
|
13
|
+
*/
|
|
14
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
15
|
+
import { Hono } from 'hono'
|
|
16
|
+
import {
|
|
17
|
+
rateLimit,
|
|
18
|
+
tokenBucket,
|
|
19
|
+
SlidingWindowRateLimiter,
|
|
20
|
+
TokenBucketRateLimiter,
|
|
21
|
+
InMemoryRateLimitStorage,
|
|
22
|
+
} from './rate-limit'
|
|
23
|
+
import type { RateLimitStorage, RateLimitWindow } from './rate-limit'
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Helper Functions
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates an array of concurrent requests to the same endpoint
|
|
31
|
+
*/
|
|
32
|
+
function createConcurrentRequests(
|
|
33
|
+
app: Hono,
|
|
34
|
+
count: number,
|
|
35
|
+
ip: string,
|
|
36
|
+
path = '/test'
|
|
37
|
+
): Promise<Response>[] {
|
|
38
|
+
return Array(count)
|
|
39
|
+
.fill(null)
|
|
40
|
+
.map(() => app.request(path, { headers: { 'CF-Connecting-IP': ip } }))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Analyzes responses from concurrent requests
|
|
45
|
+
*/
|
|
46
|
+
function analyzeResponses(responses: Response[]): {
|
|
47
|
+
successCount: number
|
|
48
|
+
limitedCount: number
|
|
49
|
+
errorCount: number
|
|
50
|
+
} {
|
|
51
|
+
return {
|
|
52
|
+
successCount: responses.filter((r) => r.status === 200).length,
|
|
53
|
+
limitedCount: responses.filter((r) => r.status === 429).length,
|
|
54
|
+
errorCount: responses.filter((r) => r.status !== 200 && r.status !== 429).length,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Atomic Operations Tests (RED - Expected to Fail)
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
describe('Concurrent request rate limiting - Atomic operations', () => {
|
|
63
|
+
let storage: InMemoryRateLimitStorage
|
|
64
|
+
|
|
65
|
+
beforeEach(() => {
|
|
66
|
+
storage = new InMemoryRateLimitStorage()
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* This test verifies that exactly N requests succeed when the limit is N,
|
|
71
|
+
* even under high concurrency. Currently FAILS due to race conditions.
|
|
72
|
+
*/
|
|
73
|
+
it.fails('should enforce EXACT rate limit under concurrent requests', async () => {
|
|
74
|
+
const app = new Hono()
|
|
75
|
+
const LIMIT = 10
|
|
76
|
+
|
|
77
|
+
app.use(
|
|
78
|
+
'*',
|
|
79
|
+
rateLimit({
|
|
80
|
+
requests: LIMIT,
|
|
81
|
+
windowMs: 60000,
|
|
82
|
+
storage,
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
app.get('/test', (c) => c.text('ok'))
|
|
86
|
+
|
|
87
|
+
// Make 100 concurrent requests with a limit of 10
|
|
88
|
+
const requests = createConcurrentRequests(app, 100, '1.2.3.4')
|
|
89
|
+
const responses = await Promise.all(requests)
|
|
90
|
+
const { successCount, limitedCount } = analyzeResponses(responses)
|
|
91
|
+
|
|
92
|
+
// With proper atomic operations, EXACTLY 10 should succeed
|
|
93
|
+
// This test will FAIL because race conditions allow more than 10
|
|
94
|
+
expect(successCount).toBe(LIMIT)
|
|
95
|
+
expect(limitedCount).toBe(90)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* This test verifies that the rate limiter uses atomic increment operations.
|
|
100
|
+
* Currently FAILS because the check-then-increment pattern is not atomic.
|
|
101
|
+
*/
|
|
102
|
+
it.fails('should use atomic check-and-increment for rate limiting', async () => {
|
|
103
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
104
|
+
requests: 5,
|
|
105
|
+
windowMs: 60000,
|
|
106
|
+
subWindows: 6,
|
|
107
|
+
storage,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// Make 20 concurrent checks on the same key
|
|
111
|
+
const promises = Array(20)
|
|
112
|
+
.fill(null)
|
|
113
|
+
.map(() => limiter.check('atomic-test-key'))
|
|
114
|
+
|
|
115
|
+
const results = await Promise.all(promises)
|
|
116
|
+
const allowedCount = results.filter((r) => !r.limited).length
|
|
117
|
+
const limitedCount = results.filter((r) => r.limited).length
|
|
118
|
+
|
|
119
|
+
// With atomic operations, exactly 5 should be allowed
|
|
120
|
+
// This test will FAIL because check-then-increment is not atomic
|
|
121
|
+
expect(allowedCount).toBe(5)
|
|
122
|
+
expect(limitedCount).toBe(15)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* This test verifies that concurrent requests don't corrupt the window state.
|
|
127
|
+
* Currently FAILS because multiple concurrent read-modify-write cycles race.
|
|
128
|
+
*/
|
|
129
|
+
it.fails('should maintain consistent window state under concurrent updates', async () => {
|
|
130
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
131
|
+
requests: 100,
|
|
132
|
+
windowMs: 60000,
|
|
133
|
+
subWindows: 10,
|
|
134
|
+
storage,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
// Make 50 concurrent requests
|
|
138
|
+
const promises = Array(50)
|
|
139
|
+
.fill(null)
|
|
140
|
+
.map(() => limiter.check('consistency-test-key'))
|
|
141
|
+
|
|
142
|
+
await Promise.all(promises)
|
|
143
|
+
|
|
144
|
+
// Read the final state directly from storage
|
|
145
|
+
const finalState = await storage.get('consistency-test-key')
|
|
146
|
+
|
|
147
|
+
// The total count should equal the number of allowed requests
|
|
148
|
+
// This test will FAIL if any updates were lost due to race conditions
|
|
149
|
+
expect(finalState).not.toBeNull()
|
|
150
|
+
expect(finalState!.total).toBe(50)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Tests that token bucket handles concurrent requests atomically
|
|
155
|
+
*/
|
|
156
|
+
it.fails('should enforce exact token bucket limits under concurrency', async () => {
|
|
157
|
+
const app = new Hono()
|
|
158
|
+
const BUCKET_SIZE = 10
|
|
159
|
+
|
|
160
|
+
app.use(
|
|
161
|
+
'*',
|
|
162
|
+
tokenBucket({
|
|
163
|
+
bucketSize: BUCKET_SIZE,
|
|
164
|
+
tokensPerSecond: 0, // No refill during test
|
|
165
|
+
storage,
|
|
166
|
+
})
|
|
167
|
+
)
|
|
168
|
+
app.get('/test', (c) => c.text('ok'))
|
|
169
|
+
|
|
170
|
+
// Make 30 concurrent requests with bucket size of 10
|
|
171
|
+
const requests = createConcurrentRequests(app, 30, '1.2.3.4')
|
|
172
|
+
const responses = await Promise.all(requests)
|
|
173
|
+
const { successCount } = analyzeResponses(responses)
|
|
174
|
+
|
|
175
|
+
// With atomic token consumption, exactly 10 should succeed
|
|
176
|
+
// This test will FAIL because token consumption is not atomic
|
|
177
|
+
expect(successCount).toBe(BUCKET_SIZE)
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Thread Safety Tests (RED - Expected to Fail)
|
|
183
|
+
// ============================================================================
|
|
184
|
+
|
|
185
|
+
describe('Concurrent request rate limiting - Thread safety', () => {
|
|
186
|
+
let storage: InMemoryRateLimitStorage
|
|
187
|
+
|
|
188
|
+
beforeEach(() => {
|
|
189
|
+
storage = new InMemoryRateLimitStorage()
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Tests that rapid successive concurrent batches maintain correct state.
|
|
194
|
+
* Currently FAILS because there's no locking between batches.
|
|
195
|
+
*/
|
|
196
|
+
it.fails('should handle rapid successive concurrent batches correctly', async () => {
|
|
197
|
+
const app = new Hono()
|
|
198
|
+
app.use(
|
|
199
|
+
'*',
|
|
200
|
+
rateLimit({
|
|
201
|
+
requests: 10,
|
|
202
|
+
windowMs: 60000,
|
|
203
|
+
storage,
|
|
204
|
+
})
|
|
205
|
+
)
|
|
206
|
+
app.get('/test', (c) => c.text('ok'))
|
|
207
|
+
|
|
208
|
+
// Send 3 rapid bursts of 5 concurrent requests each
|
|
209
|
+
const burst1 = Promise.all(createConcurrentRequests(app, 5, '1.2.3.4'))
|
|
210
|
+
const burst2 = Promise.all(createConcurrentRequests(app, 5, '1.2.3.4'))
|
|
211
|
+
const burst3 = Promise.all(createConcurrentRequests(app, 5, '1.2.3.4'))
|
|
212
|
+
|
|
213
|
+
const [responses1, responses2, responses3] = await Promise.all([burst1, burst2, burst3])
|
|
214
|
+
const allResponses = [...responses1, ...responses2, ...responses3]
|
|
215
|
+
const { successCount } = analyzeResponses(allResponses)
|
|
216
|
+
|
|
217
|
+
// With proper thread safety, exactly 10 should succeed
|
|
218
|
+
// This test will FAIL due to race conditions between bursts
|
|
219
|
+
expect(successCount).toBe(10)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Tests that rate limit state is not corrupted under stress.
|
|
224
|
+
* Currently FAILS because of read-modify-write race conditions.
|
|
225
|
+
*/
|
|
226
|
+
it.fails('should not corrupt state under high concurrency stress', async () => {
|
|
227
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
228
|
+
requests: 1000,
|
|
229
|
+
windowMs: 60000,
|
|
230
|
+
subWindows: 10,
|
|
231
|
+
storage,
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
// Create a stress test with 200 concurrent requests
|
|
235
|
+
const promises = Array(200)
|
|
236
|
+
.fill(null)
|
|
237
|
+
.map(() => limiter.check('stress-test-key'))
|
|
238
|
+
|
|
239
|
+
await Promise.all(promises)
|
|
240
|
+
|
|
241
|
+
// Verify state integrity
|
|
242
|
+
const state = await storage.get('stress-test-key')
|
|
243
|
+
expect(state).not.toBeNull()
|
|
244
|
+
|
|
245
|
+
// The sum of counts should equal total
|
|
246
|
+
const countsSum = state!.counts.reduce((a, b) => a + b, 0)
|
|
247
|
+
expect(countsSum).toBe(state!.total)
|
|
248
|
+
|
|
249
|
+
// Total should be 200 (all requests were within limit)
|
|
250
|
+
expect(state!.total).toBe(200)
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Tests interleaved operations from multiple concurrent users
|
|
255
|
+
*/
|
|
256
|
+
it.fails('should maintain isolation between concurrent users', async () => {
|
|
257
|
+
const app = new Hono()
|
|
258
|
+
app.use(
|
|
259
|
+
'*',
|
|
260
|
+
rateLimit({
|
|
261
|
+
requests: 5,
|
|
262
|
+
windowMs: 60000,
|
|
263
|
+
storage,
|
|
264
|
+
})
|
|
265
|
+
)
|
|
266
|
+
app.get('/test', (c) => c.text('ok'))
|
|
267
|
+
|
|
268
|
+
// Create interleaved requests from two users
|
|
269
|
+
const user1Requests = Array(10)
|
|
270
|
+
.fill(null)
|
|
271
|
+
.map(() => app.request('/test', { headers: { 'CF-Connecting-IP': 'user1' } }))
|
|
272
|
+
|
|
273
|
+
const user2Requests = Array(10)
|
|
274
|
+
.fill(null)
|
|
275
|
+
.map(() => app.request('/test', { headers: { 'CF-Connecting-IP': 'user2' } }))
|
|
276
|
+
|
|
277
|
+
// Interleave the requests
|
|
278
|
+
const interleaved = user1Requests.flatMap((r, i) => [r, user2Requests[i]!])
|
|
279
|
+
const responses = await Promise.all(interleaved)
|
|
280
|
+
|
|
281
|
+
// Separate responses by user
|
|
282
|
+
const user1Responses = responses.filter((_, i) => i % 2 === 0)
|
|
283
|
+
const user2Responses = responses.filter((_, i) => i % 2 === 1)
|
|
284
|
+
|
|
285
|
+
const user1Stats = analyzeResponses(user1Responses)
|
|
286
|
+
const user2Stats = analyzeResponses(user2Responses)
|
|
287
|
+
|
|
288
|
+
// Each user should have exactly 5 successful requests
|
|
289
|
+
// This test may fail if operations on one user affect another
|
|
290
|
+
expect(user1Stats.successCount).toBe(5)
|
|
291
|
+
expect(user2Stats.successCount).toBe(5)
|
|
292
|
+
})
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// ============================================================================
|
|
296
|
+
// Window Boundary Tests (RED - Expected to Fail)
|
|
297
|
+
// ============================================================================
|
|
298
|
+
|
|
299
|
+
describe('Concurrent request rate limiting - Window boundaries', () => {
|
|
300
|
+
let storage: InMemoryRateLimitStorage
|
|
301
|
+
|
|
302
|
+
beforeEach(() => {
|
|
303
|
+
vi.useFakeTimers()
|
|
304
|
+
storage = new InMemoryRateLimitStorage()
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
afterEach(() => {
|
|
308
|
+
vi.useRealTimers()
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Tests concurrent requests at the exact window boundary.
|
|
313
|
+
* Currently FAILS because rotation logic is not atomic.
|
|
314
|
+
*/
|
|
315
|
+
it.fails('should handle concurrent requests at window rotation atomically', async () => {
|
|
316
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
317
|
+
requests: 5,
|
|
318
|
+
windowMs: 10000, // 10 second window
|
|
319
|
+
subWindows: 2, // 5 second sub-windows
|
|
320
|
+
storage,
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// Make initial requests to fill one sub-window
|
|
324
|
+
await limiter.check('boundary-test')
|
|
325
|
+
await limiter.check('boundary-test')
|
|
326
|
+
await limiter.check('boundary-test')
|
|
327
|
+
|
|
328
|
+
// Advance to exactly the sub-window boundary
|
|
329
|
+
vi.advanceTimersByTime(5000)
|
|
330
|
+
|
|
331
|
+
// Now make concurrent requests at the rotation point
|
|
332
|
+
// These should trigger window rotation while handling the request
|
|
333
|
+
const promises = Array(10)
|
|
334
|
+
.fill(null)
|
|
335
|
+
.map(() => limiter.check('boundary-test'))
|
|
336
|
+
|
|
337
|
+
const results = await Promise.all(promises)
|
|
338
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
339
|
+
|
|
340
|
+
// Window rotated, so we should have room for 2 more requests (5 - 3 = 2)
|
|
341
|
+
// Plus the rotated requests freed up some capacity
|
|
342
|
+
// This test will FAIL if rotation is not atomic with the check
|
|
343
|
+
expect(allowed).toBeLessThanOrEqual(5) // Should never exceed limit
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Tests that window reset is handled correctly under concurrent load.
|
|
348
|
+
*/
|
|
349
|
+
it.fails('should handle concurrent requests during window reset correctly', async () => {
|
|
350
|
+
const app = new Hono()
|
|
351
|
+
app.use(
|
|
352
|
+
'*',
|
|
353
|
+
rateLimit({
|
|
354
|
+
requests: 5,
|
|
355
|
+
windowMs: 5000, // 5 second window
|
|
356
|
+
subWindows: 5,
|
|
357
|
+
storage,
|
|
358
|
+
})
|
|
359
|
+
)
|
|
360
|
+
app.get('/test', (c) => c.text('ok'))
|
|
361
|
+
|
|
362
|
+
// Exhaust the rate limit
|
|
363
|
+
for (let i = 0; i < 5; i++) {
|
|
364
|
+
await app.request('/test', { headers: { 'CF-Connecting-IP': '1.2.3.4' } })
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Advance time to trigger window reset
|
|
368
|
+
vi.advanceTimersByTime(5001)
|
|
369
|
+
|
|
370
|
+
// Now make concurrent requests right after reset
|
|
371
|
+
const requests = createConcurrentRequests(app, 20, '1.2.3.4')
|
|
372
|
+
const responses = await Promise.all(requests)
|
|
373
|
+
const { successCount } = analyzeResponses(responses)
|
|
374
|
+
|
|
375
|
+
// After reset, exactly 5 should succeed
|
|
376
|
+
// This test will FAIL if reset handling is not atomic
|
|
377
|
+
expect(successCount).toBe(5)
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Tests sliding window accuracy under concurrent partial window expiry.
|
|
382
|
+
*/
|
|
383
|
+
it.fails('should maintain accurate counts during partial window expiry', async () => {
|
|
384
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
385
|
+
requests: 10,
|
|
386
|
+
windowMs: 20000, // 20 second window
|
|
387
|
+
subWindows: 4, // 5 second sub-windows
|
|
388
|
+
storage,
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
// Fill first sub-window with 5 requests
|
|
392
|
+
for (let i = 0; i < 5; i++) {
|
|
393
|
+
await limiter.check('partial-expiry-test')
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Advance by one sub-window (5 seconds)
|
|
397
|
+
vi.advanceTimersByTime(5000)
|
|
398
|
+
|
|
399
|
+
// Make concurrent requests - some should succeed, some should fail
|
|
400
|
+
// based on the sliding window calculation
|
|
401
|
+
const promises = Array(10)
|
|
402
|
+
.fill(null)
|
|
403
|
+
.map(() => limiter.check('partial-expiry-test'))
|
|
404
|
+
|
|
405
|
+
const results = await Promise.all(promises)
|
|
406
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
407
|
+
|
|
408
|
+
// With 5 requests in the window and limit of 10, we should allow 5 more
|
|
409
|
+
// This test will FAIL if the count calculation races with request processing
|
|
410
|
+
expect(allowed).toBe(5)
|
|
411
|
+
})
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
// ============================================================================
|
|
415
|
+
// Distributed Rate Limiting Tests (RED - Expected to Fail)
|
|
416
|
+
// ============================================================================
|
|
417
|
+
|
|
418
|
+
describe('Concurrent request rate limiting - Distributed scenarios', () => {
|
|
419
|
+
/**
|
|
420
|
+
* Simulates distributed rate limiting with eventual consistency.
|
|
421
|
+
* Tests that rate limits are eventually enforced correctly.
|
|
422
|
+
*/
|
|
423
|
+
it.fails('should enforce global rate limit across distributed instances with shared storage', async () => {
|
|
424
|
+
// Create a shared storage that simulates network latency
|
|
425
|
+
const sharedStorage = new InMemoryRateLimitStorage()
|
|
426
|
+
const latencyMs = 10
|
|
427
|
+
|
|
428
|
+
const createDelayedStorage = (): RateLimitStorage => ({
|
|
429
|
+
async get(key: string): Promise<RateLimitWindow | null> {
|
|
430
|
+
await new Promise((r) => setTimeout(r, latencyMs))
|
|
431
|
+
return sharedStorage.get(key)
|
|
432
|
+
},
|
|
433
|
+
async set(key: string, data: RateLimitWindow, ttlMs: number): Promise<void> {
|
|
434
|
+
await new Promise((r) => setTimeout(r, latencyMs))
|
|
435
|
+
return sharedStorage.set(key, data, ttlMs)
|
|
436
|
+
},
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
// Create two "instances" with the same shared storage
|
|
440
|
+
const app1 = new Hono()
|
|
441
|
+
app1.use(
|
|
442
|
+
'*',
|
|
443
|
+
rateLimit({
|
|
444
|
+
requests: 10,
|
|
445
|
+
windowMs: 60000,
|
|
446
|
+
storage: createDelayedStorage(),
|
|
447
|
+
})
|
|
448
|
+
)
|
|
449
|
+
app1.get('/test', (c) => c.text('app1'))
|
|
450
|
+
|
|
451
|
+
const app2 = new Hono()
|
|
452
|
+
app2.use(
|
|
453
|
+
'*',
|
|
454
|
+
rateLimit({
|
|
455
|
+
requests: 10,
|
|
456
|
+
windowMs: 60000,
|
|
457
|
+
storage: createDelayedStorage(),
|
|
458
|
+
})
|
|
459
|
+
)
|
|
460
|
+
app2.get('/test', (c) => c.text('app2'))
|
|
461
|
+
|
|
462
|
+
// Make concurrent requests to both instances
|
|
463
|
+
const requests = [
|
|
464
|
+
...Array(15)
|
|
465
|
+
.fill(null)
|
|
466
|
+
.map(() => app1.request('/test', { headers: { 'CF-Connecting-IP': '1.2.3.4' } })),
|
|
467
|
+
...Array(15)
|
|
468
|
+
.fill(null)
|
|
469
|
+
.map(() => app2.request('/test', { headers: { 'CF-Connecting-IP': '1.2.3.4' } })),
|
|
470
|
+
]
|
|
471
|
+
|
|
472
|
+
const responses = await Promise.all(requests)
|
|
473
|
+
const { successCount } = analyzeResponses(responses)
|
|
474
|
+
|
|
475
|
+
// With proper distributed rate limiting, exactly 10 should succeed globally
|
|
476
|
+
// This test will FAIL because of eventual consistency issues
|
|
477
|
+
expect(successCount).toBe(10)
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Tests rate limiting with storage that has compare-and-swap semantics.
|
|
482
|
+
* Currently there's no CAS support, so this will fail.
|
|
483
|
+
*/
|
|
484
|
+
it.fails('should support compare-and-swap for atomic distributed updates', async () => {
|
|
485
|
+
// This test requires CAS semantics which don't exist yet
|
|
486
|
+
const storage = new InMemoryRateLimitStorage()
|
|
487
|
+
|
|
488
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
489
|
+
requests: 5,
|
|
490
|
+
windowMs: 60000,
|
|
491
|
+
subWindows: 6,
|
|
492
|
+
storage,
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
// Make concurrent requests that should use CAS
|
|
496
|
+
const promises = Array(20)
|
|
497
|
+
.fill(null)
|
|
498
|
+
.map(() => limiter.check('cas-test-key'))
|
|
499
|
+
|
|
500
|
+
const results = await Promise.all(promises)
|
|
501
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
502
|
+
|
|
503
|
+
// With CAS, exactly 5 should be allowed
|
|
504
|
+
expect(allowed).toBe(5)
|
|
505
|
+
})
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Tests that rate limit data is persisted correctly under concurrent writes.
|
|
509
|
+
*/
|
|
510
|
+
it.fails('should persist rate limit data correctly under concurrent writes', async () => {
|
|
511
|
+
const storage = new InMemoryRateLimitStorage()
|
|
512
|
+
|
|
513
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
514
|
+
requests: 100,
|
|
515
|
+
windowMs: 60000,
|
|
516
|
+
subWindows: 10,
|
|
517
|
+
storage,
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
// Make 50 concurrent writes
|
|
521
|
+
const writePromises = Array(50)
|
|
522
|
+
.fill(null)
|
|
523
|
+
.map(() => limiter.check('persistence-test'))
|
|
524
|
+
|
|
525
|
+
await Promise.all(writePromises)
|
|
526
|
+
|
|
527
|
+
// Verify the persisted state is correct
|
|
528
|
+
const state = await storage.get('persistence-test')
|
|
529
|
+
|
|
530
|
+
expect(state).not.toBeNull()
|
|
531
|
+
expect(state!.total).toBe(50) // All 50 writes should be recorded
|
|
532
|
+
expect(state!.counts.reduce((a, b) => a + b, 0)).toBe(50)
|
|
533
|
+
})
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
// ============================================================================
|
|
537
|
+
// Rate Limit Reset Under Concurrency Tests (RED - Expected to Fail)
|
|
538
|
+
// ============================================================================
|
|
539
|
+
|
|
540
|
+
describe('Concurrent request rate limiting - Reset behavior', () => {
|
|
541
|
+
let storage: InMemoryRateLimitStorage
|
|
542
|
+
|
|
543
|
+
beforeEach(() => {
|
|
544
|
+
vi.useFakeTimers()
|
|
545
|
+
storage = new InMemoryRateLimitStorage()
|
|
546
|
+
})
|
|
547
|
+
|
|
548
|
+
afterEach(() => {
|
|
549
|
+
vi.useRealTimers()
|
|
550
|
+
})
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Tests that reset happens exactly once even with concurrent requests.
|
|
554
|
+
*/
|
|
555
|
+
it.fails('should reset window exactly once under concurrent reset triggers', async () => {
|
|
556
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
557
|
+
requests: 5,
|
|
558
|
+
windowMs: 5000,
|
|
559
|
+
subWindows: 5,
|
|
560
|
+
storage,
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
// Fill the window
|
|
564
|
+
for (let i = 0; i < 5; i++) {
|
|
565
|
+
await limiter.check('reset-once-test')
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Move past the window expiry
|
|
569
|
+
vi.advanceTimersByTime(5001)
|
|
570
|
+
|
|
571
|
+
// Make concurrent requests that will all try to reset the window
|
|
572
|
+
const promises = Array(20)
|
|
573
|
+
.fill(null)
|
|
574
|
+
.map(() => limiter.check('reset-once-test'))
|
|
575
|
+
|
|
576
|
+
const results = await Promise.all(promises)
|
|
577
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
578
|
+
|
|
579
|
+
// After reset, exactly 5 should be allowed
|
|
580
|
+
// This test will FAIL if multiple resets occur or reset races with checks
|
|
581
|
+
expect(allowed).toBe(5)
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Tests gradual refill under concurrent token bucket requests.
|
|
586
|
+
*/
|
|
587
|
+
it.fails('should handle concurrent requests during token refill correctly', async () => {
|
|
588
|
+
const limiter = new TokenBucketRateLimiter({
|
|
589
|
+
bucketSize: 10,
|
|
590
|
+
tokensPerSecond: 5, // 5 tokens per second
|
|
591
|
+
tokensPerRequest: 1,
|
|
592
|
+
storage,
|
|
593
|
+
})
|
|
594
|
+
|
|
595
|
+
// Drain the bucket
|
|
596
|
+
for (let i = 0; i < 10; i++) {
|
|
597
|
+
await limiter.check('refill-test')
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Advance time to refill 5 tokens
|
|
601
|
+
vi.advanceTimersByTime(1000)
|
|
602
|
+
|
|
603
|
+
// Make concurrent requests for the refilled tokens
|
|
604
|
+
const promises = Array(15)
|
|
605
|
+
.fill(null)
|
|
606
|
+
.map(() => limiter.check('refill-test'))
|
|
607
|
+
|
|
608
|
+
const results = await Promise.all(promises)
|
|
609
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
610
|
+
|
|
611
|
+
// Should allow exactly 5 (the refilled tokens)
|
|
612
|
+
// This test will FAIL if refill calculation races with token consumption
|
|
613
|
+
expect(allowed).toBe(5)
|
|
614
|
+
})
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Tests that remaining count is accurate under concurrent access.
|
|
618
|
+
*/
|
|
619
|
+
it.fails('should report accurate remaining count under concurrent access', async () => {
|
|
620
|
+
const app = new Hono()
|
|
621
|
+
app.use(
|
|
622
|
+
'*',
|
|
623
|
+
rateLimit({
|
|
624
|
+
requests: 10,
|
|
625
|
+
windowMs: 60000,
|
|
626
|
+
storage,
|
|
627
|
+
})
|
|
628
|
+
)
|
|
629
|
+
app.get('/test', (c) => c.text('ok'))
|
|
630
|
+
|
|
631
|
+
// Make 5 concurrent requests
|
|
632
|
+
const requests = createConcurrentRequests(app, 5, '1.2.3.4')
|
|
633
|
+
const responses = await Promise.all(requests)
|
|
634
|
+
|
|
635
|
+
// Get all remaining counts
|
|
636
|
+
const remainingCounts = responses.map((r) =>
|
|
637
|
+
parseInt(r.headers.get('X-RateLimit-Remaining') || '0', 10)
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
// With atomic operations, remaining counts should be consecutive
|
|
641
|
+
// E.g., [9, 8, 7, 6, 5] in some order
|
|
642
|
+
const sortedCounts = [...remainingCounts].sort((a, b) => b - a)
|
|
643
|
+
const expectedCounts = [9, 8, 7, 6, 5]
|
|
644
|
+
|
|
645
|
+
// This test will FAIL if counts are duplicated due to race conditions
|
|
646
|
+
expect(sortedCounts).toEqual(expectedCounts)
|
|
647
|
+
})
|
|
648
|
+
})
|
|
649
|
+
|
|
650
|
+
// ============================================================================
|
|
651
|
+
// High-Load Stress Tests (RED - Expected to Fail)
|
|
652
|
+
// ============================================================================
|
|
653
|
+
|
|
654
|
+
describe('Concurrent request rate limiting - High load stress tests', () => {
|
|
655
|
+
let storage: InMemoryRateLimitStorage
|
|
656
|
+
|
|
657
|
+
beforeEach(() => {
|
|
658
|
+
storage = new InMemoryRateLimitStorage()
|
|
659
|
+
})
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Tests rate limiting under extreme concurrency.
|
|
663
|
+
*/
|
|
664
|
+
it.fails('should maintain correct limits under extreme concurrency', async () => {
|
|
665
|
+
const app = new Hono()
|
|
666
|
+
const LIMIT = 50
|
|
667
|
+
|
|
668
|
+
app.use(
|
|
669
|
+
'*',
|
|
670
|
+
rateLimit({
|
|
671
|
+
requests: LIMIT,
|
|
672
|
+
windowMs: 60000,
|
|
673
|
+
storage,
|
|
674
|
+
})
|
|
675
|
+
)
|
|
676
|
+
app.get('/test', (c) => c.text('ok'))
|
|
677
|
+
|
|
678
|
+
// Make 500 concurrent requests
|
|
679
|
+
const requests = createConcurrentRequests(app, 500, '1.2.3.4')
|
|
680
|
+
const responses = await Promise.all(requests)
|
|
681
|
+
const { successCount, limitedCount, errorCount } = analyzeResponses(responses)
|
|
682
|
+
|
|
683
|
+
// With proper concurrency handling:
|
|
684
|
+
// - Exactly 50 should succeed
|
|
685
|
+
// - Exactly 450 should be rate limited
|
|
686
|
+
// - No errors should occur
|
|
687
|
+
expect(errorCount).toBe(0)
|
|
688
|
+
expect(successCount).toBe(LIMIT)
|
|
689
|
+
expect(limitedCount).toBe(450)
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Tests that rate limiting works correctly with many concurrent users.
|
|
694
|
+
*/
|
|
695
|
+
it.fails('should handle many concurrent users correctly', async () => {
|
|
696
|
+
const app = new Hono()
|
|
697
|
+
const LIMIT = 3
|
|
698
|
+
const NUM_USERS = 20
|
|
699
|
+
const REQUESTS_PER_USER = 10
|
|
700
|
+
|
|
701
|
+
app.use(
|
|
702
|
+
'*',
|
|
703
|
+
rateLimit({
|
|
704
|
+
requests: LIMIT,
|
|
705
|
+
windowMs: 60000,
|
|
706
|
+
storage,
|
|
707
|
+
})
|
|
708
|
+
)
|
|
709
|
+
app.get('/test', (c) => c.text('ok'))
|
|
710
|
+
|
|
711
|
+
// Create requests for all users concurrently
|
|
712
|
+
const allRequests: Promise<Response>[] = []
|
|
713
|
+
for (let user = 0; user < NUM_USERS; user++) {
|
|
714
|
+
const userIp = `user-${user}`
|
|
715
|
+
for (let req = 0; req < REQUESTS_PER_USER; req++) {
|
|
716
|
+
allRequests.push(app.request('/test', { headers: { 'CF-Connecting-IP': userIp } }))
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const responses = await Promise.all(allRequests)
|
|
721
|
+
|
|
722
|
+
// Group responses by user and verify each user has exactly LIMIT successes
|
|
723
|
+
for (let user = 0; user < NUM_USERS; user++) {
|
|
724
|
+
const userResponses = responses.slice(user * REQUESTS_PER_USER, (user + 1) * REQUESTS_PER_USER)
|
|
725
|
+
const { successCount } = analyzeResponses(userResponses)
|
|
726
|
+
|
|
727
|
+
// Each user should have exactly LIMIT successful requests
|
|
728
|
+
// This test will FAIL if user isolation is compromised under load
|
|
729
|
+
expect(successCount).toBe(LIMIT)
|
|
730
|
+
}
|
|
731
|
+
})
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Tests memory consistency under sustained high load.
|
|
735
|
+
*/
|
|
736
|
+
it.fails('should maintain memory consistency under sustained load', async () => {
|
|
737
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
738
|
+
requests: 1000,
|
|
739
|
+
windowMs: 60000,
|
|
740
|
+
subWindows: 10,
|
|
741
|
+
storage,
|
|
742
|
+
})
|
|
743
|
+
|
|
744
|
+
// Simulate sustained load with multiple batches
|
|
745
|
+
const batches = 10
|
|
746
|
+
const requestsPerBatch = 100
|
|
747
|
+
|
|
748
|
+
for (let batch = 0; batch < batches; batch++) {
|
|
749
|
+
const promises = Array(requestsPerBatch)
|
|
750
|
+
.fill(null)
|
|
751
|
+
.map(() => limiter.check('sustained-load-key'))
|
|
752
|
+
|
|
753
|
+
await Promise.all(promises)
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Verify final state is consistent
|
|
757
|
+
const state = await storage.get('sustained-load-key')
|
|
758
|
+
expect(state).not.toBeNull()
|
|
759
|
+
|
|
760
|
+
const totalRequests = batches * requestsPerBatch // 1000
|
|
761
|
+
expect(state!.total).toBe(totalRequests)
|
|
762
|
+
expect(state!.counts.reduce((a, b) => a + b, 0)).toBe(totalRequests)
|
|
763
|
+
})
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Tests that no requests are lost under high concurrency.
|
|
767
|
+
*/
|
|
768
|
+
it.fails('should not lose any requests under high concurrency', async () => {
|
|
769
|
+
const limiter = new SlidingWindowRateLimiter({
|
|
770
|
+
requests: 10000, // High limit so nothing is rate limited
|
|
771
|
+
windowMs: 60000,
|
|
772
|
+
subWindows: 10,
|
|
773
|
+
storage,
|
|
774
|
+
})
|
|
775
|
+
|
|
776
|
+
const totalRequests = 500
|
|
777
|
+
|
|
778
|
+
// Make all requests concurrently
|
|
779
|
+
const promises = Array(totalRequests)
|
|
780
|
+
.fill(null)
|
|
781
|
+
.map(() => limiter.check('no-loss-key'))
|
|
782
|
+
|
|
783
|
+
const results = await Promise.all(promises)
|
|
784
|
+
|
|
785
|
+
// All should succeed (within limit)
|
|
786
|
+
const allowed = results.filter((r) => !r.limited).length
|
|
787
|
+
expect(allowed).toBe(totalRequests)
|
|
788
|
+
|
|
789
|
+
// Verify storage reflects all requests
|
|
790
|
+
const state = await storage.get('no-loss-key')
|
|
791
|
+
expect(state).not.toBeNull()
|
|
792
|
+
expect(state!.total).toBe(totalRequests)
|
|
793
|
+
})
|
|
794
|
+
})
|