pipework 0.251.0 → 0.252.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/core/config/load.d.ts +2 -0
- package/dist/core/config/load.d.ts.map +1 -1
- package/dist/core/config/load.js +1 -0
- package/dist/core/config/load.js.map +1 -1
- package/dist/core/config/namespace.d.ts +1 -0
- package/dist/core/config/namespace.d.ts.map +1 -1
- package/dist/core/config/schema.d.ts +2 -0
- package/dist/core/config/schema.d.ts.map +1 -1
- package/dist/core/config/schema.js +1 -0
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/surface/types.d.ts +1 -0
- package/dist/core/surface/types.d.ts.map +1 -1
- package/dist/data/db/namespace.d.ts +3 -0
- package/dist/data/db/namespace.d.ts.map +1 -1
- package/dist/data/db/namespace.js +3 -0
- package/dist/data/db/namespace.js.map +1 -1
- package/dist/data/db/pool.d.ts.map +1 -1
- package/dist/data/db/pool.js +6 -1
- package/dist/data/db/pool.js.map +1 -1
- package/dist/data/db/query-label.d.ts +5 -0
- package/dist/data/db/query-label.d.ts.map +1 -0
- package/dist/data/db/query-label.js +11 -0
- package/dist/data/db/query-label.js.map +1 -0
- package/dist/data/db/query-watch.d.ts +21 -0
- package/dist/data/db/query-watch.d.ts.map +1 -0
- package/dist/data/db/query-watch.js +90 -0
- package/dist/data/db/query-watch.js.map +1 -0
- package/dist/data/query/postgres-js/driver.js +1 -1
- package/dist/data/query/postgres-js/driver.js.map +1 -1
- package/dist/data/query/postgres-js/session.d.ts +5 -1
- package/dist/data/query/postgres-js/session.d.ts.map +1 -1
- package/dist/data/query/postgres-js/session.js +16 -11
- package/dist/data/query/postgres-js/session.js.map +1 -1
- package/dist/data/query/utils.d.ts +2 -0
- package/dist/data/query/utils.d.ts.map +1 -1
- package/dist/data/query/utils.js.map +1 -1
- package/dist/infra/credits/schema.d.ts +1 -1
- package/dist/test/plugin.d.ts.map +1 -1
- package/dist/test/plugin.js +10 -4
- package/dist/test/plugin.js.map +1 -1
- package/package.json +4 -3
- package/src/async/jobs/abortable-delay.ts +18 -0
- package/src/async/jobs/claims.ts +52 -0
- package/src/async/jobs/cron.ts +179 -0
- package/src/async/jobs/errors.ts +56 -0
- package/src/async/jobs/exclusion.ts +117 -0
- package/src/async/jobs/execute.ts +219 -0
- package/src/async/jobs/index.ts +10 -0
- package/src/async/jobs/listener.ts +135 -0
- package/src/async/jobs/namespace.ts +20 -0
- package/src/async/jobs/queue-door.ts +44 -0
- package/src/async/jobs/queue.ts +1012 -0
- package/src/async/jobs/run-script.ts +67 -0
- package/src/async/jobs/scheduler.ts +218 -0
- package/src/async/jobs/schedules-table.ts +37 -0
- package/src/async/jobs/serialize-error.ts +48 -0
- package/src/async/jobs/table.ts +191 -0
- package/src/async/pipeline/define.ts +53 -0
- package/src/async/pipeline/errors.ts +35 -0
- package/src/async/pipeline/execute.ts +53 -0
- package/src/async/pipeline/index.ts +13 -0
- package/src/async/pipeline/namespace.ts +12 -0
- package/src/async/pipeline/resume.ts +67 -0
- package/src/async/pipeline/run-steps.ts +98 -0
- package/src/async/pipeline/types.ts +57 -0
- package/src/async/state-machine/define.ts +64 -0
- package/src/async/state-machine/errors.ts +29 -0
- package/src/async/state-machine/index.ts +3 -0
- package/src/async/state-machine/namespace.ts +12 -0
- package/src/async/state-machine/transition.ts +90 -0
- package/src/async/state-machine/types.ts +37 -0
- package/src/async/steps/errors.ts +31 -0
- package/src/async/steps/graph.ts +1214 -0
- package/src/async/steps/hash.ts +40 -0
- package/src/async/steps/index.ts +7 -0
- package/src/async/steps/namespace.ts +7 -0
- package/src/async/steps/table.ts +97 -0
- package/src/async/steps/types.ts +318 -0
- package/src/audit/chain/index.ts +9 -0
- package/src/audit/chain/install.ts +113 -0
- package/src/audit/chain/retire.ts +52 -0
- package/src/audit/chain/verify.ts +257 -0
- package/src/audit/query/cursor.ts +37 -0
- package/src/audit/query/index.ts +9 -0
- package/src/audit/query/query.ts +223 -0
- package/src/audit/schema/audit-record-fields.ts +68 -0
- package/src/audit/schema/audit-record.ts +23 -0
- package/src/auth/auth/audit.ts +31 -0
- package/src/auth/auth/chain.ts +84 -0
- package/src/auth/auth/cookie.ts +136 -0
- package/src/auth/auth/email-links.ts +311 -0
- package/src/auth/auth/guard.ts +128 -0
- package/src/auth/auth/index.ts +18 -0
- package/src/auth/auth/multi-org.ts +337 -0
- package/src/auth/auth/namespace.ts +34 -0
- package/src/auth/auth/parse-expiry.ts +13 -0
- package/src/auth/auth/passwords.ts +110 -0
- package/src/auth/auth/schema.ts +110 -0
- package/src/auth/auth/sessions.ts +565 -0
- package/src/auth/auth/sign-in.ts +156 -0
- package/src/auth/auth/signing-keys.ts +69 -0
- package/src/auth/auth/types.ts +26 -0
- package/src/auth/auth/uuid.ts +10 -0
- package/src/auth/rbac/cache.ts +55 -0
- package/src/auth/rbac/check.ts +30 -0
- package/src/auth/rbac/create.ts +35 -0
- package/src/auth/rbac/index.ts +5 -0
- package/src/auth/rbac/middleware.ts +20 -0
- package/src/auth/rbac/namespace.ts +15 -0
- package/src/auth/rbac/resolve.ts +31 -0
- package/src/auth/rbac/schema.sql +31 -0
- package/src/auth/rbac/seed.ts +67 -0
- package/src/auth/rbac/tables.ts +32 -0
- package/src/auth/rbac/types.ts +65 -0
- package/src/auth/tenant/extract.ts +33 -0
- package/src/auth/tenant/in-tenant.ts +49 -0
- package/src/auth/tenant/index.ts +7 -0
- package/src/auth/tenant/namespace.ts +23 -0
- package/src/auth/tenant/propagate.ts +20 -0
- package/src/auth/tenant/rls.ts +120 -0
- package/src/auth/tenant/scope.ts +33 -0
- package/src/auth/tenant/scoped-db.ts +581 -0
- package/src/auth/tenant/types.ts +14 -0
- package/src/auth/tenant/validate.ts +27 -0
- package/src/cli/commands/add.ts +158 -0
- package/src/cli/commands/alerts.ts +98 -0
- package/src/cli/commands/check.ts +1418 -0
- package/src/cli/commands/codemod.ts +78 -0
- package/src/cli/commands/db.ts +356 -0
- package/src/cli/commands/dev.ts +101 -0
- package/src/cli/commands/generate.ts +75 -0
- package/src/cli/commands/init.ts +36 -0
- package/src/cli/commands/install.ts +28 -0
- package/src/cli/commands/lint.ts +62 -0
- package/src/cli/commands/migrate.ts +132 -0
- package/src/cli/commands/openapi.ts +63 -0
- package/src/cli/commands/remove.ts +72 -0
- package/src/cli/commands/run.ts +50 -0
- package/src/cli/commands/scope.ts +54 -0
- package/src/cli/commands/serve.ts +68 -0
- package/src/cli/commands/shard.ts +31 -0
- package/src/cli/commands/shared/config-pipework-version.ts +28 -0
- package/src/cli/commands/shared/find-config.ts +22 -0
- package/src/cli/commands/shared/load-config.ts +35 -0
- package/src/cli/commands/shared/pnpm-install.ts +95 -0
- package/src/cli/commands/shared/report-removed.ts +8 -0
- package/src/cli/commands/sync.ts +32 -0
- package/src/cli/commands/test.ts +307 -0
- package/src/cli/commands/upgrade.ts +48 -0
- package/src/cli/dev-bootstrap.ts +24 -0
- package/src/cli/errors.ts +10 -0
- package/src/cli/index.ts +303 -0
- package/src/cli/output.ts +17 -0
- package/src/cli/port.ts +15 -0
- package/src/cli/surface-kinds.ts +20 -0
- package/src/client/index.ts +4 -0
- package/src/client/poll.ts +130 -0
- package/src/client/report-fault.ts +119 -0
- package/src/core/config/app-pool.ts +19 -0
- package/src/core/config/aws-env.ts +29 -0
- package/src/core/config/base-dir.ts +24 -0
- package/src/core/config/discover.ts +64 -0
- package/src/core/config/env-resolve.ts +87 -0
- package/src/core/config/env-types.ts +116 -0
- package/src/core/config/env.ts +55 -0
- package/src/core/config/errors.ts +9 -0
- package/src/core/config/import-config.ts +40 -0
- package/src/core/config/index.ts +8 -0
- package/src/core/config/load.ts +417 -0
- package/src/core/config/namespace.ts +14 -0
- package/src/core/config/resolve.ts +195 -0
- package/src/core/config/schema.ts +488 -0
- package/src/core/config/statement-observer.ts +48 -0
- package/src/core/config/ts-inline-hooks.ts +75 -0
- package/src/core/config/ts-register.ts +4 -0
- package/src/core/config/ts-resolve-hooks.ts +101 -0
- package/src/core/errors/base.ts +49 -0
- package/src/core/errors/http.ts +146 -0
- package/src/core/errors/index.ts +2 -0
- package/src/core/errors/namespace.ts +31 -0
- package/src/core/lifecycle/drain.ts +33 -0
- package/src/core/lifecycle/health.ts +72 -0
- package/src/core/lifecycle/index.ts +4 -0
- package/src/core/lifecycle/namespace.ts +7 -0
- package/src/core/lifecycle/startup.ts +102 -0
- package/src/core/lifecycle/types.ts +36 -0
- package/src/core/logging/context.ts +60 -0
- package/src/core/logging/error-chain.ts +68 -0
- package/src/core/logging/index.ts +5 -0
- package/src/core/logging/logger.ts +65 -0
- package/src/core/logging/namespace.ts +16 -0
- package/src/core/logging/proxy.ts +22 -0
- package/src/core/logging/redact-match.ts +24 -0
- package/src/core/logging/types.ts +47 -0
- package/src/core/pipework.ts +566 -0
- package/src/core/runtime/broker.ts +69 -0
- package/src/core/surface/http.ts +133 -0
- package/src/core/surface/index.ts +11 -0
- package/src/core/surface/job-timeout.ts +40 -0
- package/src/core/surface/namespace.ts +13 -0
- package/src/core/surface/script.ts +33 -0
- package/src/core/surface/start.ts +142 -0
- package/src/core/surface/types.ts +225 -0
- package/src/core/surface/validate.ts +88 -0
- package/src/core/surface/worker.ts +528 -0
- package/src/core/validation/connectivity.ts +49 -0
- package/src/core/validation/domain.ts +99 -0
- package/src/core/validation/index.ts +5 -0
- package/src/core/validation/queue-tables.ts +312 -0
- package/src/core/validation/rls-role.ts +138 -0
- package/src/core/validation/startup.ts +51 -0
- package/src/core/validation/surfaces.ts +65 -0
- package/src/core/validation/types.ts +25 -0
- package/src/data/db/advisory-lock.ts +55 -0
- package/src/data/db/aggregates.ts +172 -0
- package/src/data/db/array-elements.ts +111 -0
- package/src/data/db/bulk-set.ts +53 -0
- package/src/data/db/col/index.ts +14 -0
- package/src/data/db/composed.ts +53 -0
- package/src/data/db/db.ts +276 -0
- package/src/data/db/excluded.ts +16 -0
- package/src/data/db/expressions.ts +473 -0
- package/src/data/db/filter.ts +90 -0
- package/src/data/db/function-source.ts +114 -0
- package/src/data/db/identifiers.ts +16 -0
- package/src/data/db/idx/index.ts +9 -0
- package/src/data/db/in-list.ts +49 -0
- package/src/data/db/index.ts +9 -0
- package/src/data/db/insert-split.ts +137 -0
- package/src/data/db/instrumentation.ts +82 -0
- package/src/data/db/maintenance.ts +28 -0
- package/src/data/db/namespace.ts +107 -0
- package/src/data/db/owner-labels.ts +9 -0
- package/src/data/db/pool.ts +187 -0
- package/src/data/db/query-label.ts +13 -0
- package/src/data/db/query-watch.ts +116 -0
- package/src/data/db/raw-client-warning.ts +37 -0
- package/src/data/db/readonly.ts +23 -0
- package/src/data/db/reservation.ts +151 -0
- package/src/data/db/schema-features.ts +14 -0
- package/src/data/db/serializable.ts +83 -0
- package/src/data/db/sql.ts +1 -0
- package/src/data/db/timeouts.ts +76 -0
- package/src/data/db/types.ts +18 -0
- package/src/data/db/unbound.ts +33 -0
- package/src/data/db/values.ts +29 -0
- package/src/data/domain/brand.ts +15 -0
- package/src/data/domain/build-factory.ts +193 -0
- package/src/data/domain/build-schema.ts +161 -0
- package/src/data/domain/build-table.ts +355 -0
- package/src/data/domain/define.ts +239 -0
- package/src/data/domain/external-registry.ts +34 -0
- package/src/data/domain/external.ts +77 -0
- package/src/data/domain/field.ts +279 -0
- package/src/data/domain/index.ts +13 -0
- package/src/data/domain/naming.ts +6 -0
- package/src/data/domain/projections.ts +57 -0
- package/src/data/domain/trace-safe-projection.ts +31 -0
- package/src/data/domain/traits.ts +108 -0
- package/src/data/domain/types.ts +289 -0
- package/src/data/jsonb/composed.ts +18 -0
- package/src/data/jsonb/index.ts +1 -0
- package/src/data/jsonb/namespace.ts +30 -0
- package/src/data/jsonb/query.ts +86 -0
- package/src/data/migrate/append-only-generate.ts +47 -0
- package/src/data/migrate/applied.ts +47 -0
- package/src/data/migrate/apply.ts +309 -0
- package/src/data/migrate/check.ts +119 -0
- package/src/data/migrate/diff.ts +357 -0
- package/src/data/migrate/door-generate.ts +130 -0
- package/src/data/migrate/framework-rls.ts +58 -0
- package/src/data/migrate/generate.ts +201 -0
- package/src/data/migrate/history.ts +215 -0
- package/src/data/migrate/index.ts +9 -0
- package/src/data/migrate/internal-definitions.ts +175 -0
- package/src/data/migrate/post-process.ts +73 -0
- package/src/data/migrate/pragma.ts +73 -0
- package/src/data/migrate/provision-framework.ts +147 -0
- package/src/data/migrate/rls-generate.ts +61 -0
- package/src/data/migrate/run.ts +124 -0
- package/src/data/migrate/safety.ts +167 -0
- package/src/data/migrate/snapshot.ts +368 -0
- package/src/data/migrate/sql-emit.ts +392 -0
- package/src/data/migrate/statements.ts +312 -0
- package/src/data/query/alias.ts +126 -0
- package/src/data/query/batch.ts +8 -0
- package/src/data/query/cache/core/cache.ts +78 -0
- package/src/data/query/cache/core/index.ts +1 -0
- package/src/data/query/cache/core/types.ts +29 -0
- package/src/data/query/cache/readme.md +230 -0
- package/src/data/query/casing.ts +76 -0
- package/src/data/query/collation.ts +11 -0
- package/src/data/query/column-builder.ts +370 -0
- package/src/data/query/column.ts +150 -0
- package/src/data/query/entity.ts +42 -0
- package/src/data/query/errors.ts +33 -0
- package/src/data/query/index.ts +14 -0
- package/src/data/query/logger.ts +47 -0
- package/src/data/query/operations.ts +45 -0
- package/src/data/query/pg-core/alias.ts +12 -0
- package/src/data/query/pg-core/checks.ts +32 -0
- package/src/data/query/pg-core/columns/all.ts +71 -0
- package/src/data/query/pg-core/columns/bigint.ts +110 -0
- package/src/data/query/pg-core/columns/bigserial.ts +128 -0
- package/src/data/query/pg-core/columns/boolean.ts +43 -0
- package/src/data/query/pg-core/columns/char.ts +85 -0
- package/src/data/query/pg-core/columns/cidr.ts +43 -0
- package/src/data/query/pg-core/columns/common.ts +366 -0
- package/src/data/query/pg-core/columns/custom.ts +232 -0
- package/src/data/query/pg-core/columns/date.common.ts +15 -0
- package/src/data/query/pg-core/columns/date.ts +112 -0
- package/src/data/query/pg-core/columns/double-precision.ts +55 -0
- package/src/data/query/pg-core/columns/enum.ts +201 -0
- package/src/data/query/pg-core/columns/index.ts +35 -0
- package/src/data/query/pg-core/columns/inet.ts +43 -0
- package/src/data/query/pg-core/columns/int.common.ts +57 -0
- package/src/data/query/pg-core/columns/integer.ts +53 -0
- package/src/data/query/pg-core/columns/interval.ts +83 -0
- package/src/data/query/pg-core/columns/json.ts +58 -0
- package/src/data/query/pg-core/columns/jsonb.ts +56 -0
- package/src/data/query/pg-core/columns/line.ts +117 -0
- package/src/data/query/pg-core/columns/macaddr.ts +43 -0
- package/src/data/query/pg-core/columns/macaddr8.ts +43 -0
- package/src/data/query/pg-core/columns/numeric.ts +227 -0
- package/src/data/query/pg-core/columns/point.ts +127 -0
- package/src/data/query/pg-core/columns/postgis_extension/geometry.ts +119 -0
- package/src/data/query/pg-core/columns/postgis_extension/utils.ts +47 -0
- package/src/data/query/pg-core/columns/real.ts +58 -0
- package/src/data/query/pg-core/columns/serial.ts +55 -0
- package/src/data/query/pg-core/columns/smallint.ts +53 -0
- package/src/data/query/pg-core/columns/smallserial.ts +60 -0
- package/src/data/query/pg-core/columns/text.ts +67 -0
- package/src/data/query/pg-core/columns/time.ts +72 -0
- package/src/data/query/pg-core/columns/timestamp.ts +163 -0
- package/src/data/query/pg-core/columns/uuid.ts +51 -0
- package/src/data/query/pg-core/columns/varchar.ts +89 -0
- package/src/data/query/pg-core/columns/vector_extension/bit.ts +68 -0
- package/src/data/query/pg-core/columns/vector_extension/halfvec.ts +80 -0
- package/src/data/query/pg-core/columns/vector_extension/sparsevec.ts +67 -0
- package/src/data/query/pg-core/columns/vector_extension/vector.ts +80 -0
- package/src/data/query/pg-core/db.ts +674 -0
- package/src/data/query/pg-core/dialect.ts +1404 -0
- package/src/data/query/pg-core/expressions.ts +25 -0
- package/src/data/query/pg-core/foreign-keys.ts +130 -0
- package/src/data/query/pg-core/index.ts +21 -0
- package/src/data/query/pg-core/indexes.ts +276 -0
- package/src/data/query/pg-core/policies.ts +56 -0
- package/src/data/query/pg-core/primary-keys.ts +62 -0
- package/src/data/query/pg-core/query-builders/count.ts +86 -0
- package/src/data/query/pg-core/query-builders/delete.ts +293 -0
- package/src/data/query/pg-core/query-builders/index.ts +7 -0
- package/src/data/query/pg-core/query-builders/insert.ts +452 -0
- package/src/data/query/pg-core/query-builders/query-builder.ts +123 -0
- package/src/data/query/pg-core/query-builders/query.ts +157 -0
- package/src/data/query/pg-core/query-builders/raw.ts +49 -0
- package/src/data/query/pg-core/query-builders/refresh-materialized-view.ts +108 -0
- package/src/data/query/pg-core/query-builders/select.ts +1346 -0
- package/src/data/query/pg-core/query-builders/select.types.ts +437 -0
- package/src/data/query/pg-core/query-builders/update.ts +626 -0
- package/src/data/query/pg-core/roles.ts +41 -0
- package/src/data/query/pg-core/schema.ts +72 -0
- package/src/data/query/pg-core/sequence.ts +41 -0
- package/src/data/query/pg-core/session.ts +292 -0
- package/src/data/query/pg-core/subquery.ts +46 -0
- package/src/data/query/pg-core/table.ts +252 -0
- package/src/data/query/pg-core/unique-constraint.ts +73 -0
- package/src/data/query/pg-core/utils/array.ts +95 -0
- package/src/data/query/pg-core/utils/index.ts +1 -0
- package/src/data/query/pg-core/utils.ts +104 -0
- package/src/data/query/pg-core/view-base.ts +14 -0
- package/src/data/query/pg-core/view-common.ts +1 -0
- package/src/data/query/pg-core/view.ts +435 -0
- package/src/data/query/pg-core/with-builder.ts +41 -0
- package/src/data/query/postgres-js/README.md +46 -0
- package/src/data/query/postgres-js/array-parser.ts +45 -0
- package/src/data/query/postgres-js/driver-error-boundary.ts +149 -0
- package/src/data/query/postgres-js/driver.ts +163 -0
- package/src/data/query/postgres-js/index.ts +2 -0
- package/src/data/query/postgres-js/session.ts +234 -0
- package/src/data/query/primary-key.ts +11 -0
- package/src/data/query/query-builders/query-builder.ts +19 -0
- package/src/data/query/query-builders/select.types.ts +175 -0
- package/src/data/query/query-promise.ts +35 -0
- package/src/data/query/relations.ts +725 -0
- package/src/data/query/runnable-query.ts +12 -0
- package/src/data/query/selection-proxy.ts +121 -0
- package/src/data/query/session.ts +8 -0
- package/src/data/query/sql/expressions/conditions.ts +741 -0
- package/src/data/query/sql/expressions/index.ts +2 -0
- package/src/data/query/sql/expressions/select.ts +45 -0
- package/src/data/query/sql/functions/aggregate.ts +129 -0
- package/src/data/query/sql/functions/index.ts +2 -0
- package/src/data/query/sql/functions/vector.ts +178 -0
- package/src/data/query/sql/index.ts +3 -0
- package/src/data/query/sql/sql.ts +794 -0
- package/src/data/query/subquery.ts +53 -0
- package/src/data/query/table.ts +208 -0
- package/src/data/query/table.utils.ts +2 -0
- package/src/data/query/tracing-utils.ts +3 -0
- package/src/data/query/tracing.ts +11 -0
- package/src/data/query/utils.ts +357 -0
- package/src/data/query/version.ts +4 -0
- package/src/data/query/view-common.ts +1 -0
- package/src/data/schema/branded.ts +13 -0
- package/src/data/schema/generated/coerce.ts +5 -0
- package/src/data/schema/generated/combinator.ts +6 -0
- package/src/data/schema/generated/encoding.ts +5 -0
- package/src/data/schema/generated/error.ts +6 -0
- package/src/data/schema/generated/format.ts +5 -0
- package/src/data/schema/generated/type-constructor.ts +10 -0
- package/src/data/schema/generated/type.ts +6 -0
- package/src/data/schema/index.ts +6 -0
- package/src/data/schema/json-schema.ts +33 -0
- package/src/data/schema/namespace.ts +55 -0
- package/src/data/schema/parse.ts +39 -0
- package/src/data/schema/types.ts +39 -0
- package/src/data/temporal/append-only.ts +134 -0
- package/src/data/temporal/close.ts +27 -0
- package/src/data/temporal/columns.ts +10 -0
- package/src/data/temporal/definition-queries.ts +70 -0
- package/src/data/temporal/errors.ts +10 -0
- package/src/data/temporal/get-current.ts +22 -0
- package/src/data/temporal/index.ts +9 -0
- package/src/data/temporal/namespace.ts +36 -0
- package/src/data/temporal/query.ts +25 -0
- package/src/data/temporal/resolve.ts +17 -0
- package/src/data/temporal/revise.ts +67 -0
- package/src/data/temporal/types.ts +22 -0
- package/src/data/valve/artifact.ts +33 -0
- package/src/data/valve/contract-diff.ts +21 -0
- package/src/data/valve/cross.ts +57 -0
- package/src/data/valve/crossing-ledger.ts +50 -0
- package/src/data/valve/decision.ts +44 -0
- package/src/data/valve/durable-crossing.ts +52 -0
- package/src/data/valve/execute-crossing.ts +77 -0
- package/src/data/valve/faucet.ts +56 -0
- package/src/data/valve/gate.ts +114 -0
- package/src/data/valve/graph.ts +77 -0
- package/src/data/valve/index.ts +53 -0
- package/src/data/valve/namespace.ts +57 -0
- package/src/data/valve/registry.ts +50 -0
- package/src/data/valve/schema/valve-crossing-fields.ts +23 -0
- package/src/data/valve/schema/valve-crossing.ts +9 -0
- package/src/data/valve/supply.ts +154 -0
- package/src/data/valve/types.ts +143 -0
- package/src/data/vector/columns.ts +27 -0
- package/src/data/vector/index.ts +4 -0
- package/src/data/vector/namespace.ts +33 -0
- package/src/data/vector/query.ts +85 -0
- package/src/data/vector/validate.ts +16 -0
- package/src/data/write/audit/actor.ts +15 -0
- package/src/data/write/audit/audit-columns.ts +18 -0
- package/src/data/write/audit/audit-select.ts +111 -0
- package/src/data/write/audit/bound-transaction.ts +14 -0
- package/src/data/write/audit/cte-compile.ts +32 -0
- package/src/data/write/audit/decode-returning.ts +47 -0
- package/src/data/write/audit/final-select.ts +43 -0
- package/src/data/write/audit/infra-audit.ts +36 -0
- package/src/data/write/audit/primary-key.ts +65 -0
- package/src/data/write/audit/projection.ts +41 -0
- package/src/data/write/audit/read-touches.ts +86 -0
- package/src/data/write/audit/touch-match.ts +78 -0
- package/src/data/write/audit/verb-delete.ts +62 -0
- package/src/data/write/audit/verb-insert.ts +36 -0
- package/src/data/write/audit/verb-select.ts +47 -0
- package/src/data/write/audit/verb-update.ts +60 -0
- package/src/data/write/audit/verb-upsert.ts +104 -0
- package/src/data/write/conflict.ts +43 -0
- package/src/data/write/delete.ts +38 -0
- package/src/data/write/execute.ts +243 -0
- package/src/data/write/index.ts +11 -0
- package/src/data/write/insert.ts +63 -0
- package/src/data/write/state.ts +43 -0
- package/src/data/write/update.ts +54 -0
- package/src/data/write/upsert.ts +58 -0
- package/src/data/write/values.ts +19 -0
- package/src/index.ts +230 -0
- package/src/infra/access-links/code.ts +70 -0
- package/src/infra/access-links/handle.ts +892 -0
- package/src/infra/access-links/index.ts +9 -0
- package/src/infra/access-links/namespace.ts +30 -0
- package/src/infra/access-links/person-check.ts +177 -0
- package/src/infra/access-links/schema.ts +71 -0
- package/src/infra/alerts/async-sources.ts +231 -0
- package/src/infra/alerts/audit.ts +36 -0
- package/src/infra/alerts/beat.ts +123 -0
- package/src/infra/alerts/client-faults.ts +111 -0
- package/src/infra/alerts/faults.ts +156 -0
- package/src/infra/alerts/handle.ts +778 -0
- package/src/infra/alerts/http.ts +192 -0
- package/src/infra/alerts/index.ts +12 -0
- package/src/infra/alerts/infra-sources.ts +180 -0
- package/src/infra/alerts/namespace.ts +81 -0
- package/src/infra/alerts/redact.ts +21 -0
- package/src/infra/alerts/request-faults.ts +41 -0
- package/src/infra/alerts/schema.ts +124 -0
- package/src/infra/alerts/sinks.ts +125 -0
- package/src/infra/alerts/source-options.ts +26 -0
- package/src/infra/alerts/sources.ts +503 -0
- package/src/infra/alerts/subsystem-sources.ts +137 -0
- package/src/infra/audit/emit.ts +87 -0
- package/src/infra/audit/index.ts +2 -0
- package/src/infra/audit/namespace.ts +22 -0
- package/src/infra/audit/schema.sql +35 -0
- package/src/infra/audit/types.ts +18 -0
- package/src/infra/aws/credentials.ts +147 -0
- package/src/infra/aws/sigv4.ts +140 -0
- package/src/infra/cache/create.ts +58 -0
- package/src/infra/cache/entry.ts +81 -0
- package/src/infra/cache/index.ts +4 -0
- package/src/infra/cache/namespace.ts +10 -0
- package/src/infra/cache/tenant.ts +93 -0
- package/src/infra/cache/types.ts +24 -0
- package/src/infra/crawl/audit.ts +35 -0
- package/src/infra/crawl/errors.ts +25 -0
- package/src/infra/crawl/handle.ts +693 -0
- package/src/infra/crawl/index.ts +9 -0
- package/src/infra/crawl/links.ts +160 -0
- package/src/infra/crawl/namespace.ts +36 -0
- package/src/infra/crawl/robots.ts +100 -0
- package/src/infra/crawl/schema.ts +89 -0
- package/src/infra/credit-line/handle.ts +883 -0
- package/src/infra/credit-line/index.ts +6 -0
- package/src/infra/credit-line/namespace.ts +7 -0
- package/src/infra/credit-line/schema.ts +96 -0
- package/src/infra/credits/handle.ts +706 -0
- package/src/infra/credits/index.ts +5 -0
- package/src/infra/credits/namespace.ts +7 -0
- package/src/infra/credits/schema.ts +83 -0
- package/src/infra/email/audit.ts +36 -0
- package/src/infra/email/inbound.ts +622 -0
- package/src/infra/email/index.ts +11 -0
- package/src/infra/email/mail.ts +517 -0
- package/src/infra/email/mime.ts +447 -0
- package/src/infra/email/namespace.ts +22 -0
- package/src/infra/email/providers.ts +111 -0
- package/src/infra/email/schema.ts +96 -0
- package/src/infra/email/sns.ts +200 -0
- package/src/infra/email/unsubscribe.ts +44 -0
- package/src/infra/fetch/address.ts +88 -0
- package/src/infra/fetch/connect-retry.ts +87 -0
- package/src/infra/fetch/handle.ts +329 -0
- package/src/infra/fetch/index.ts +7 -0
- package/src/infra/fetch/namespace.ts +70 -0
- package/src/infra/idempotency/index.ts +3 -0
- package/src/infra/idempotency/middleware.ts +87 -0
- package/src/infra/idempotency/store.ts +92 -0
- package/src/infra/idempotency/types.ts +30 -0
- package/src/infra/join-requests/handle.ts +312 -0
- package/src/infra/join-requests/index.ts +2 -0
- package/src/infra/join-requests/namespace.ts +7 -0
- package/src/infra/join-requests/schema.ts +33 -0
- package/src/infra/outbox/core.ts +165 -0
- package/src/infra/quota/errors.ts +32 -0
- package/src/infra/quota/handle.ts +215 -0
- package/src/infra/quota/index.ts +5 -0
- package/src/infra/quota/namespace.ts +7 -0
- package/src/infra/quota/schema.ts +15 -0
- package/src/infra/storage/backend.ts +34 -0
- package/src/infra/storage/handle.ts +513 -0
- package/src/infra/storage/index.ts +9 -0
- package/src/infra/storage/local.ts +104 -0
- package/src/infra/storage/namespace.ts +13 -0
- package/src/infra/storage/s3.ts +257 -0
- package/src/infra/storage/schema.ts +24 -0
- package/src/infra/support/handle.ts +854 -0
- package/src/infra/support/http.ts +229 -0
- package/src/infra/support/index.ts +7 -0
- package/src/infra/support/namespace.ts +12 -0
- package/src/infra/support/schema.ts +96 -0
- package/src/infra/webhook/inbound.ts +45 -0
- package/src/infra/webhook/index.ts +5 -0
- package/src/infra/webhook/namespace.ts +24 -0
- package/src/infra/webhook/outbound.ts +315 -0
- package/src/infra/webhook/sign.ts +32 -0
- package/src/infra/webhook/verify.ts +82 -0
- package/src/invariants/assert.ts +26 -0
- package/src/invariants/index.ts +1 -0
- package/src/lint/config.ts +56 -0
- package/src/lint/doctrine.ts +163 -0
- package/src/lint/include.ts +97 -0
- package/src/lint/index.ts +3 -0
- package/src/lint/preset.ts +10 -0
- package/src/lint/resolver.ts +218 -0
- package/src/lint/rules/no-reexports.ts +46 -0
- package/src/request/behavior/audited.ts +85 -0
- package/src/request/behavior/cached.ts +62 -0
- package/src/request/behavior/compose.ts +28 -0
- package/src/request/behavior/index.ts +5 -0
- package/src/request/behavior/namespace.ts +16 -0
- package/src/request/behavior/types.ts +26 -0
- package/src/request/behavior/versioned.ts +54 -0
- package/src/request/context/create.ts +103 -0
- package/src/request/context/guard.ts +49 -0
- package/src/request/context/index.ts +4 -0
- package/src/request/context/run-in-transaction.ts +200 -0
- package/src/request/context/store.ts +28 -0
- package/src/request/context/types.ts +50 -0
- package/src/request/di/builder.ts +535 -0
- package/src/request/di/index.ts +8 -0
- package/src/request/di/resolve.ts +271 -0
- package/src/request/di/types.ts +262 -0
- package/src/request/fitting/namespace.ts +7 -0
- package/src/request/fixture/batch.ts +71 -0
- package/src/request/fixture/builder.ts +26 -0
- package/src/request/fixture/errors.ts +10 -0
- package/src/request/fixture/index.ts +8 -0
- package/src/request/fixture/namespace.ts +23 -0
- package/src/request/fixture/paginate.ts +44 -0
- package/src/request/fixture/to-handlers.ts +260 -0
- package/src/request/fixture/types.ts +79 -0
- package/src/request/flow/act-as.ts +78 -0
- package/src/request/flow/namespace.ts +17 -0
- package/src/request/http/error-step.ts +42 -0
- package/src/request/http/file.ts +141 -0
- package/src/request/http/index.ts +4 -0
- package/src/request/http/middleware.ts +141 -0
- package/src/request/http/namespace.ts +5 -0
- package/src/request/http/rate-limit-classes.ts +170 -0
- package/src/request/http/response.ts +82 -0
- package/src/request/http/server.ts +916 -0
- package/src/request/http/sniff.ts +261 -0
- package/src/request/http/types.ts +250 -0
- package/src/request/http/upload.ts +284 -0
- package/src/request/internal/text.ts +6 -0
- package/src/request/openapi/generate.ts +205 -0
- package/src/request/openapi/index.ts +2 -0
- package/src/request/openapi/namespace.ts +7 -0
- package/src/test/auth.ts +13 -0
- package/src/test/auto-setup.ts +45 -0
- package/src/test/context.ts +91 -0
- package/src/test/crawl-fixture.ts +157 -0
- package/src/test/discover-fork.ts +17 -0
- package/src/test/fingerprint.ts +135 -0
- package/src/test/globals.d.ts +7 -0
- package/src/test/index.ts +19 -0
- package/src/test/namespace.ts +87 -0
- package/src/test/plugin.ts +189 -0
- package/src/test/progress.ts +185 -0
- package/src/test/reap-after-run.ts +28 -0
- package/src/test/reap.ts +286 -0
- package/src/test/reset.ts +253 -0
- package/src/test/savepoints.ts +172 -0
- package/src/test/setup.ts +1422 -0
- package/src/test/system-channel.ts +50 -0
- package/src/test/vitest-plugin.ts +142 -0
- package/src/test/vitest-workspace.ts +507 -0
- package/src/test/vitest.ts +333 -0
- package/src/test/watch.ts +105 -0
- package/src/trace/capture/bounded-serializer.ts +146 -0
- package/src/trace/cardinality/analyze.ts +173 -0
- package/src/trace/cardinality/branch-context.ts +214 -0
- package/src/trace/cardinality/check.ts +33 -0
- package/src/trace/cardinality/classify-edge.ts +64 -0
- package/src/trace/cardinality/structural-max.ts +107 -0
- package/src/trace/check/coverage-check.ts +188 -0
- package/src/trace/check/flow-check.ts +103 -0
- package/src/trace/check/flow-step-site.ts +234 -0
- package/src/trace/check/io-pattern.ts +116 -0
- package/src/trace/codemod/add-cardinality.ts +152 -0
- package/src/trace/codemod/run.ts +80 -0
- package/src/trace/entry/child-trace.ts +21 -0
- package/src/trace/entry/close-trace.ts +87 -0
- package/src/trace/entry/finalize-trace.ts +28 -0
- package/src/trace/entry/open-trace.ts +138 -0
- package/src/trace/entry/parent-trace.ts +20 -0
- package/src/trace/entry/parse-traceparent.ts +39 -0
- package/src/trace/entry/process-start.ts +38 -0
- package/src/trace/entry/trace-context.ts +26 -0
- package/src/trace/entry/tracing-enabled.ts +10 -0
- package/src/trace/external/record.ts +195 -0
- package/src/trace/external/report.ts +66 -0
- package/src/trace/namespace.ts +19 -0
- package/src/trace/partition/day.ts +47 -0
- package/src/trace/partition/index.ts +14 -0
- package/src/trace/partition/partition-name.ts +23 -0
- package/src/trace/partition/plan.ts +82 -0
- package/src/trace/partition/schedule.ts +26 -0
- package/src/trace/partition/startup-hook.ts +39 -0
- package/src/trace/partition/sync.ts +154 -0
- package/src/trace/partition/tables.ts +53 -0
- package/src/trace/read/tree.ts +83 -0
- package/src/trace/retain/copy-on-error.ts +76 -0
- package/src/trace/runtime/expire-stale-traces.ts +54 -0
- package/src/trace/runtime/flow-step.ts +147 -0
- package/src/trace/runtime/flush-steps.ts +31 -0
- package/src/trace/runtime/pending-writes.ts +54 -0
- package/src/trace/runtime/step-buffer.ts +298 -0
- package/src/trace/runtime/step-error.ts +21 -0
- package/src/trace/runtime/step-meta.ts +55 -0
- package/src/trace/runtime/thenable.ts +12 -0
- package/src/trace/runtime/truncate-trace.ts +62 -0
- package/src/trace/schema/trace-fields.ts +52 -0
- package/src/trace/schema/trace-retained.ts +22 -0
- package/src/trace/schema/trace-step-fields.ts +44 -0
- package/src/trace/schema/trace-step-retained.ts +25 -0
- package/src/trace/schema/trace-step.ts +18 -0
- package/src/trace/schema/trace.ts +12 -0
- package/src/trace/transformer/apply.ts +79 -0
- package/src/trace/transformer/build-meta-literal.ts +30 -0
- package/src/trace/transformer/find-flow-step-sites.ts +85 -0
- package/src/trace/transformer/inject-flow-step-import.ts +39 -0
- package/src/trace/transformer/transform-error.ts +14 -0
- package/src/trace/transformer/transform-flow-steps.ts +123 -0
- package/src/trace/transformer/wrap-function-declaration.ts +62 -0
- package/src/trace/transformer/wrap-variable-declaration.ts +67 -0
- package/src/workspace/affected.ts +110 -0
- package/src/workspace/changed-files.ts +163 -0
- package/src/workspace/check-deps.ts +213 -0
- package/src/workspace/checksum.ts +20 -0
- package/src/workspace/dependency-graph.ts +67 -0
- package/src/workspace/detect-pipework-copies.ts +93 -0
- package/src/workspace/discover.ts +206 -0
- package/src/workspace/generate.ts +401 -0
- package/src/workspace/index.ts +7 -0
- package/src/workspace/module-imports-pipework.ts +39 -0
- package/src/workspace/module-package-name.ts +12 -0
- package/src/workspace/scrub-git-env.ts +23 -0
- package/src/workspace/source-paths.ts +36 -0
- package/src/workspace/sync.ts +182 -0
- package/dist/REFERENCE.md +0 -1477
- package/dist/infra/access-links/rate-limit.d.ts +0 -10
- package/dist/infra/access-links/rate-limit.d.ts.map +0 -1
- package/dist/infra/access-links/rate-limit.js +0 -28
- package/dist/infra/access-links/rate-limit.js.map +0 -1
- package/dist/infra/email/sigv4.d.ts +0 -24
- package/dist/infra/email/sigv4.d.ts.map +0 -1
- package/dist/infra/email/sigv4.js +0 -55
- package/dist/infra/email/sigv4.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// The partitioned tables the substrate manages, plus the retention window each
|
|
2
|
+
// one obeys. Three retention classes share one partition lifecycle:
|
|
3
|
+
//
|
|
4
|
+
// - **hot** (`trace`, `trace_step`) — `hotRetentionDays`, short-lived.
|
|
5
|
+
// - **cold** (`trace_retained`, `trace_step_retained`) — `errorRetentionDays`,
|
|
6
|
+
// copy-on-error survives past hot retention.
|
|
7
|
+
// - **audit** (`audit_record`) — `auditRetentionDays`, long / indefinite; the
|
|
8
|
+
// audit projection lives independently of trace storage.
|
|
9
|
+
//
|
|
10
|
+
// Partition creation uses the same `partitionLeadDays` for all three classes —
|
|
11
|
+
// inserts on any class must never race partition creation.
|
|
12
|
+
|
|
13
|
+
import { trace } from '../schema/trace.js'
|
|
14
|
+
import { traceStep } from '../schema/trace-step.js'
|
|
15
|
+
import { traceRetained } from '../schema/trace-retained.js'
|
|
16
|
+
import { traceStepRetained } from '../schema/trace-step-retained.js'
|
|
17
|
+
import { auditRecord } from '../../audit/schema/audit-record.js'
|
|
18
|
+
|
|
19
|
+
export type RetentionClass = 'hot' | 'cold' | 'audit'
|
|
20
|
+
|
|
21
|
+
export interface PartitionedTraceTable {
|
|
22
|
+
/** The parent table's wire name — partitions are children of this. */
|
|
23
|
+
readonly parent: string
|
|
24
|
+
readonly retention: RetentionClass
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const PARTITIONED_TRACE_TABLES: readonly PartitionedTraceTable[] = [
|
|
28
|
+
{ parent: trace.$name, retention: 'hot' },
|
|
29
|
+
{ parent: traceStep.$name, retention: 'hot' },
|
|
30
|
+
{ parent: traceRetained.$name, retention: 'cold' },
|
|
31
|
+
{ parent: traceStepRetained.$name, retention: 'cold' },
|
|
32
|
+
{ parent: auditRecord.$name, retention: 'audit' },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Wire names of the framework-owned partitioned tables. A `pipework generate`
|
|
37
|
+
* must not emit these into an application migration (a bare `CREATE TABLE` of a
|
|
38
|
+
* `PARTITION BY RANGE` table accepts no inserts), and the test harness
|
|
39
|
+
* provisions them — parent plus day partitions — itself. Issue #313.
|
|
40
|
+
*/
|
|
41
|
+
export const PARTITIONED_TRACE_TABLE_NAMES: ReadonlySet<string> = new Set(
|
|
42
|
+
PARTITIONED_TRACE_TABLES.map(t => t.parent),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Each step table with the trace table its foreign key points at. A day's step
|
|
47
|
+
* partition must go before the trace partition it references, so retention
|
|
48
|
+
* drops the two together.
|
|
49
|
+
*/
|
|
50
|
+
export const STEP_TABLE_PARENTS: ReadonlyMap<string, string> = new Map([
|
|
51
|
+
[traceStep.$name, trace.$name],
|
|
52
|
+
[traceStepRetained.$name, traceRetained.$name],
|
|
53
|
+
])
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// `trace.tree`: every hot trace sharing a root, with its steps.
|
|
2
|
+
|
|
3
|
+
import { sql } from '../../data/db/sql.js'
|
|
4
|
+
import type { DB } from '../../data/db/index.js'
|
|
5
|
+
|
|
6
|
+
/** One step of a trace. `ref` is the flow step's `path:symbol`, or `external:<name>` for a recorded or point-event step. */
|
|
7
|
+
export interface TraceStepNode {
|
|
8
|
+
readonly id: string
|
|
9
|
+
readonly parentStepId: string | null
|
|
10
|
+
readonly ref: string
|
|
11
|
+
readonly status: 'ok' | 'error'
|
|
12
|
+
readonly startedAt: Date
|
|
13
|
+
readonly completedAt: Date | null
|
|
14
|
+
/** The step's captured inputs (one entry per captured argument), or `null` when none were captured. */
|
|
15
|
+
readonly capturedInputs: unknown
|
|
16
|
+
readonly error: unknown
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** One trace of the tree, with its steps ordered by `seq`. */
|
|
20
|
+
export interface TraceNode {
|
|
21
|
+
readonly id: string
|
|
22
|
+
readonly parentId: string | null
|
|
23
|
+
readonly entryKind: 'http' | 'job' | 'cron' | 'test'
|
|
24
|
+
readonly tenant: string | null
|
|
25
|
+
readonly requestId: string | null
|
|
26
|
+
readonly startedAt: Date
|
|
27
|
+
readonly steps: readonly TraceStepNode[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The traces that share a root id, ordered by when they opened. */
|
|
31
|
+
export interface TraceTree {
|
|
32
|
+
readonly traces: readonly TraceNode[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const str = (v: unknown): string | null => (v === null || v === undefined ? null : String(v))
|
|
36
|
+
const date = (v: unknown): Date => (v instanceof Date ? v : new Date(String(v)))
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Reads the hot `trace` and `trace_step` rows whose root is `rootId`: the
|
|
40
|
+
* request's trace and the traces of the jobs it queued. Rows already moved to
|
|
41
|
+
* the retained tables are not read. The read runs on `db` as given, so the
|
|
42
|
+
* tables' tenant policies apply: a connection with a tenant setting sees that
|
|
43
|
+
* tenant's rows, and only an unrestricted one (the table owner or a role that
|
|
44
|
+
* bypasses row-level security, as in tests) sees every tenant's. An unknown
|
|
45
|
+
* root returns no traces.
|
|
46
|
+
*/
|
|
47
|
+
export async function tree(db: DB, rootId: string): Promise<TraceTree> {
|
|
48
|
+
const traces = await db.execute(sql`
|
|
49
|
+
SELECT "id", "parent_id", "entry_kind", "tenant_id", "request_id", "opened_at"
|
|
50
|
+
FROM "trace" WHERE "root_id" = ${rootId}::uuid ORDER BY "opened_at", "id"`)
|
|
51
|
+
if (traces.length === 0) return { traces: [] }
|
|
52
|
+
const steps = await db.execute(sql`
|
|
53
|
+
SELECT s."trace_id", s."id", s."parent_step_id", s."flow_step_ref", s."status", s."started_at",
|
|
54
|
+
s."completed_at", s."captured_inputs", s."error"
|
|
55
|
+
FROM "trace_step" s JOIN "trace" t ON t."id" = s."trace_id" AND t."opened_day" = s."trace_day"
|
|
56
|
+
WHERE t."root_id" = ${rootId}::uuid ORDER BY s."trace_id", s."seq"`)
|
|
57
|
+
const byTrace = new Map<string, TraceStepNode[]>()
|
|
58
|
+
for (const r of steps) {
|
|
59
|
+
const list = byTrace.get(String(r['trace_id'])) ?? []
|
|
60
|
+
list.push({
|
|
61
|
+
id: String(r['id']),
|
|
62
|
+
parentStepId: str(r['parent_step_id']),
|
|
63
|
+
ref: String(r['flow_step_ref']),
|
|
64
|
+
status: r['status'] as 'ok' | 'error',
|
|
65
|
+
startedAt: date(r['started_at']),
|
|
66
|
+
completedAt: r['completed_at'] === null ? null : date(r['completed_at']),
|
|
67
|
+
capturedInputs: r['captured_inputs'],
|
|
68
|
+
error: r['error'],
|
|
69
|
+
})
|
|
70
|
+
byTrace.set(String(r['trace_id']), list)
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
traces: traces.map(r => ({
|
|
74
|
+
id: String(r['id']),
|
|
75
|
+
parentId: str(r['parent_id']),
|
|
76
|
+
entryKind: r['entry_kind'] as TraceNode['entryKind'],
|
|
77
|
+
tenant: str(r['tenant_id']),
|
|
78
|
+
requestId: str(r['request_id']),
|
|
79
|
+
startedAt: date(r['opened_at']),
|
|
80
|
+
steps: byTrace.get(String(r['id'])) ?? [],
|
|
81
|
+
})),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copy-on-error: when a trace ends badly (error / truncated / expired), the hot
|
|
2
|
+
// `trace` / `trace_step` partitions it lives in will be dropped on the normal
|
|
3
|
+
// `hotRetentionDays` schedule. Before that happens the errored trace — and its
|
|
4
|
+
// ancestry spine up to the root — is copied into the cold `trace_retained` /
|
|
5
|
+
// `trace_step_retained` tables, which keep the longer `errorRetentionDays`
|
|
6
|
+
// window.
|
|
7
|
+
//
|
|
8
|
+
// Only the parent chain is followed (`parent_id`): not siblings, not the step
|
|
9
|
+
// tree (`parent_step_id`). The spine is what you need to read an errored trace
|
|
10
|
+
// in context. Each copied trace brings all of its own steps.
|
|
11
|
+
//
|
|
12
|
+
// The copy is idempotent — `ON CONFLICT DO NOTHING` against each cold table's
|
|
13
|
+
// composite primary key — so re-running after a crash, or copying a trace whose
|
|
14
|
+
// ancestor was already retained by an earlier error, is a no-op.
|
|
15
|
+
|
|
16
|
+
import { sql } from '../../data/db/sql.js'
|
|
17
|
+
import type { DB } from '../../data/db/index.js'
|
|
18
|
+
import { quoteIdentifier } from '../../data/db/identifiers.js'
|
|
19
|
+
import { withMaintenance } from '../../data/db/maintenance.js'
|
|
20
|
+
import { camelToSnake } from '../../data/domain/naming.js'
|
|
21
|
+
import { traceFields } from '../schema/trace-fields.js'
|
|
22
|
+
import { traceStepFields } from '../schema/trace-step-fields.js'
|
|
23
|
+
|
|
24
|
+
export interface CopyOnErrorResult {
|
|
25
|
+
/** Rows newly inserted into `trace_retained` (rows already retained excluded). */
|
|
26
|
+
readonly traces: number
|
|
27
|
+
/** Rows newly inserted into `trace_step_retained`. */
|
|
28
|
+
readonly steps: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function columnList(keys: string[], label: string, prefix = ''): string {
|
|
32
|
+
return keys.map(k => `${prefix}${quoteIdentifier(camelToSnake(k), label)}`).join(', ')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const TRACE_COLUMNS = columnList(Object.keys(traceFields), 'trace column')
|
|
36
|
+
const TRACE_STEP_COLUMNS = columnList(Object.keys(traceStepFields), 'trace step column')
|
|
37
|
+
const TRACE_STEP_COLUMNS_FROM_STEP = columnList(Object.keys(traceStepFields), 'trace step column', 's.')
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Copy an errored trace and its parent spine into the cold retained tables.
|
|
41
|
+
*
|
|
42
|
+
* `traceId` is the trace that ended badly. Its ancestry is walked through
|
|
43
|
+
* `parent_id` to the root; every trace on that spine, plus all of their steps,
|
|
44
|
+
* is inserted into `trace_retained` / `trace_step_retained`. Returns the count
|
|
45
|
+
* of rows actually inserted — zero for both when everything was already
|
|
46
|
+
* retained, or when `traceId` does not exist.
|
|
47
|
+
*/
|
|
48
|
+
export async function copyTraceOnError(db: DB, traceId: string): Promise<CopyOnErrorResult> {
|
|
49
|
+
// Reads the whole parent spine, which may cross tenants, so the copy is a maintenance pass.
|
|
50
|
+
const rows = await withMaintenance(db, tx => tx.execute(sql`
|
|
51
|
+
WITH RECURSIVE spine AS (
|
|
52
|
+
SELECT * FROM "trace" WHERE "id" = ${traceId}
|
|
53
|
+
UNION
|
|
54
|
+
SELECT t.* FROM "trace" t JOIN spine ON t."id" = spine."parent_id"
|
|
55
|
+
),
|
|
56
|
+
copied_traces AS (
|
|
57
|
+
INSERT INTO "trace_retained" (${sql.raw(TRACE_COLUMNS)})
|
|
58
|
+
SELECT ${sql.raw(TRACE_COLUMNS)} FROM spine
|
|
59
|
+
ON CONFLICT ("id", "opened_day") DO NOTHING
|
|
60
|
+
RETURNING "id"
|
|
61
|
+
),
|
|
62
|
+
copied_steps AS (
|
|
63
|
+
INSERT INTO "trace_step_retained" (${sql.raw(TRACE_STEP_COLUMNS)})
|
|
64
|
+
SELECT ${sql.raw(TRACE_STEP_COLUMNS_FROM_STEP)}
|
|
65
|
+
FROM "trace_step" s JOIN spine ON s."trace_id" = spine."id"
|
|
66
|
+
ON CONFLICT ("id", "trace_day") DO NOTHING
|
|
67
|
+
RETURNING "id"
|
|
68
|
+
)
|
|
69
|
+
SELECT
|
|
70
|
+
(SELECT count(*) FROM copied_traces)::int AS traces,
|
|
71
|
+
(SELECT count(*) FROM copied_steps)::int AS steps
|
|
72
|
+
`))
|
|
73
|
+
|
|
74
|
+
const row = rows[0]!
|
|
75
|
+
return { traces: row['traces'] as number, steps: row['steps'] as number }
|
|
76
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Q7 expiry sweep. A trace must not outlive its own oldest day-partition: if
|
|
2
|
+
// a trace is still `open` past `expires_at` (stamped as `opened_at +
|
|
3
|
+
// hotRetentionDays` at entry), the entry leaked or the job hung — the process
|
|
4
|
+
// that opened the trace may be long dead, so there is no in-memory buffer to
|
|
5
|
+
// flush. The sweep force-closes those orphans at the database level: stamps
|
|
6
|
+
// `status = 'expired'` and `closed_at`, then copies the trace to the cold set
|
|
7
|
+
// (treated as an error for Q4) before the next partition retirement drops the
|
|
8
|
+
// hot row.
|
|
9
|
+
//
|
|
10
|
+
// `force_now` is injectable so the sweep is testable without mocking the
|
|
11
|
+
// clock — production calls pass nothing and use `NOW()`.
|
|
12
|
+
|
|
13
|
+
import { sql } from '../../data/db/sql.js'
|
|
14
|
+
import type { DB } from '../../data/db/index.js'
|
|
15
|
+
import { getBaseLogger } from '../../core/logging/index.js'
|
|
16
|
+
import { withMaintenance } from '../../data/db/maintenance.js'
|
|
17
|
+
import { copyTraceOnError } from '../retain/copy-on-error.js'
|
|
18
|
+
|
|
19
|
+
export interface ExpireStaleTracesResult {
|
|
20
|
+
/** Trace rows force-closed by this sweep (`open` past `expires_at`). */
|
|
21
|
+
readonly expired: number
|
|
22
|
+
/** Rows newly inserted into `trace_retained` across all expired traces. */
|
|
23
|
+
readonly retained: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Force-closes every trace whose `expires_at` has passed; copies each to the cold set. */
|
|
27
|
+
export async function expireStaleTraces(
|
|
28
|
+
db: DB,
|
|
29
|
+
now: Date = new Date(),
|
|
30
|
+
): Promise<ExpireStaleTracesResult> {
|
|
31
|
+
// postgres.js's raw `sql` parameters carry no column-type hint, so a Date
|
|
32
|
+
// binds as an unsupported type for `timestamptz`. The boundary cast to an
|
|
33
|
+
// ISO string keeps the production signature on `Date` without losing
|
|
34
|
+
// precision (compared as a literal, Postgres parses it back to `timestamptz`).
|
|
35
|
+
const nowIso = now.toISOString()
|
|
36
|
+
// Every tenant's traces, so the sweep is a maintenance pass.
|
|
37
|
+
const rows = await withMaintenance(db, tx => tx.execute(sql`
|
|
38
|
+
UPDATE "trace"
|
|
39
|
+
SET "status" = 'expired', "closed_at" = ${nowIso}
|
|
40
|
+
WHERE "status" = 'open' AND "expires_at" <= ${nowIso}
|
|
41
|
+
RETURNING "id"
|
|
42
|
+
`))
|
|
43
|
+
const ids = rows.map(r => r['id'] as string)
|
|
44
|
+
if (ids.length === 0) return { expired: 0, retained: 0 }
|
|
45
|
+
|
|
46
|
+
getBaseLogger().error(
|
|
47
|
+
{ count: ids.length, traceIds: ids },
|
|
48
|
+
'Force-closed expired traces — entries leaked or hung past their hot retention window',
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
const copyResults = await Promise.all(ids.map(id => copyTraceOnError(db, id)))
|
|
52
|
+
const retained = copyResults.reduce((sum, r) => sum + r.traces, 0)
|
|
53
|
+
return { expired: ids.length, retained }
|
|
54
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// `__flowStep` — the value-wrapping runtime for a flow step. The build
|
|
2
|
+
// transformer (component 5) renames each documented function and rebinds its
|
|
3
|
+
// public name through this wrapper: `export const runJob = __flowStep(meta,
|
|
4
|
+
// runJobImpl)`. No body is rewritten; the wrapper is the whole instrumentation.
|
|
5
|
+
//
|
|
6
|
+
// Off the traced path it is a pass-through with one `getContext()` lookup and a
|
|
7
|
+
// branch — there is no active Flow, or the Flow opened no trace, so there is
|
|
8
|
+
// nothing to record. On the traced path it brackets the implementation with a
|
|
9
|
+
// `trace_step`: a `seq`, a parent link, start/end timing, and the outcome.
|
|
10
|
+
// Once a trace truncates (Q7), every later step takes the pass-through path
|
|
11
|
+
// too, so a truncated trace costs exactly what an untraced one does.
|
|
12
|
+
//
|
|
13
|
+
// Tier-2 input capture (Q5) runs at `begin` time, before the implementation
|
|
14
|
+
// gets a chance to mutate the arguments. Each parameter's projection — baked
|
|
15
|
+
// into `meta.capture` by the transformer — turns its argument into a
|
|
16
|
+
// trace-safe payload, which the bounded serializer caps for depth, fan-out,
|
|
17
|
+
// string length, and redaction before staging onto `trace_step.captured_inputs`.
|
|
18
|
+
// The trace's `captureInputs` kill-switch (resolved at trace open from
|
|
19
|
+
// `config.trace.captureInputs`) suppresses the whole capture path while
|
|
20
|
+
// leaving Tier-1 (timing, status, error) untouched.
|
|
21
|
+
//
|
|
22
|
+
// `meta` is a literal baked in at transform time — the wrapper never computes
|
|
23
|
+
// the step's identity.
|
|
24
|
+
|
|
25
|
+
import { getContext } from '../../request/context/store.js'
|
|
26
|
+
import { serializeForTrace } from '../capture/bounded-serializer.js'
|
|
27
|
+
import { isThenable } from './thenable.js'
|
|
28
|
+
import { truncateTrace } from './truncate-trace.js'
|
|
29
|
+
import { emitReadTouches } from '../../data/write/audit/read-touches.js'
|
|
30
|
+
import type { CaptureProjection, FlowStepMeta } from './step-meta.js'
|
|
31
|
+
import type { BegunStep } from './step-buffer.js'
|
|
32
|
+
import type { Flow } from '../../request/context/types.js'
|
|
33
|
+
|
|
34
|
+
/* eslint-disable @typescript-eslint/no-explicit-any -- a transparent wrapper must accept and return the implementation's exact signature */
|
|
35
|
+
type AnyFunction = (...args: any[]) => any
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Wraps `impl` so that, under an active traced Flow, each call records a `trace_step`.
|
|
39
|
+
*
|
|
40
|
+
* A function documented with `@flow_step` (and `@touches Entity:verb`) is wrapped automatically: under `pipework test` and the vitest preset, and under `pipework dev` and `pipework serve`. An app built with plain `tsc` gets no wrapping: run it through `pipework serve`, or call `__flowStep` by hand.
|
|
41
|
+
*
|
|
42
|
+
* A write under a step with `@touches` is audited only under the touches whose entity is the written table, one `audit_record` per affected row per selected touch. A row's verb is `create` (an insert, or an upsert row that did not exist), `update` or `delete`; it is recorded under the touches with exactly that verb, else under the touches with a custom verb (not create/update/delete), else under all the entity's touches. A write also counts as written for the step's other create/update/delete touches on the entity, and for the same touch on enclosing steps. A touch's `Entity` matches a table when the definition declares `define(name, fields, { auditEntity })` equal to `Entity` exactly; otherwise when the names agree ignoring case and underscores, with the table name optionally plural (`Version` matches `version` and `versions`; `DocumentVersion` matches `document_versions`). A write to a table no touch matches is not audited. A touch that no write of the step was audited under gets a read row (`before` and `after` null) when the step completes. A write under a step with a touch whose entity matches no defined table throws, naming the closest table names. `.returning()` returns the same rows with or without an audited step.
|
|
43
|
+
*/
|
|
44
|
+
export function __flowStep<F extends AnyFunction>(meta: FlowStepMeta, impl: F): F {
|
|
45
|
+
function traced(this: unknown, ...args: Parameters<F>): ReturnType<F> {
|
|
46
|
+
const flow = getContext()
|
|
47
|
+
if (flow === undefined || flow.trace === null) {
|
|
48
|
+
return impl.apply(this, args) as ReturnType<F>
|
|
49
|
+
}
|
|
50
|
+
const ctx = flow.trace
|
|
51
|
+
const buffer = ctx.buffer
|
|
52
|
+
if (buffer.truncated) {
|
|
53
|
+
return impl.apply(this, args) as ReturnType<F>
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const capturedInputs = buffer.captureInputs && meta.capture !== undefined
|
|
57
|
+
? captureArgs(args, meta.capture)
|
|
58
|
+
: null
|
|
59
|
+
|
|
60
|
+
const begun = buffer.begin(meta.ref, capturedInputs, meta.touches ?? [])
|
|
61
|
+
// `begin` returns null for the call that blows the step cap — that call,
|
|
62
|
+
// and every step after it, runs untraced. The transition fires `truncateTrace`
|
|
63
|
+
// exactly once: the `buffer.truncated` short-circuit above catches every
|
|
64
|
+
// subsequent call before it reaches `begin`.
|
|
65
|
+
if (begun === null) {
|
|
66
|
+
void truncateTrace(flow.instance, ctx)
|
|
67
|
+
return impl.apply(this, args) as ReturnType<F>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let result: unknown
|
|
71
|
+
try {
|
|
72
|
+
result = impl.apply(this, args)
|
|
73
|
+
} catch (err) {
|
|
74
|
+
buffer.complete(begun, 'error', err)
|
|
75
|
+
throw err
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isThenable(result)) {
|
|
79
|
+
return result.then(
|
|
80
|
+
async (value: unknown) => {
|
|
81
|
+
buffer.complete(begun, 'ok', null)
|
|
82
|
+
await emitReadTouchesIfNeeded(flow, begun)
|
|
83
|
+
return value
|
|
84
|
+
},
|
|
85
|
+
(err: unknown) => {
|
|
86
|
+
buffer.complete(begun, 'error', err)
|
|
87
|
+
throw err
|
|
88
|
+
},
|
|
89
|
+
) as ReturnType<F>
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
buffer.complete(begun, 'ok', null)
|
|
93
|
+
// Sync impl: can't change the wrapper's return type to Promise, so fire-and-
|
|
94
|
+
// forget. The audit emitter swallows its own errors, so this won't yield an
|
|
95
|
+
// unhandled rejection; the trade-off is that a sync `@touches` step's audit
|
|
96
|
+
// row may land after control has returned to the caller. Sync impls under
|
|
97
|
+
// `@touches` are rare anyway (pipe.* writes are all async).
|
|
98
|
+
void emitReadTouchesIfNeeded(flow, begun)
|
|
99
|
+
return result as ReturnType<F>
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return traced as F
|
|
103
|
+
}
|
|
104
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Read-touches gate. The CTE-form write path already covered the touches it wrote
|
|
108
|
+
* (recorded via `markWrote(touch)`); this fires for the rest — touches
|
|
109
|
+
* no `pipe.*` write of the step was audited under. Empty
|
|
110
|
+
* `touches` means no audit projection at all and short-circuits earlier in
|
|
111
|
+
* the emitter.
|
|
112
|
+
*/
|
|
113
|
+
function emitReadTouchesIfNeeded(flow: Flow, begun: BegunStep): Promise<void> {
|
|
114
|
+
if (begun.touches.every(t => begun.wroteTouches.has(t))) return Promise.resolve()
|
|
115
|
+
return emitReadTouches(flow, begun)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Projects + bounded-serializes one captured payload per parameter, in
|
|
120
|
+
* declaration order. A `null` projection slot means the parameter has no
|
|
121
|
+
* registry-derived projection (primitive, `any`, or no `.traceSafe()` entry)
|
|
122
|
+
* and the raw arg is handed straight to the serializer. A projection that
|
|
123
|
+
* returns `undefined` is preserved as a `null` slot — fail-closed: an unsafe
|
|
124
|
+
* structured type with no marked-safe fields contributes no payload.
|
|
125
|
+
*/
|
|
126
|
+
function captureArgs(
|
|
127
|
+
args: readonly unknown[],
|
|
128
|
+
projections: ReadonlyArray<CaptureProjection | null>,
|
|
129
|
+
): unknown[] {
|
|
130
|
+
const out: unknown[] = []
|
|
131
|
+
// Pair by parameter index. Extra args (a variadic tail without a matching
|
|
132
|
+
// projection) fall through to the raw-serializer path; extra projections
|
|
133
|
+
// (impl invoked with fewer than declared args) project `undefined` — both
|
|
134
|
+
// paths converge on the bounded serializer's `undefined` handling.
|
|
135
|
+
const count = Math.max(args.length, projections.length)
|
|
136
|
+
for (let i = 0; i < count; i++) {
|
|
137
|
+
const projection = projections[i] ?? null
|
|
138
|
+
const raw = args[i]
|
|
139
|
+
const projected = projection === null ? raw : projection(raw)
|
|
140
|
+
if (projected === undefined) {
|
|
141
|
+
out.push(null)
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
out.push(serializeForTrace(projected))
|
|
145
|
+
}
|
|
146
|
+
return out
|
|
147
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Batch-writes a buffered set of `trace_step` rows. The write is fire-and-
|
|
2
|
+
// forget — the close path doesn't block on it, and a failure must not break
|
|
3
|
+
// the request: a missing step row is a degraded trace, not a degraded user
|
|
4
|
+
// flow. Errors land in the base logger so an operator can see what was lost.
|
|
5
|
+
//
|
|
6
|
+
// The write goes through `instance.pool` directly, never the request
|
|
7
|
+
// transaction — an errored request rolls back, but its trace steps must
|
|
8
|
+
// survive to be inspected.
|
|
9
|
+
|
|
10
|
+
import type { Manifold } from '../../core/pipework.js'
|
|
11
|
+
import { getBaseLogger } from '../../core/logging/index.js'
|
|
12
|
+
import { recordFaultFor, faultMessage } from '../../infra/alerts/faults.js'
|
|
13
|
+
import { traceStep } from '../schema/trace-step.js'
|
|
14
|
+
import { trackTraceWrite } from './pending-writes.js'
|
|
15
|
+
import type { PendingStep } from './step-buffer.js'
|
|
16
|
+
|
|
17
|
+
/** Inserts `steps` into `trace_step` in a single batch. Resolves once the write settles. */
|
|
18
|
+
export function flushSteps(instance: Manifold, steps: readonly PendingStep[]): Promise<void> {
|
|
19
|
+
if (steps.length === 0) return Promise.resolve()
|
|
20
|
+
const db = instance.pool.getOrCreate(instance.config.database()).drizzle
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Drizzle's insert needs the concrete runtime table type
|
|
22
|
+
return trackTraceWrite((db as any).insert(traceStep.table()).values([...steps])
|
|
23
|
+
.then(() => undefined)
|
|
24
|
+
.catch((err: unknown) => {
|
|
25
|
+
getBaseLogger().error(
|
|
26
|
+
{ err, traceId: steps[0]!.traceId, steps: steps.length },
|
|
27
|
+
'Failed to persist trace steps — the trace is missing step rows',
|
|
28
|
+
)
|
|
29
|
+
void recordFaultFor(instance, 'trace-steps-lost', `${String(steps.length)} trace step(s) not persisted: ${faultMessage(err)}`, { traceId: steps[0]!.traceId, steps: steps.length })
|
|
30
|
+
}))
|
|
31
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Trace writes are fire-and-forget; this tracks the ones in flight so the test
|
|
2
|
+
// harness can wait for them before it ends the connection they write through.
|
|
3
|
+
|
|
4
|
+
import { getBaseLogger } from '../../core/logging/index.js'
|
|
5
|
+
|
|
6
|
+
// Process-global so writes tracked by any copy of this module (loaded by
|
|
7
|
+
// `vi.resetModules()` / `vi.isolateModules`) are visible to the harness's settle.
|
|
8
|
+
const SLOT = Symbol.for('pipework.traceWrites')
|
|
9
|
+
const slots = globalThis as unknown as Record<symbol, Set<Promise<void>> | undefined>
|
|
10
|
+
const pending: Set<Promise<void>> = (slots[SLOT] ??= new Set<Promise<void>>())
|
|
11
|
+
|
|
12
|
+
/** Records `write` as in flight until it settles; returns it unchanged. */
|
|
13
|
+
export function trackTraceWrite(write: Promise<void>): Promise<void> {
|
|
14
|
+
pending.add(write)
|
|
15
|
+
const forget = (): void => { pending.delete(write) }
|
|
16
|
+
write.then(forget, forget)
|
|
17
|
+
return write
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Resolves once no trace write is in flight, including writes started by earlier ones. */
|
|
21
|
+
export async function settleTraceWrites(): Promise<void> {
|
|
22
|
+
while (pending.size > 0) await Promise.allSettled([...pending])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** How many trace writes are in flight now. */
|
|
26
|
+
export function pendingTraceWriteCount(): number {
|
|
27
|
+
return pending.size
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const TRACE_SETTLE_TIMEOUT_MS = 30_000
|
|
31
|
+
|
|
32
|
+
/** The harness's teardown hooks' own timeout: room for a full settle plus the teardown itself. */
|
|
33
|
+
export const TEARDOWN_HOOK_TIMEOUT_MS = TRACE_SETTLE_TIMEOUT_MS + 30_000
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Waits for in-flight trace writes for at most `timeoutMs`. On expiry it warns once with
|
|
37
|
+
* the number still in flight and returns, so teardown proceeds anyway.
|
|
38
|
+
*/
|
|
39
|
+
export async function settleTraceWritesBounded(timeoutMs: number = TRACE_SETTLE_TIMEOUT_MS): Promise<void> {
|
|
40
|
+
let timer: NodeJS.Timeout | undefined
|
|
41
|
+
const expired = Symbol('expired')
|
|
42
|
+
const timeout = new Promise<typeof expired>(resolve => { timer = setTimeout(() => resolve(expired), timeoutMs) })
|
|
43
|
+
try {
|
|
44
|
+
const outcome = await Promise.race([settleTraceWrites(), timeout])
|
|
45
|
+
if (outcome === expired) {
|
|
46
|
+
getBaseLogger().warn(
|
|
47
|
+
{ inFlight: pendingTraceWriteCount(), timeoutMs },
|
|
48
|
+
`${pendingTraceWriteCount()} trace write(s) still in flight after ${timeoutMs} ms; test teardown proceeds anyway`,
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
} finally {
|
|
52
|
+
clearTimeout(timer)
|
|
53
|
+
}
|
|
54
|
+
}
|