@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,1029 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAL to Iceberg Transformer
|
|
3
|
+
* Task: postgres-5iv - WAL to Iceberg transformation
|
|
4
|
+
*
|
|
5
|
+
* Transforms streaming WAL data into Iceberg table format for efficient querying.
|
|
6
|
+
* Implements:
|
|
7
|
+
* - Continuous transformation pipeline
|
|
8
|
+
* - Batched micro-batch processing
|
|
9
|
+
* - Schema mapping from WAL to Iceberg
|
|
10
|
+
* - Deduplication of replayed/retried WAL
|
|
11
|
+
* - Exactly-once processing semantics via checkpointing
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { SerializedWALEntry } from '../worker/wal'
|
|
15
|
+
import type { WALSegmentMetadata } from '../worker/wal-r2'
|
|
16
|
+
import { createLogger, LogLevel, type ILogger } from '@dotdo/postgres-shared'
|
|
17
|
+
|
|
18
|
+
// Re-export for external use
|
|
19
|
+
export type { R2WALStorage } from '../worker/wal-r2'
|
|
20
|
+
import type {
|
|
21
|
+
IcebergTableMetadata,
|
|
22
|
+
IcebergSnapshot,
|
|
23
|
+
IcebergSchema,
|
|
24
|
+
IcebergPartitionSpec,
|
|
25
|
+
} from './types'
|
|
26
|
+
import { IcebergWALWriter, createIcebergWALWriter } from './writer'
|
|
27
|
+
import { walEntryToParquetRecord, type WALParquetRecord } from './parquet'
|
|
28
|
+
import { createWALSchema, createWALPartitionSpec } from './schema'
|
|
29
|
+
|
|
30
|
+
// Re-export schema utils for external use
|
|
31
|
+
export { getPartitionValue, generatePartitionPath } from './schema'
|
|
32
|
+
|
|
33
|
+
// Module-level logger for transformer errors
|
|
34
|
+
const transformerLogger: ILogger = createLogger({
|
|
35
|
+
level: LogLevel.ERROR,
|
|
36
|
+
prefix: '[WALIcebergTransformer]',
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Checkpoint for tracking transformation progress
|
|
41
|
+
*/
|
|
42
|
+
export interface TransformCheckpoint {
|
|
43
|
+
/** DO ID being transformed */
|
|
44
|
+
doId: string
|
|
45
|
+
/** Last successfully processed LSN */
|
|
46
|
+
lastProcessedLsn: string
|
|
47
|
+
/** Last successfully processed timestamp */
|
|
48
|
+
lastProcessedTimestamp: number
|
|
49
|
+
/** Number of entries processed since last checkpoint */
|
|
50
|
+
entriesProcessed: number
|
|
51
|
+
/** Number of Iceberg snapshots created since last checkpoint */
|
|
52
|
+
snapshotsCreated: number
|
|
53
|
+
/** Timestamp of last checkpoint */
|
|
54
|
+
checkpointedAt: number
|
|
55
|
+
/** R2 segment keys that have been fully processed */
|
|
56
|
+
processedSegmentKeys: string[]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Transformation batch result
|
|
61
|
+
*/
|
|
62
|
+
export interface TransformBatchResult {
|
|
63
|
+
/** Number of WAL entries processed */
|
|
64
|
+
entriesProcessed: number
|
|
65
|
+
/** Number of entries skipped (duplicates) */
|
|
66
|
+
entriesSkipped: number
|
|
67
|
+
/** Iceberg snapshot created (if any) */
|
|
68
|
+
snapshot: IcebergSnapshot | null
|
|
69
|
+
/** Processing duration in ms */
|
|
70
|
+
durationMs: number
|
|
71
|
+
/** LSN range processed */
|
|
72
|
+
lsnRange: { start: string; end: string } | null
|
|
73
|
+
/** Timestamp range processed */
|
|
74
|
+
timestampRange: { start: number; end: number } | null
|
|
75
|
+
/** R2 segment keys processed */
|
|
76
|
+
segmentKeysProcessed: string[]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Transformation statistics
|
|
81
|
+
*/
|
|
82
|
+
export interface TransformerStats {
|
|
83
|
+
/** Total entries processed */
|
|
84
|
+
totalEntriesProcessed: bigint
|
|
85
|
+
/** Total entries skipped (duplicates) */
|
|
86
|
+
totalEntriesSkipped: bigint
|
|
87
|
+
/** Total Iceberg snapshots created */
|
|
88
|
+
totalSnapshotsCreated: number
|
|
89
|
+
/** Total bytes written to Iceberg */
|
|
90
|
+
totalBytesWritten: bigint
|
|
91
|
+
/** Average transformation lag in ms */
|
|
92
|
+
avgTransformLagMs: number
|
|
93
|
+
/** Last transformation timestamp */
|
|
94
|
+
lastTransformAt: number | null
|
|
95
|
+
/** Last checkpoint timestamp */
|
|
96
|
+
lastCheckpointAt: number | null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Transformer configuration
|
|
101
|
+
*/
|
|
102
|
+
export interface TransformerConfig {
|
|
103
|
+
/** R2 bucket for WAL storage */
|
|
104
|
+
walBucket: R2Bucket
|
|
105
|
+
/** R2 bucket for Iceberg storage (can be same as walBucket) */
|
|
106
|
+
icebergBucket: R2Bucket
|
|
107
|
+
/** Durable Object ID being transformed */
|
|
108
|
+
doId: string
|
|
109
|
+
/** WAL prefix in R2 (default: 'wal/') */
|
|
110
|
+
walPrefix?: string
|
|
111
|
+
/** Iceberg table path in R2 */
|
|
112
|
+
icebergTablePath: string
|
|
113
|
+
/** Batch size for micro-batch processing (default: 1000) */
|
|
114
|
+
batchSize?: number
|
|
115
|
+
/** Maximum entries per transformation cycle (default: 10000) */
|
|
116
|
+
maxEntriesPerCycle?: number
|
|
117
|
+
/** Checkpoint interval in entries (default: 1000) */
|
|
118
|
+
checkpointInterval?: number
|
|
119
|
+
/** Target transformation lag in ms (default: 300000 = 5 minutes) */
|
|
120
|
+
targetLagMs?: number
|
|
121
|
+
/** Enable deduplication (default: true) */
|
|
122
|
+
deduplication?: boolean
|
|
123
|
+
/** DO state for storing checkpoints */
|
|
124
|
+
state?: DurableObjectState
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Default configuration values
|
|
129
|
+
*/
|
|
130
|
+
const DEFAULT_CONFIG = {
|
|
131
|
+
walPrefix: 'wal/',
|
|
132
|
+
batchSize: 1000,
|
|
133
|
+
maxEntriesPerCycle: 10000,
|
|
134
|
+
checkpointInterval: 1000,
|
|
135
|
+
targetLagMs: 5 * 60 * 1000, // 5 minutes
|
|
136
|
+
deduplication: true,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Checkpoint storage key prefix
|
|
141
|
+
*/
|
|
142
|
+
const CHECKPOINT_KEY_PREFIX = '__wal_iceberg_checkpoint__'
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Processed LSN set storage key prefix
|
|
146
|
+
*/
|
|
147
|
+
const PROCESSED_LSN_KEY_PREFIX = '__wal_iceberg_processed_lsn__'
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* WAL to Iceberg Transformer
|
|
151
|
+
*
|
|
152
|
+
* Transforms WAL segments from R2 into Iceberg tables with:
|
|
153
|
+
* - Continuous micro-batch processing
|
|
154
|
+
* - Exactly-once semantics via checkpointing
|
|
155
|
+
* - Deduplication of replayed entries
|
|
156
|
+
* - Schema mapping from WAL to Iceberg format
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const transformer = new WALIcebergTransformer({
|
|
161
|
+
* walBucket: env.WAL_BUCKET,
|
|
162
|
+
* icebergBucket: env.ICEBERG_BUCKET,
|
|
163
|
+
* doId: 'my-do-id',
|
|
164
|
+
* icebergTablePath: 'iceberg/wal-table',
|
|
165
|
+
* state: ctx.storage,
|
|
166
|
+
* })
|
|
167
|
+
*
|
|
168
|
+
* // Initialize (loads checkpoint, creates Iceberg table if needed)
|
|
169
|
+
* await transformer.initialize()
|
|
170
|
+
*
|
|
171
|
+
* // Transform pending WAL entries
|
|
172
|
+
* const result = await transformer.transformBatch()
|
|
173
|
+
*
|
|
174
|
+
* // Get stats
|
|
175
|
+
* const stats = transformer.getStats()
|
|
176
|
+
* console.log(`Processed ${stats.totalEntriesProcessed} entries`)
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export class WALIcebergTransformer {
|
|
180
|
+
private walBucket: R2Bucket
|
|
181
|
+
private icebergBucket: R2Bucket
|
|
182
|
+
private doId: string
|
|
183
|
+
private walPrefix: string
|
|
184
|
+
private icebergTablePath: string
|
|
185
|
+
/** @internal Reserved for future batch processing */
|
|
186
|
+
private _batchSize: number
|
|
187
|
+
private maxEntriesPerCycle: number
|
|
188
|
+
private checkpointInterval: number
|
|
189
|
+
private targetLagMs: number
|
|
190
|
+
private deduplication: boolean
|
|
191
|
+
private state: DurableObjectState | null
|
|
192
|
+
|
|
193
|
+
private icebergWriter: IcebergWALWriter | null = null
|
|
194
|
+
private checkpoint: TransformCheckpoint | null = null
|
|
195
|
+
private processedLsns: Set<string> = new Set()
|
|
196
|
+
private initialized = false
|
|
197
|
+
|
|
198
|
+
private stats: TransformerStats = {
|
|
199
|
+
totalEntriesProcessed: 0n,
|
|
200
|
+
totalEntriesSkipped: 0n,
|
|
201
|
+
totalSnapshotsCreated: 0,
|
|
202
|
+
totalBytesWritten: 0n,
|
|
203
|
+
avgTransformLagMs: 0,
|
|
204
|
+
lastTransformAt: null,
|
|
205
|
+
lastCheckpointAt: null,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private entriesSinceCheckpoint = 0
|
|
209
|
+
|
|
210
|
+
constructor(config: TransformerConfig) {
|
|
211
|
+
this.walBucket = config.walBucket
|
|
212
|
+
this.icebergBucket = config.icebergBucket
|
|
213
|
+
this.doId = config.doId
|
|
214
|
+
this.walPrefix = config.walPrefix ?? DEFAULT_CONFIG.walPrefix
|
|
215
|
+
this.icebergTablePath = config.icebergTablePath
|
|
216
|
+
this._batchSize = config.batchSize ?? DEFAULT_CONFIG.batchSize
|
|
217
|
+
this.maxEntriesPerCycle = config.maxEntriesPerCycle ?? DEFAULT_CONFIG.maxEntriesPerCycle
|
|
218
|
+
this.checkpointInterval = config.checkpointInterval ?? DEFAULT_CONFIG.checkpointInterval
|
|
219
|
+
this.targetLagMs = config.targetLagMs ?? DEFAULT_CONFIG.targetLagMs
|
|
220
|
+
this.deduplication = config.deduplication ?? DEFAULT_CONFIG.deduplication
|
|
221
|
+
this.state = config.state ?? null
|
|
222
|
+
void this._batchSize // Reserved for future batch processing
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Initialize the transformer
|
|
227
|
+
*
|
|
228
|
+
* - Loads checkpoint from DO storage
|
|
229
|
+
* - Creates or loads Iceberg table
|
|
230
|
+
* - Initializes deduplication state
|
|
231
|
+
*/
|
|
232
|
+
async initialize(): Promise<void> {
|
|
233
|
+
if (this.initialized) {
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Load checkpoint from DO storage
|
|
238
|
+
await this.loadCheckpoint()
|
|
239
|
+
|
|
240
|
+
// Initialize Iceberg writer
|
|
241
|
+
this.icebergWriter = createIcebergWALWriter({
|
|
242
|
+
bucket: this.icebergBucket,
|
|
243
|
+
tablePath: this.icebergTablePath,
|
|
244
|
+
})
|
|
245
|
+
await this.icebergWriter.initialize()
|
|
246
|
+
|
|
247
|
+
// Load processed LSNs for deduplication (keep last N LSNs in memory)
|
|
248
|
+
if (this.deduplication) {
|
|
249
|
+
await this.loadProcessedLsns()
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
this.initialized = true
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Ensure the transformer is initialized
|
|
257
|
+
*/
|
|
258
|
+
private ensureInitialized(): void {
|
|
259
|
+
if (!this.initialized || !this.icebergWriter) {
|
|
260
|
+
throw new Error('Transformer not initialized. Call initialize() first.')
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Load checkpoint from DO storage
|
|
266
|
+
*/
|
|
267
|
+
private async loadCheckpoint(): Promise<void> {
|
|
268
|
+
if (!this.state) {
|
|
269
|
+
this.checkpoint = this.createInitialCheckpoint()
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const key = `${CHECKPOINT_KEY_PREFIX}${this.doId}`
|
|
274
|
+
const stored = await this.state.storage.get<TransformCheckpoint>(key)
|
|
275
|
+
|
|
276
|
+
if (stored) {
|
|
277
|
+
this.checkpoint = stored
|
|
278
|
+
} else {
|
|
279
|
+
this.checkpoint = this.createInitialCheckpoint()
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Create initial checkpoint
|
|
285
|
+
*/
|
|
286
|
+
private createInitialCheckpoint(): TransformCheckpoint {
|
|
287
|
+
return {
|
|
288
|
+
doId: this.doId,
|
|
289
|
+
lastProcessedLsn: '0',
|
|
290
|
+
lastProcessedTimestamp: 0,
|
|
291
|
+
entriesProcessed: 0,
|
|
292
|
+
snapshotsCreated: 0,
|
|
293
|
+
checkpointedAt: Date.now(),
|
|
294
|
+
processedSegmentKeys: [],
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Save checkpoint to DO storage
|
|
300
|
+
*/
|
|
301
|
+
private async saveCheckpoint(): Promise<void> {
|
|
302
|
+
if (!this.state || !this.checkpoint) {
|
|
303
|
+
return
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const key = `${CHECKPOINT_KEY_PREFIX}${this.doId}`
|
|
307
|
+
this.checkpoint.checkpointedAt = Date.now()
|
|
308
|
+
await this.state.storage.put(key, this.checkpoint)
|
|
309
|
+
|
|
310
|
+
this.stats.lastCheckpointAt = this.checkpoint.checkpointedAt
|
|
311
|
+
this.entriesSinceCheckpoint = 0
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Load processed LSNs for deduplication
|
|
316
|
+
*/
|
|
317
|
+
private async loadProcessedLsns(): Promise<void> {
|
|
318
|
+
if (!this.state) {
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const key = `${PROCESSED_LSN_KEY_PREFIX}${this.doId}`
|
|
323
|
+
const stored = await this.state.storage.get<string[]>(key)
|
|
324
|
+
|
|
325
|
+
if (stored) {
|
|
326
|
+
this.processedLsns = new Set(stored)
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Save processed LSNs for deduplication
|
|
332
|
+
* Only keeps the most recent LSNs to prevent unbounded growth
|
|
333
|
+
*/
|
|
334
|
+
private async saveProcessedLsns(): Promise<void> {
|
|
335
|
+
if (!this.state) {
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Keep only the most recent 10000 LSNs
|
|
340
|
+
const maxLsns = 10000
|
|
341
|
+
let lsns = Array.from(this.processedLsns)
|
|
342
|
+
if (lsns.length > maxLsns) {
|
|
343
|
+
// Sort by LSN value and keep the highest
|
|
344
|
+
lsns.sort((a, b) => BigInt(a) > BigInt(b) ? -1 : 1)
|
|
345
|
+
lsns = lsns.slice(0, maxLsns)
|
|
346
|
+
this.processedLsns = new Set(lsns)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const key = `${PROCESSED_LSN_KEY_PREFIX}${this.doId}`
|
|
350
|
+
await this.state.storage.put(key, lsns)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Check if an LSN has already been processed (for deduplication)
|
|
355
|
+
*/
|
|
356
|
+
private isProcessed(lsn: string): boolean {
|
|
357
|
+
if (!this.deduplication) {
|
|
358
|
+
return false
|
|
359
|
+
}
|
|
360
|
+
return this.processedLsns.has(lsn)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Mark an LSN as processed
|
|
365
|
+
*/
|
|
366
|
+
private markProcessed(lsn: string): void {
|
|
367
|
+
if (this.deduplication) {
|
|
368
|
+
this.processedLsns.add(lsn)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get transformation statistics
|
|
374
|
+
*/
|
|
375
|
+
getStats(): TransformerStats {
|
|
376
|
+
return { ...this.stats }
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get the current checkpoint
|
|
381
|
+
*/
|
|
382
|
+
getCheckpoint(): TransformCheckpoint | null {
|
|
383
|
+
return this.checkpoint ? { ...this.checkpoint } : null
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Get the current transformation lag in milliseconds
|
|
388
|
+
*/
|
|
389
|
+
async getCurrentLag(): Promise<number> {
|
|
390
|
+
const newestSegment = await this.getNewestWALSegment()
|
|
391
|
+
if (!newestSegment) {
|
|
392
|
+
return 0
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const now = Date.now()
|
|
396
|
+
return now - (this.checkpoint?.lastProcessedTimestamp ?? 0)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Check if transformation is within target lag
|
|
401
|
+
*/
|
|
402
|
+
async isWithinTargetLag(): Promise<boolean> {
|
|
403
|
+
const lag = await this.getCurrentLag()
|
|
404
|
+
return lag <= this.targetLagMs
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* List WAL segments that need to be processed
|
|
409
|
+
*/
|
|
410
|
+
private async listPendingWALSegments(): Promise<{ key: string; metadata: WALSegmentMetadata }[]> {
|
|
411
|
+
const prefix = `${this.walPrefix}${this.doId}/`
|
|
412
|
+
const processedKeys = new Set(this.checkpoint?.processedSegmentKeys ?? [])
|
|
413
|
+
|
|
414
|
+
const segments: { key: string; metadata: WALSegmentMetadata }[] = []
|
|
415
|
+
let cursor: string | undefined
|
|
416
|
+
|
|
417
|
+
do {
|
|
418
|
+
const listOptions: R2ListOptions = { prefix, limit: 1000 }
|
|
419
|
+
if (cursor) {
|
|
420
|
+
listOptions.cursor = cursor
|
|
421
|
+
}
|
|
422
|
+
const result = await this.walBucket.list(listOptions)
|
|
423
|
+
|
|
424
|
+
for (const obj of result.objects) {
|
|
425
|
+
// Skip already processed segments
|
|
426
|
+
if (processedKeys.has(obj.key)) {
|
|
427
|
+
continue
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Extract metadata from the key
|
|
431
|
+
const match = obj.key.match(/(\d+)-(\d+)\.wal$/)
|
|
432
|
+
if (match && match[1] && match[2]) {
|
|
433
|
+
const startLsn = match[1]
|
|
434
|
+
const endLsn = match[2]
|
|
435
|
+
|
|
436
|
+
// Check if this segment might contain new entries
|
|
437
|
+
// (endLsn > lastProcessedLsn)
|
|
438
|
+
if (BigInt(endLsn) > BigInt(this.checkpoint?.lastProcessedLsn ?? '0')) {
|
|
439
|
+
segments.push({
|
|
440
|
+
key: obj.key,
|
|
441
|
+
metadata: {
|
|
442
|
+
doId: this.doId,
|
|
443
|
+
startLsn,
|
|
444
|
+
endLsn,
|
|
445
|
+
entryCount: 0, // Will be populated when reading
|
|
446
|
+
uncompressedSize: 0,
|
|
447
|
+
compressedSize: obj.size,
|
|
448
|
+
compression: 'gzip',
|
|
449
|
+
checksum: '',
|
|
450
|
+
createdAt: obj.uploaded.getTime(),
|
|
451
|
+
windowStart: 0,
|
|
452
|
+
windowEnd: 0,
|
|
453
|
+
},
|
|
454
|
+
})
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
cursor = result.truncated ? result.cursor : undefined
|
|
460
|
+
} while (cursor)
|
|
461
|
+
|
|
462
|
+
// Sort by start LSN
|
|
463
|
+
segments.sort((a, b) => {
|
|
464
|
+
const aLsn = BigInt(a.metadata.startLsn)
|
|
465
|
+
const bLsn = BigInt(b.metadata.startLsn)
|
|
466
|
+
return aLsn < bLsn ? -1 : aLsn > bLsn ? 1 : 0
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
return segments
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Get the newest WAL segment for lag calculation
|
|
474
|
+
*/
|
|
475
|
+
private async getNewestWALSegment(): Promise<{ key: string; timestamp: number } | null> {
|
|
476
|
+
const prefix = `${this.walPrefix}${this.doId}/`
|
|
477
|
+
|
|
478
|
+
// List segments in reverse order (by key, which includes timestamp)
|
|
479
|
+
const result = await this.walBucket.list({ prefix, limit: 1 })
|
|
480
|
+
|
|
481
|
+
if (result.objects.length === 0) {
|
|
482
|
+
return null
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const obj = result.objects[0]
|
|
486
|
+
if (obj) {
|
|
487
|
+
return {
|
|
488
|
+
key: obj.key,
|
|
489
|
+
timestamp: obj.uploaded.getTime(),
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return null
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Read a WAL segment from R2
|
|
498
|
+
*/
|
|
499
|
+
private async readWALSegment(key: string): Promise<SerializedWALEntry[]> {
|
|
500
|
+
try {
|
|
501
|
+
const obj = await this.walBucket.get(key)
|
|
502
|
+
if (!obj) {
|
|
503
|
+
return []
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const metadata = obj.customMetadata as Record<string, string> | undefined
|
|
507
|
+
const compression = metadata?.compression || 'none'
|
|
508
|
+
|
|
509
|
+
let data = await obj.bytes()
|
|
510
|
+
|
|
511
|
+
// Decompress if needed
|
|
512
|
+
if (compression === 'gzip') {
|
|
513
|
+
data = await this.decompressData(data)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Parse NDJSON
|
|
517
|
+
const jsonStr = new TextDecoder().decode(data)
|
|
518
|
+
const lines = jsonStr.split('\n').filter((line) => line.trim())
|
|
519
|
+
return lines.map((line) => JSON.parse(line) as SerializedWALEntry)
|
|
520
|
+
} catch (error) {
|
|
521
|
+
transformerLogger.error('Failed to read segment', { key, error: error instanceof Error ? error.message : String(error) })
|
|
522
|
+
return []
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Decompress gzip data
|
|
528
|
+
*/
|
|
529
|
+
private async decompressData(data: Uint8Array): Promise<Uint8Array> {
|
|
530
|
+
const stream = new DecompressionStream('gzip')
|
|
531
|
+
const writer = stream.writable.getWriter()
|
|
532
|
+
const reader = stream.readable.getReader()
|
|
533
|
+
|
|
534
|
+
writer.write(data)
|
|
535
|
+
writer.close()
|
|
536
|
+
|
|
537
|
+
const chunks: Uint8Array[] = []
|
|
538
|
+
while (true) {
|
|
539
|
+
const { done, value } = await reader.read()
|
|
540
|
+
if (done) break
|
|
541
|
+
chunks.push(value)
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0)
|
|
545
|
+
const result = new Uint8Array(totalLength)
|
|
546
|
+
let offset = 0
|
|
547
|
+
for (const chunk of chunks) {
|
|
548
|
+
result.set(chunk, offset)
|
|
549
|
+
offset += chunk.length
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return result
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Transform WAL entries to Iceberg records
|
|
557
|
+
*/
|
|
558
|
+
private transformEntries(entries: SerializedWALEntry[]): {
|
|
559
|
+
records: WALParquetRecord[]
|
|
560
|
+
skipped: number
|
|
561
|
+
} {
|
|
562
|
+
const records: WALParquetRecord[] = []
|
|
563
|
+
let skipped = 0
|
|
564
|
+
|
|
565
|
+
for (const entry of entries) {
|
|
566
|
+
// Check for duplicates
|
|
567
|
+
if (this.isProcessed(entry.lsn)) {
|
|
568
|
+
skipped++
|
|
569
|
+
continue
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Transform to Parquet record
|
|
573
|
+
const record = walEntryToParquetRecord(entry, this.doId)
|
|
574
|
+
records.push(record)
|
|
575
|
+
|
|
576
|
+
// Mark as processed
|
|
577
|
+
this.markProcessed(entry.lsn)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return { records, skipped }
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Transform a batch of pending WAL entries to Iceberg
|
|
585
|
+
*
|
|
586
|
+
* This is the main transformation method. Call it periodically
|
|
587
|
+
* (e.g., via a scheduled worker or alarm) to keep transformation
|
|
588
|
+
* lag within target.
|
|
589
|
+
*/
|
|
590
|
+
async transformBatch(): Promise<TransformBatchResult> {
|
|
591
|
+
this.ensureInitialized()
|
|
592
|
+
|
|
593
|
+
const startTime = performance.now()
|
|
594
|
+
let entriesProcessed = 0
|
|
595
|
+
let entriesSkipped = 0
|
|
596
|
+
let lsnRange: { start: string; end: string } | null = null
|
|
597
|
+
let timestampRange: { start: number; end: number } | null = null
|
|
598
|
+
const segmentKeysProcessed: string[] = []
|
|
599
|
+
|
|
600
|
+
// Get pending WAL segments
|
|
601
|
+
const pendingSegments = await this.listPendingWALSegments()
|
|
602
|
+
|
|
603
|
+
if (pendingSegments.length === 0) {
|
|
604
|
+
return {
|
|
605
|
+
entriesProcessed: 0,
|
|
606
|
+
entriesSkipped: 0,
|
|
607
|
+
snapshot: null,
|
|
608
|
+
durationMs: performance.now() - startTime,
|
|
609
|
+
lsnRange: null,
|
|
610
|
+
timestampRange: null,
|
|
611
|
+
segmentKeysProcessed: [],
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Process segments in order, respecting maxEntriesPerCycle
|
|
616
|
+
for (const segment of pendingSegments) {
|
|
617
|
+
if (entriesProcessed >= this.maxEntriesPerCycle) {
|
|
618
|
+
break
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Read segment entries
|
|
622
|
+
const entries = await this.readWALSegment(segment.key)
|
|
623
|
+
if (entries.length === 0) {
|
|
624
|
+
continue
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Filter to entries after lastProcessedLsn
|
|
628
|
+
let newEntries = entries.filter(
|
|
629
|
+
(e) => BigInt(e.lsn) > BigInt(this.checkpoint?.lastProcessedLsn ?? '0')
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
if (newEntries.length === 0) {
|
|
633
|
+
// Segment fully processed, mark it
|
|
634
|
+
segmentKeysProcessed.push(segment.key)
|
|
635
|
+
continue
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Limit entries to respect maxEntriesPerCycle
|
|
639
|
+
const remainingCapacity = this.maxEntriesPerCycle - entriesProcessed
|
|
640
|
+
const segmentFullyProcessed = newEntries.length <= remainingCapacity
|
|
641
|
+
if (newEntries.length > remainingCapacity) {
|
|
642
|
+
newEntries = newEntries.slice(0, remainingCapacity)
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// Transform entries
|
|
646
|
+
const { records, skipped } = this.transformEntries(newEntries)
|
|
647
|
+
entriesSkipped += skipped
|
|
648
|
+
|
|
649
|
+
if (records.length > 0) {
|
|
650
|
+
// Add to Iceberg writer
|
|
651
|
+
this.icebergWriter!.addEntries(
|
|
652
|
+
newEntries.filter((e) => !this.isProcessed(e.lsn) || records.some((r) => r.lsn === e.lsn)),
|
|
653
|
+
this.doId
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
entriesProcessed += records.length
|
|
657
|
+
|
|
658
|
+
// Update LSN and timestamp ranges
|
|
659
|
+
const firstEntry = newEntries[0]
|
|
660
|
+
const lastEntry = newEntries[newEntries.length - 1]
|
|
661
|
+
|
|
662
|
+
if (firstEntry && (!lsnRange || BigInt(firstEntry.lsn) < BigInt(lsnRange.start))) {
|
|
663
|
+
lsnRange = lsnRange ?? { start: firstEntry.lsn, end: lastEntry!.lsn }
|
|
664
|
+
lsnRange.start = firstEntry.lsn
|
|
665
|
+
}
|
|
666
|
+
if (lastEntry && (!lsnRange || BigInt(lastEntry.lsn) > BigInt(lsnRange.end))) {
|
|
667
|
+
lsnRange = lsnRange ?? { start: firstEntry!.lsn, end: lastEntry.lsn }
|
|
668
|
+
lsnRange.end = lastEntry.lsn
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (firstEntry && (!timestampRange || firstEntry.timestamp < timestampRange.start)) {
|
|
672
|
+
timestampRange = timestampRange ?? { start: firstEntry.timestamp, end: lastEntry!.timestamp }
|
|
673
|
+
timestampRange.start = firstEntry.timestamp
|
|
674
|
+
}
|
|
675
|
+
if (lastEntry && (!timestampRange || lastEntry.timestamp > timestampRange.end)) {
|
|
676
|
+
timestampRange = timestampRange ?? { start: firstEntry!.timestamp, end: lastEntry.timestamp }
|
|
677
|
+
timestampRange.end = lastEntry.timestamp
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Update checkpoint progress
|
|
681
|
+
if (lastEntry) {
|
|
682
|
+
this.checkpoint!.lastProcessedLsn = lastEntry.lsn
|
|
683
|
+
this.checkpoint!.lastProcessedTimestamp = lastEntry.timestamp
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Only mark segment as fully processed if we processed all its entries
|
|
688
|
+
if (segmentFullyProcessed) {
|
|
689
|
+
segmentKeysProcessed.push(segment.key)
|
|
690
|
+
}
|
|
691
|
+
this.entriesSinceCheckpoint += records.length
|
|
692
|
+
|
|
693
|
+
// Checkpoint if needed
|
|
694
|
+
if (this.entriesSinceCheckpoint >= this.checkpointInterval) {
|
|
695
|
+
await this.saveCheckpoint()
|
|
696
|
+
await this.saveProcessedLsns()
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Flush to Iceberg and create snapshot
|
|
701
|
+
let snapshot: IcebergSnapshot | null = null
|
|
702
|
+
if (entriesProcessed > 0) {
|
|
703
|
+
snapshot = await this.icebergWriter!.flush()
|
|
704
|
+
|
|
705
|
+
if (snapshot) {
|
|
706
|
+
this.stats.totalSnapshotsCreated++
|
|
707
|
+
this.checkpoint!.snapshotsCreated++
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Update checkpoint with processed segments
|
|
712
|
+
this.checkpoint!.processedSegmentKeys.push(...segmentKeysProcessed)
|
|
713
|
+
this.checkpoint!.entriesProcessed += entriesProcessed
|
|
714
|
+
|
|
715
|
+
// Final checkpoint save
|
|
716
|
+
await this.saveCheckpoint()
|
|
717
|
+
await this.saveProcessedLsns()
|
|
718
|
+
|
|
719
|
+
// Update stats
|
|
720
|
+
this.stats.totalEntriesProcessed += BigInt(entriesProcessed)
|
|
721
|
+
this.stats.totalEntriesSkipped += BigInt(entriesSkipped)
|
|
722
|
+
this.stats.lastTransformAt = Date.now()
|
|
723
|
+
|
|
724
|
+
if (this.icebergWriter) {
|
|
725
|
+
const writerStats = this.icebergWriter.getStats()
|
|
726
|
+
this.stats.totalBytesWritten = writerStats.bytesWritten
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Calculate average lag
|
|
730
|
+
if (timestampRange) {
|
|
731
|
+
const lag = Date.now() - timestampRange.end
|
|
732
|
+
this.stats.avgTransformLagMs = (this.stats.avgTransformLagMs + lag) / 2
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
const durationMs = performance.now() - startTime
|
|
736
|
+
|
|
737
|
+
return {
|
|
738
|
+
entriesProcessed,
|
|
739
|
+
entriesSkipped,
|
|
740
|
+
snapshot,
|
|
741
|
+
durationMs,
|
|
742
|
+
lsnRange,
|
|
743
|
+
timestampRange,
|
|
744
|
+
segmentKeysProcessed,
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Transform all pending WAL entries until caught up
|
|
750
|
+
*
|
|
751
|
+
* Continues transforming batches until there are no more
|
|
752
|
+
* pending entries or the target lag is achieved.
|
|
753
|
+
*/
|
|
754
|
+
async transformUntilCaughtUp(
|
|
755
|
+
maxIterations = 100
|
|
756
|
+
): Promise<{
|
|
757
|
+
totalEntriesProcessed: number
|
|
758
|
+
totalEntriesSkipped: number
|
|
759
|
+
totalSnapshots: number
|
|
760
|
+
iterations: number
|
|
761
|
+
durationMs: number
|
|
762
|
+
}> {
|
|
763
|
+
const startTime = performance.now()
|
|
764
|
+
let totalEntriesProcessed = 0
|
|
765
|
+
let totalEntriesSkipped = 0
|
|
766
|
+
let totalSnapshots = 0
|
|
767
|
+
let iterations = 0
|
|
768
|
+
|
|
769
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
770
|
+
const result = await this.transformBatch()
|
|
771
|
+
iterations++
|
|
772
|
+
|
|
773
|
+
totalEntriesProcessed += result.entriesProcessed
|
|
774
|
+
totalEntriesSkipped += result.entriesSkipped
|
|
775
|
+
if (result.snapshot) {
|
|
776
|
+
totalSnapshots++
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Stop if no entries were processed (caught up)
|
|
780
|
+
if (result.entriesProcessed === 0) {
|
|
781
|
+
break
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// Stop if within target lag
|
|
785
|
+
if (await this.isWithinTargetLag()) {
|
|
786
|
+
break
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return {
|
|
791
|
+
totalEntriesProcessed,
|
|
792
|
+
totalEntriesSkipped,
|
|
793
|
+
totalSnapshots,
|
|
794
|
+
iterations,
|
|
795
|
+
durationMs: performance.now() - startTime,
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* Reset the transformer checkpoint
|
|
801
|
+
*
|
|
802
|
+
* WARNING: This will cause all WAL entries to be reprocessed.
|
|
803
|
+
* Use only for disaster recovery or testing.
|
|
804
|
+
*/
|
|
805
|
+
async resetCheckpoint(): Promise<void> {
|
|
806
|
+
this.checkpoint = this.createInitialCheckpoint()
|
|
807
|
+
this.processedLsns.clear()
|
|
808
|
+
this.entriesSinceCheckpoint = 0
|
|
809
|
+
|
|
810
|
+
if (this.state) {
|
|
811
|
+
const checkpointKey = `${CHECKPOINT_KEY_PREFIX}${this.doId}`
|
|
812
|
+
const processedKey = `${PROCESSED_LSN_KEY_PREFIX}${this.doId}`
|
|
813
|
+
await this.state.storage.delete([checkpointKey, processedKey])
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
this.stats = {
|
|
817
|
+
totalEntriesProcessed: 0n,
|
|
818
|
+
totalEntriesSkipped: 0n,
|
|
819
|
+
totalSnapshotsCreated: 0,
|
|
820
|
+
totalBytesWritten: 0n,
|
|
821
|
+
avgTransformLagMs: 0,
|
|
822
|
+
lastTransformAt: null,
|
|
823
|
+
lastCheckpointAt: null,
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Get the Iceberg table metadata
|
|
829
|
+
*/
|
|
830
|
+
getIcebergMetadata(): IcebergTableMetadata | null {
|
|
831
|
+
return this.icebergWriter?.getMetadata() ?? null
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Get the Iceberg writer statistics
|
|
836
|
+
*/
|
|
837
|
+
getIcebergWriterStats() {
|
|
838
|
+
return this.icebergWriter?.getStats() ?? null
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Create a WAL to Iceberg transformer
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```typescript
|
|
847
|
+
* const transformer = createWALIcebergTransformer({
|
|
848
|
+
* walBucket: env.WAL_BUCKET,
|
|
849
|
+
* icebergBucket: env.ICEBERG_BUCKET,
|
|
850
|
+
* doId: 'my-do-id',
|
|
851
|
+
* icebergTablePath: 'iceberg/wal-table',
|
|
852
|
+
* state: ctx.storage,
|
|
853
|
+
* })
|
|
854
|
+
*
|
|
855
|
+
* await transformer.initialize()
|
|
856
|
+
* const result = await transformer.transformBatch()
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
export function createWALIcebergTransformer(config: TransformerConfig): WALIcebergTransformer {
|
|
860
|
+
return new WALIcebergTransformer(config)
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Schema mapper for WAL entries to custom Iceberg schemas
|
|
865
|
+
*
|
|
866
|
+
* Allows mapping WAL entries to user-defined Iceberg schemas
|
|
867
|
+
* for per-table data warehousing.
|
|
868
|
+
*/
|
|
869
|
+
export interface WALSchemaMapper {
|
|
870
|
+
/** Map a WAL entry to a custom record format */
|
|
871
|
+
mapEntry(entry: SerializedWALEntry, doId: string): Record<string, unknown>
|
|
872
|
+
/** Get the Iceberg schema for the mapped records */
|
|
873
|
+
getSchema(): IcebergSchema
|
|
874
|
+
/** Get the partition spec for the mapped records */
|
|
875
|
+
getPartitionSpec(): IcebergPartitionSpec
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Default WAL schema mapper (uses the standard WAL schema)
|
|
880
|
+
*/
|
|
881
|
+
export class DefaultWALSchemaMapper implements WALSchemaMapper {
|
|
882
|
+
mapEntry(entry: SerializedWALEntry, doId: string): Record<string, unknown> {
|
|
883
|
+
return walEntryToParquetRecord(entry, doId) as unknown as Record<string, unknown>
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
getSchema(): IcebergSchema {
|
|
887
|
+
return createWALSchema()
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
getPartitionSpec(): IcebergPartitionSpec {
|
|
891
|
+
return createWALPartitionSpec()
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Per-table schema mapper
|
|
897
|
+
*
|
|
898
|
+
* Maps WAL entries to table-specific Iceberg tables,
|
|
899
|
+
* extracting row data into proper columns.
|
|
900
|
+
*/
|
|
901
|
+
export class TableSchemaMapper implements WALSchemaMapper {
|
|
902
|
+
private tableName: string
|
|
903
|
+
private schema: IcebergSchema
|
|
904
|
+
private partitionSpec: IcebergPartitionSpec
|
|
905
|
+
|
|
906
|
+
constructor(
|
|
907
|
+
tableName: string,
|
|
908
|
+
schema: IcebergSchema,
|
|
909
|
+
partitionSpec: IcebergPartitionSpec
|
|
910
|
+
) {
|
|
911
|
+
this.tableName = tableName
|
|
912
|
+
this.schema = schema
|
|
913
|
+
this.partitionSpec = partitionSpec
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
mapEntry(entry: SerializedWALEntry, doId: string): Record<string, unknown> {
|
|
917
|
+
// Only map entries for this table
|
|
918
|
+
if (entry.table !== this.tableName) {
|
|
919
|
+
throw new Error(`Entry is for table ${entry.table}, expected ${this.tableName}`)
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Extract row data
|
|
923
|
+
const rowData = entry.operation === 'DELETE' ? entry.oldRow : entry.newRow
|
|
924
|
+
if (!rowData) {
|
|
925
|
+
return {
|
|
926
|
+
__do_id: doId,
|
|
927
|
+
__lsn: entry.lsn,
|
|
928
|
+
__timestamp: entry.timestamp,
|
|
929
|
+
__operation: entry.operation,
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Map row columns to schema fields
|
|
934
|
+
const mapped: Record<string, unknown> = {
|
|
935
|
+
__do_id: doId,
|
|
936
|
+
__lsn: entry.lsn,
|
|
937
|
+
__timestamp: entry.timestamp,
|
|
938
|
+
__operation: entry.operation,
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
for (const field of this.schema.fields) {
|
|
942
|
+
const value = rowData[field.name]
|
|
943
|
+
if (value !== undefined) {
|
|
944
|
+
mapped[field.name] = value
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
return mapped
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
getSchema(): IcebergSchema {
|
|
952
|
+
return this.schema
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
getPartitionSpec(): IcebergPartitionSpec {
|
|
956
|
+
return this.partitionSpec
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Multi-table transformer that routes WAL entries to table-specific Iceberg tables
|
|
962
|
+
*/
|
|
963
|
+
export class MultiTableTransformer {
|
|
964
|
+
private transformers: Map<string, WALIcebergTransformer> = new Map()
|
|
965
|
+
private defaultTransformer: WALIcebergTransformer
|
|
966
|
+
private walBucket: R2Bucket
|
|
967
|
+
private icebergBucket: R2Bucket
|
|
968
|
+
private doId: string
|
|
969
|
+
private state: DurableObjectState | null
|
|
970
|
+
|
|
971
|
+
constructor(config: {
|
|
972
|
+
walBucket: R2Bucket
|
|
973
|
+
icebergBucket: R2Bucket
|
|
974
|
+
doId: string
|
|
975
|
+
defaultTablePath: string
|
|
976
|
+
state?: DurableObjectState
|
|
977
|
+
}) {
|
|
978
|
+
this.walBucket = config.walBucket
|
|
979
|
+
this.icebergBucket = config.icebergBucket
|
|
980
|
+
this.doId = config.doId
|
|
981
|
+
this.state = config.state ?? null
|
|
982
|
+
|
|
983
|
+
// Create default transformer for unmapped tables
|
|
984
|
+
const defaultConfig: TransformerConfig = {
|
|
985
|
+
walBucket: config.walBucket,
|
|
986
|
+
icebergBucket: config.icebergBucket,
|
|
987
|
+
doId: config.doId,
|
|
988
|
+
icebergTablePath: config.defaultTablePath,
|
|
989
|
+
}
|
|
990
|
+
if (config.state !== undefined) {
|
|
991
|
+
defaultConfig.state = config.state
|
|
992
|
+
}
|
|
993
|
+
this.defaultTransformer = createWALIcebergTransformer(defaultConfig)
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Register a table-specific transformer
|
|
998
|
+
*/
|
|
999
|
+
registerTable(tableName: string, icebergTablePath: string): void {
|
|
1000
|
+
const transformerConfig: TransformerConfig = {
|
|
1001
|
+
walBucket: this.walBucket,
|
|
1002
|
+
icebergBucket: this.icebergBucket,
|
|
1003
|
+
doId: this.doId,
|
|
1004
|
+
icebergTablePath,
|
|
1005
|
+
}
|
|
1006
|
+
if (this.state !== null) {
|
|
1007
|
+
transformerConfig.state = this.state
|
|
1008
|
+
}
|
|
1009
|
+
const transformer = createWALIcebergTransformer(transformerConfig)
|
|
1010
|
+
this.transformers.set(tableName, transformer)
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
/**
|
|
1014
|
+
* Initialize all transformers
|
|
1015
|
+
*/
|
|
1016
|
+
async initialize(): Promise<void> {
|
|
1017
|
+
await this.defaultTransformer.initialize()
|
|
1018
|
+
for (const transformer of this.transformers.values()) {
|
|
1019
|
+
await transformer.initialize()
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Get transformer for a specific table
|
|
1025
|
+
*/
|
|
1026
|
+
getTransformer(tableName: string): WALIcebergTransformer {
|
|
1027
|
+
return this.transformers.get(tableName) ?? this.defaultTransformer
|
|
1028
|
+
}
|
|
1029
|
+
}
|