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,179 @@
|
|
|
1
|
+
import { ValidationError } from '../../core/errors/index.js'
|
|
2
|
+
|
|
3
|
+
/** Parsed cron schedule — arrays of valid minutes, hours, days, months, weekdays. */
|
|
4
|
+
export interface CronSchedule {
|
|
5
|
+
readonly minutes: readonly number[]
|
|
6
|
+
readonly hours: readonly number[]
|
|
7
|
+
readonly daysOfMonth: readonly number[]
|
|
8
|
+
readonly months: readonly number[]
|
|
9
|
+
readonly daysOfWeek: readonly number[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const FIELD_RANGES: readonly [number, number][] = [
|
|
13
|
+
[0, 59], // minute
|
|
14
|
+
[0, 23], // hour
|
|
15
|
+
[1, 31], // day of month
|
|
16
|
+
[1, 12], // month
|
|
17
|
+
[0, 6], // day of week (0=Sun)
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
export function parseCron(expression: string): CronSchedule {
|
|
21
|
+
const parts = expression.trim().split(/\s+/)
|
|
22
|
+
if (parts.length !== 5) {
|
|
23
|
+
throw new ValidationError(
|
|
24
|
+
`Invalid cron expression "${expression}": expected 5 fields (minute hour day month weekday), got ${parts.length}`,
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const [minutes, hours, daysOfMonth, months, daysOfWeek] = parts as [string, string, string, string, string]
|
|
29
|
+
return {
|
|
30
|
+
minutes: parseField(minutes, FIELD_RANGES[0]!, 'minute'),
|
|
31
|
+
hours: parseField(hours, FIELD_RANGES[1]!, 'hour'),
|
|
32
|
+
daysOfMonth: parseField(daysOfMonth, FIELD_RANGES[2]!, 'day-of-month'),
|
|
33
|
+
months: parseField(months, FIELD_RANGES[3]!, 'month'),
|
|
34
|
+
daysOfWeek: parseField(daysOfWeek, FIELD_RANGES[4]!, 'day-of-week'),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseField(field: string, [min, max]: [number, number], name: string): number[] {
|
|
39
|
+
const values = new Set<number>()
|
|
40
|
+
|
|
41
|
+
for (const part of field.split(',')) {
|
|
42
|
+
const stepMatch = part.match(/^(.+)\/(\d+)$/)
|
|
43
|
+
const step = stepMatch ? parseInt(stepMatch[2]!, 10) : null
|
|
44
|
+
const rangePart = stepMatch ? stepMatch[1]! : part
|
|
45
|
+
|
|
46
|
+
if (step !== null && (step < 1 || step > max)) {
|
|
47
|
+
throw new ValidationError(`Invalid cron ${name}: step "${step}" out of range`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (rangePart === '*') {
|
|
51
|
+
for (let i = min; i <= max; i += (step ?? 1)) {
|
|
52
|
+
values.add(i)
|
|
53
|
+
}
|
|
54
|
+
} else if (rangePart.includes('-')) {
|
|
55
|
+
const [startStr, endStr] = rangePart.split('-') as [string, string]
|
|
56
|
+
const start = parseInt(startStr, 10)
|
|
57
|
+
const end = parseInt(endStr, 10)
|
|
58
|
+
if (Number.isNaN(start) || Number.isNaN(end) || start < min || end > max || start > end) {
|
|
59
|
+
throw new ValidationError(`Invalid cron ${name}: range "${rangePart}" out of bounds (${min}-${max})`)
|
|
60
|
+
}
|
|
61
|
+
for (let i = start; i <= end; i += (step ?? 1)) {
|
|
62
|
+
values.add(i)
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
const val = parseInt(rangePart, 10)
|
|
66
|
+
if (Number.isNaN(val) || val < min || val > max) {
|
|
67
|
+
throw new ValidationError(`Invalid cron ${name}: value "${rangePart}" out of range (${min}-${max})`)
|
|
68
|
+
}
|
|
69
|
+
if (step !== null) {
|
|
70
|
+
for (let i = val; i <= max; i += step) {
|
|
71
|
+
values.add(i)
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
values.add(val)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return [...values].sort((a, b) => a - b)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function nextTick(schedule: CronSchedule, after: Date, timezone?: string): Date {
|
|
83
|
+
const tz = timezone ?? 'UTC'
|
|
84
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
85
|
+
timeZone: tz,
|
|
86
|
+
year: 'numeric',
|
|
87
|
+
month: '2-digit',
|
|
88
|
+
day: '2-digit',
|
|
89
|
+
hour: '2-digit',
|
|
90
|
+
minute: '2-digit',
|
|
91
|
+
second: '2-digit',
|
|
92
|
+
hour12: false,
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const parts = extractParts(formatter, after)
|
|
96
|
+
let year = parts.year
|
|
97
|
+
let month = parts.month
|
|
98
|
+
let day = parts.day
|
|
99
|
+
let hour = parts.hour
|
|
100
|
+
let minute = parts.minute + 1
|
|
101
|
+
|
|
102
|
+
for (let guard = 0; guard < 5 * 366; guard++) {
|
|
103
|
+
if (minute > 59) { minute = 0; hour++ }
|
|
104
|
+
if (hour > 23) { hour = 0; day++ }
|
|
105
|
+
const dim = getDaysInMonth(year, month)
|
|
106
|
+
if (day > dim) { day = 1; month++ }
|
|
107
|
+
if (month > 12) { month = 1; year++ }
|
|
108
|
+
|
|
109
|
+
if (!schedule.months.includes(month)) {
|
|
110
|
+
month++; day = schedule.daysOfMonth[0]!; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
111
|
+
continue
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!schedule.daysOfMonth.includes(day)) {
|
|
115
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const dow = getDayOfWeekForDate(year, month, day)
|
|
120
|
+
if (!schedule.daysOfWeek.includes(dow)) {
|
|
121
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!schedule.hours.includes(hour)) {
|
|
126
|
+
const nextHour = schedule.hours.find(h => h > hour)
|
|
127
|
+
if (nextHour !== undefined) {
|
|
128
|
+
hour = nextHour; minute = schedule.minutes[0]!
|
|
129
|
+
} else {
|
|
130
|
+
day++; hour = schedule.hours[0]!; minute = schedule.minutes[0]!
|
|
131
|
+
}
|
|
132
|
+
continue
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!schedule.minutes.includes(minute)) {
|
|
136
|
+
const nextMin = schedule.minutes.find(m => m >= minute)
|
|
137
|
+
if (nextMin !== undefined) {
|
|
138
|
+
minute = nextMin
|
|
139
|
+
} else {
|
|
140
|
+
hour++; minute = schedule.minutes[0]!
|
|
141
|
+
}
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return buildDate(tz, year, month, day, hour, minute)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
throw new Error('Could not find next cron tick within search window')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function extractParts(formatter: Intl.DateTimeFormat, date: Date): { year: number; month: number; day: number; hour: number; minute: number } {
|
|
152
|
+
const resolved = formatter.formatToParts(date)
|
|
153
|
+
const get = (type: Intl.DateTimeFormatPartTypes) => parseInt(resolved.find(p => p.type === type)!.value, 10)
|
|
154
|
+
return { year: get('year'), month: get('month'), day: get('day'), hour: get('hour'), minute: get('minute') }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function getDayOfWeekForDate(year: number, month: number, day: number): number {
|
|
158
|
+
return new Date(Date.UTC(year, month - 1, day, 12, 0, 0)).getUTCDay()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getDaysInMonth(year: number, month: number): number {
|
|
162
|
+
return new Date(year, month, 0).getDate()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function buildDate(tz: string, year: number, month: number, day: number, hour: number, minute: number): Date {
|
|
166
|
+
if (tz === 'UTC') {
|
|
167
|
+
return new Date(Date.UTC(year, month - 1, day, hour, minute, 0, 0))
|
|
168
|
+
}
|
|
169
|
+
const iso = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`
|
|
170
|
+
const formatter = new Intl.DateTimeFormat('en-US', { timeZone: tz, timeZoneName: 'longOffset' })
|
|
171
|
+
const refParts = formatter.formatToParts(new Date(iso + 'Z'))
|
|
172
|
+
const tzPart = refParts.find(p => p.type === 'timeZoneName')?.value ?? '+00:00'
|
|
173
|
+
const offsetMatch = tzPart.match(/GMT([+-]\d{1,2}):?(\d{2})?/)
|
|
174
|
+
if (!offsetMatch) return new Date(iso + 'Z')
|
|
175
|
+
const offsetHours = parseInt(offsetMatch[1]!, 10)
|
|
176
|
+
const offsetMinutes = parseInt(offsetMatch[2] ?? '0', 10)
|
|
177
|
+
const totalOffsetMs = (offsetHours * 60 + (offsetHours < 0 ? -offsetMinutes : offsetMinutes)) * 60_000
|
|
178
|
+
return new Date(new Date(iso + 'Z').getTime() - totalOffsetMs)
|
|
179
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PipeworkError } from '../../core/errors/base.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Thrown by `jobs.execute` when the caller's `signal` aborts before the handler
|
|
5
|
+
* returns. `name` is `'AbortError'` so the standard `err.name === 'AbortError'`
|
|
6
|
+
* check works; `code` stays pipework's `JOB_ABORTED`.
|
|
7
|
+
*
|
|
8
|
+
* Aborting with an `Error` as the reason rejects with that error instead — the
|
|
9
|
+
* worker uses this to keep its own job-timeout message.
|
|
10
|
+
*/
|
|
11
|
+
export class JobAbortedError extends PipeworkError {
|
|
12
|
+
readonly code = 'JOB_ABORTED' as const
|
|
13
|
+
readonly httpStatus = 499 as const
|
|
14
|
+
|
|
15
|
+
constructor(jobLabel: string, reason?: unknown) {
|
|
16
|
+
super(
|
|
17
|
+
`[pipework] Job ${jobLabel} was aborted by its caller's signal.\n\n` +
|
|
18
|
+
' The handler was still running; its transaction was rolled back and its\n' +
|
|
19
|
+
' connection released. An in-flight query was cancelled on the server, but a\n' +
|
|
20
|
+
' handler that ignores the cancellation keeps running until it returns.\n',
|
|
21
|
+
reason === undefined ? { jobLabel } : { jobLabel, reason },
|
|
22
|
+
)
|
|
23
|
+
this.name = 'AbortError'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Thrown by a job handler to end the attempt as "try again later": the job goes
|
|
29
|
+
* back to pending after `delayMs` (the queue's backoff, at least a second, when
|
|
30
|
+
* unset) and the attempt is not counted. Build it with `jobs.later(...)`.
|
|
31
|
+
*/
|
|
32
|
+
export class JobLaterError extends PipeworkError {
|
|
33
|
+
readonly code = 'JOB_LATER' as const
|
|
34
|
+
readonly httpStatus = 503 as const
|
|
35
|
+
readonly delayMs: number | undefined
|
|
36
|
+
|
|
37
|
+
constructor(message: string, opts: { delayMs?: number; cause?: unknown } = {}) {
|
|
38
|
+
super(message, opts.cause === undefined ? {} : { cause: opts.cause })
|
|
39
|
+
this.name = 'JobLaterError'
|
|
40
|
+
this.delayMs = opts.delayMs
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Thrown by a job handler to end the attempt as a final failure: the job is
|
|
46
|
+
* dead-lettered now, whatever attempts remain. Build it with `jobs.permanent(...)`.
|
|
47
|
+
*/
|
|
48
|
+
export class JobPermanentError extends PipeworkError {
|
|
49
|
+
readonly code = 'JOB_PERMANENT' as const
|
|
50
|
+
readonly httpStatus = 500 as const
|
|
51
|
+
|
|
52
|
+
constructor(message: string, opts: { cause?: unknown } = {}) {
|
|
53
|
+
super(message, opts.cause === undefined ? {} : { cause: opts.cause })
|
|
54
|
+
this.name = 'JobPermanentError'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Cross-job exclusion gate for the claim query.
|
|
2
|
+
//
|
|
3
|
+
// A job "participates" in exclusion when its array column is non-NULL or its
|
|
4
|
+
// blocks-all flag is true. Against the concurrent set R (claimed/running jobs,
|
|
5
|
+
// tenant-scoped when a tenant column is configured), a pending candidate is
|
|
6
|
+
// claimable when:
|
|
7
|
+
// - it does not participate: always claimable, and it never blocks others
|
|
8
|
+
// - it is blocks-all: R contains no participating job
|
|
9
|
+
// - it carries an array: R contains no blocks-all job and no job whose
|
|
10
|
+
// array overlaps (&&) the candidate's
|
|
11
|
+
//
|
|
12
|
+
// Two concurrent workers can evaluate these NOT EXISTS checks against the same
|
|
13
|
+
// MVCC snapshot and both pass (write skew) — the claim query must run under
|
|
14
|
+
// SERIALIZABLE; queue.ts handles that.
|
|
15
|
+
|
|
16
|
+
import { assertValidIdentifier, quoteIdentifier } from '../../data/db/identifiers.js'
|
|
17
|
+
import { QUEUE_BASE_COLUMNS } from './table.js'
|
|
18
|
+
|
|
19
|
+
/** Cross-job exclusion config — names the consumer's conflict columns; the mechanism is pipework's. */
|
|
20
|
+
export interface ExclusionConfig {
|
|
21
|
+
/** Array column — two jobs whose arrays overlap (`&&`) are mutually exclusive. */
|
|
22
|
+
readonly arrayColumn?: string
|
|
23
|
+
/** Element type of `arrayColumn`. Default `'uuid'`. */
|
|
24
|
+
readonly arrayElementType?: 'uuid' | 'text'
|
|
25
|
+
/** Boolean column — a TRUE job is exclusive against every participating job in its scope. */
|
|
26
|
+
readonly blocksAllColumn?: string
|
|
27
|
+
/** Tenant column — exclusion checks compare only jobs with the same tenant value. */
|
|
28
|
+
readonly tenantColumn?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ResolvedExclusion {
|
|
32
|
+
readonly arrayColumn?: string
|
|
33
|
+
readonly arrayElementType: 'uuid' | 'text'
|
|
34
|
+
readonly blocksAllColumn?: string
|
|
35
|
+
readonly tenantColumn?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function resolveExclusion(config: ExclusionConfig | undefined): ResolvedExclusion | undefined {
|
|
39
|
+
if (config === undefined) return undefined
|
|
40
|
+
|
|
41
|
+
if (config.arrayColumn === undefined && config.blocksAllColumn === undefined) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
'[pipework] exclusion requires arrayColumn and/or blocksAllColumn.\n\n' +
|
|
44
|
+
' A tenantColumn alone only scopes checks — it expresses no conflict.\n' +
|
|
45
|
+
" Configure the conflict columns: exclusion: { arrayColumn: 'conflict_keys' }\n" +
|
|
46
|
+
" or exclusion: { blocksAllColumn: 'exclusive' }.\n",
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (config.arrayElementType !== undefined && config.arrayColumn === undefined) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
'[pipework] exclusion.arrayElementType is set but arrayColumn is not.\n\n' +
|
|
53
|
+
' arrayElementType only describes arrayColumn.\n' +
|
|
54
|
+
' Add arrayColumn, or remove arrayElementType.\n',
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const named = [config.arrayColumn, config.blocksAllColumn, config.tenantColumn]
|
|
59
|
+
.filter((c): c is string => c !== undefined)
|
|
60
|
+
for (const column of named) {
|
|
61
|
+
assertValidIdentifier(column, 'exclusion column')
|
|
62
|
+
if (QUEUE_BASE_COLUMNS.has(column)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`[pipework] exclusion column "${column}" collides with a base queue column.\n\n` +
|
|
65
|
+
` The queue table already owns: ${[...QUEUE_BASE_COLUMNS].join(', ')}\n` +
|
|
66
|
+
' Pick a different column name.\n',
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (new Set(named).size !== named.length) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
'[pipework] exclusion columns must be distinct.\n\n' +
|
|
73
|
+
` Got: arrayColumn=${config.arrayColumn ?? '—'}, blocksAllColumn=${config.blocksAllColumn ?? '—'}, tenantColumn=${config.tenantColumn ?? '—'}\n` +
|
|
74
|
+
' Each role needs its own column.\n',
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...(config.arrayColumn !== undefined ? { arrayColumn: config.arrayColumn } : {}),
|
|
80
|
+
arrayElementType: config.arrayElementType ?? 'uuid',
|
|
81
|
+
...(config.blocksAllColumn !== undefined ? { blocksAllColumn: config.blocksAllColumn } : {}),
|
|
82
|
+
...(config.tenantColumn !== undefined ? { tenantColumn: config.tenantColumn } : {}),
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The claimability predicate for the claim query's candidate SELECT. Pure
|
|
88
|
+
* identifiers — all quoted, no values — so the result composes as a raw SQL
|
|
89
|
+
* fragment. The candidate row is aliased `candidate`, concurrent rows `r`.
|
|
90
|
+
*/
|
|
91
|
+
export function exclusionClaimClause(tableQ: string, exclusion: ResolvedExclusion): string {
|
|
92
|
+
const arr = exclusion.arrayColumn !== undefined ? quoteIdentifier(exclusion.arrayColumn, 'exclusion column') : undefined
|
|
93
|
+
const blocks = exclusion.blocksAllColumn !== undefined ? quoteIdentifier(exclusion.blocksAllColumn, 'exclusion column') : undefined
|
|
94
|
+
const tenant = exclusion.tenantColumn !== undefined ? quoteIdentifier(exclusion.tenantColumn, 'exclusion column') : undefined
|
|
95
|
+
|
|
96
|
+
const tenantScope = tenant !== undefined ? `r.${tenant} = candidate.${tenant} AND ` : ''
|
|
97
|
+
const noConcurrent = (condition: string): string =>
|
|
98
|
+
`NOT EXISTS (SELECT 1 FROM ${tableQ} r WHERE ${tenantScope}r.status IN ('claimed', 'running') AND ${condition})`
|
|
99
|
+
|
|
100
|
+
if (arr !== undefined && blocks !== undefined) {
|
|
101
|
+
return '(' +
|
|
102
|
+
`(candidate.${blocks} = false AND candidate.${arr} IS NULL)` +
|
|
103
|
+
` OR (candidate.${blocks} = true AND ${noConcurrent(`(r.${arr} IS NOT NULL OR r.${blocks} = true)`)})` +
|
|
104
|
+
` OR (candidate.${blocks} = false AND candidate.${arr} IS NOT NULL` +
|
|
105
|
+
` AND ${noConcurrent(`r.${blocks} = true`)}` +
|
|
106
|
+
` AND ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})` +
|
|
107
|
+
')'
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (arr !== undefined) {
|
|
111
|
+
return `(candidate.${arr} IS NULL OR ${noConcurrent(`r.${arr} IS NOT NULL AND r.${arr} && candidate.${arr}`)})`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// blocks-all only: participation reduces to the flag itself, so a false
|
|
115
|
+
// candidate never conflicts and a true candidate waits for true jobs.
|
|
116
|
+
return `(candidate.${blocks!} = false OR ${noConcurrent(`r.${blocks!} = true`)})`
|
|
117
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { Manifold } from '../../core/pipework.js'
|
|
2
|
+
import type { Handler } from '../../request/di/types.js'
|
|
3
|
+
import type { TenantConfig } from '../../auth/tenant/types.js'
|
|
4
|
+
import { runInContext } from '../../request/context/store.js'
|
|
5
|
+
import { createJobContext } from '../../request/context/create.js'
|
|
6
|
+
import { executeInTransaction } from '../../request/context/run-in-transaction.js'
|
|
7
|
+
import { resolveAndExecute, resolveHandlerDatabases, buildCheckpoint } from '../../request/di/resolve.js'
|
|
8
|
+
import { isTracingEnabled } from '../../trace/entry/tracing-enabled.js'
|
|
9
|
+
import { openTrace } from '../../trace/entry/open-trace.js'
|
|
10
|
+
import { parentTraceRef } from '../../trace/entry/parent-trace.js'
|
|
11
|
+
import type { ParentTraceRef } from '../../trace/entry/open-trace.js'
|
|
12
|
+
import { finalizeTrace } from '../../trace/entry/finalize-trace.js'
|
|
13
|
+
import { JobAbortedError } from './errors.js'
|
|
14
|
+
import { randomUUID } from 'node:crypto'
|
|
15
|
+
import { serializeForTrace } from '../../trace/capture/bounded-serializer.js'
|
|
16
|
+
|
|
17
|
+
/** Default timeout for setting up a tenant job's database transaction(s). */
|
|
18
|
+
const DEFAULT_JOB_TRANSACTION_TIMEOUT_MS = 5000
|
|
19
|
+
|
|
20
|
+
export interface ExecuteJobOptions {
|
|
21
|
+
instance: Manifold
|
|
22
|
+
jobId?: string
|
|
23
|
+
jobType?: string
|
|
24
|
+
/** 1-based attempt number, exposed as `flow.jobAttempt`. */
|
|
25
|
+
attempt?: number
|
|
26
|
+
/** The job's attempt limit, exposed as `flow.jobMaxAttempts`. */
|
|
27
|
+
maxAttempts?: number
|
|
28
|
+
auth?: unknown
|
|
29
|
+
tenant?: string | null
|
|
30
|
+
/**
|
|
31
|
+
* Tenant config carrying custom `sessionVars`. When provided alongside
|
|
32
|
+
* `tenant`, the custom session variables are propagated in addition to
|
|
33
|
+
* `pipework.tenant_id` — matching the HTTP surface's behaviour.
|
|
34
|
+
*/
|
|
35
|
+
tenantConfig?: TenantConfig | null
|
|
36
|
+
input?: unknown
|
|
37
|
+
/** Timeout for multi-database transaction setup when running a tenant job. */
|
|
38
|
+
transactionTimeoutMs?: number
|
|
39
|
+
/**
|
|
40
|
+
* The trace this job continues. Omitted: the trace on the active Flow, if any.
|
|
41
|
+
* `null`: a root trace even inside a Flow. The worker surface passes the
|
|
42
|
+
* trace recorded when the job was enqueued.
|
|
43
|
+
*/
|
|
44
|
+
parent?: ParentTraceRef | null
|
|
45
|
+
/** The ingress kind for the opened trace — `'cron'` for schedule-fired jobs, `'job'` otherwise. */
|
|
46
|
+
entryKind?: 'job' | 'cron'
|
|
47
|
+
/**
|
|
48
|
+
* Set when this attempt follows one that ended without failing on its own (a
|
|
49
|
+
* reap or a hand-back): the attempt's trace opens with a `pipework.job.restart`
|
|
50
|
+
* external step naming the reason and the worker that held the previous claim.
|
|
51
|
+
*/
|
|
52
|
+
restart?: { readonly reason: 'reaped' | 'handed-back' | 'later'; readonly previousWorkerId: string | null }
|
|
53
|
+
/**
|
|
54
|
+
* Ends the job at the caller's deadline. On abort the job's in-flight query is
|
|
55
|
+
* cancelled server-side so its transaction rolls back and its connection
|
|
56
|
+
* returns to the pool, and `executeJob` rejects — with `signal.reason` when
|
|
57
|
+
* that is an `Error`, otherwise a `JobAbortedError` (`name: 'AbortError'`)
|
|
58
|
+
* naming the job. A handler that ignores the cancelled query keeps running;
|
|
59
|
+
* the rejection is still delivered on time.
|
|
60
|
+
*/
|
|
61
|
+
signal?: AbortSignal
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function executeJob<TDeps extends Record<string, unknown>, TReturn>(
|
|
65
|
+
handler: Handler<TDeps, TReturn>,
|
|
66
|
+
options: ExecuteJobOptions,
|
|
67
|
+
): Promise<TReturn> {
|
|
68
|
+
const label = jobLabel(options)
|
|
69
|
+
if (options.signal?.aborted === true) throw abortReason(options.signal, label)
|
|
70
|
+
|
|
71
|
+
const jobCtxOptions: Parameters<typeof createJobContext>[0] = {
|
|
72
|
+
instance: options.instance,
|
|
73
|
+
}
|
|
74
|
+
if (options.jobId !== undefined) jobCtxOptions.jobId = options.jobId
|
|
75
|
+
if (options.jobType !== undefined) jobCtxOptions.jobType = options.jobType
|
|
76
|
+
if (options.attempt !== undefined) jobCtxOptions.attempt = options.attempt
|
|
77
|
+
if (options.maxAttempts !== undefined) jobCtxOptions.maxAttempts = options.maxAttempts
|
|
78
|
+
if (options.auth !== undefined) jobCtxOptions.auth = options.auth
|
|
79
|
+
if (options.tenant !== undefined) jobCtxOptions.tenant = options.tenant
|
|
80
|
+
if (options.tenantConfig !== undefined) jobCtxOptions.tenantConfig = options.tenantConfig
|
|
81
|
+
if (isTracingEnabled(options.instance)) {
|
|
82
|
+
jobCtxOptions.trace = openTrace({
|
|
83
|
+
instance: options.instance,
|
|
84
|
+
entryKind: options.entryKind ?? 'job',
|
|
85
|
+
parent: options.parent !== undefined ? options.parent : parentTraceRef(),
|
|
86
|
+
tenant: options.tenant ?? null,
|
|
87
|
+
auth: options.auth ?? null,
|
|
88
|
+
requestId: options.jobId ?? null,
|
|
89
|
+
sessionId: null,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (options.restart !== undefined && jobCtxOptions.trace !== undefined && jobCtxOptions.trace !== null) {
|
|
94
|
+
const now = new Date()
|
|
95
|
+
jobCtxOptions.trace.buffer.stageExternal({
|
|
96
|
+
id: randomUUID(),
|
|
97
|
+
parentStepId: null,
|
|
98
|
+
flowStepRef: 'external:pipework.job.restart',
|
|
99
|
+
status: 'ok',
|
|
100
|
+
startedAt: now,
|
|
101
|
+
completedAt: now,
|
|
102
|
+
durationMicros: 0n,
|
|
103
|
+
capturedInputs: [serializeForTrace({ reason: options.restart.reason, previousWorkerId: options.restart.previousWorkerId })],
|
|
104
|
+
error: null,
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The handler's own signal: aborted, with the error `executeJob` rejects with,
|
|
109
|
+
// whenever the job stops being the handler's while it may still be running.
|
|
110
|
+
const own = new AbortController()
|
|
111
|
+
const ctx = createJobContext(jobCtxOptions)
|
|
112
|
+
const databases = resolveHandlerDatabases(handler, options.instance)
|
|
113
|
+
const timeoutMs = options.transactionTimeoutMs ?? DEFAULT_JOB_TRANSACTION_TIMEOUT_MS
|
|
114
|
+
|
|
115
|
+
// Manual transaction mode: the framework opens no outer transaction. The
|
|
116
|
+
// handler owns its commit boundaries through `checkpoint`, which opens a fresh
|
|
117
|
+
// tenant-scoped transaction per call (re-establishing the tenant session vars
|
|
118
|
+
// so database-side RLS sees the tenant) and commits it independently.
|
|
119
|
+
if (handler.meta.jobTransaction === 'manual') {
|
|
120
|
+
const checkpoint = buildCheckpoint(
|
|
121
|
+
handler,
|
|
122
|
+
ctx,
|
|
123
|
+
databases,
|
|
124
|
+
options.tenantConfig ?? null,
|
|
125
|
+
timeoutMs,
|
|
126
|
+
options.signal,
|
|
127
|
+
own.signal,
|
|
128
|
+
)
|
|
129
|
+
return finalizeTrace(
|
|
130
|
+
options.instance,
|
|
131
|
+
ctx.trace,
|
|
132
|
+
untilAborted(
|
|
133
|
+
runInContext(ctx, () => resolveAndExecute(handler, options.input, undefined, undefined, { checkpoint, signal: own.signal })),
|
|
134
|
+
options.signal,
|
|
135
|
+
label,
|
|
136
|
+
own,
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const run = (): Promise<TReturn> => resolveAndExecute(handler, options.input, undefined, undefined, { signal: own.signal })
|
|
142
|
+
|
|
143
|
+
// No tenant: app-level scoping does not apply, so there is nothing to
|
|
144
|
+
// propagate to Postgres — run the handler directly as before.
|
|
145
|
+
if (ctx.tenant === null || databases.length === 0) {
|
|
146
|
+
return finalizeTrace(options.instance, ctx.trace, untilAborted(runInContext(ctx, run), options.signal, label, own))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Tenant job: wrap in a transaction and propagate session vars so
|
|
150
|
+
// database-side RLS sees the tenant — consistent with the HTTP surface.
|
|
151
|
+
return finalizeTrace(
|
|
152
|
+
options.instance,
|
|
153
|
+
ctx.trace,
|
|
154
|
+
untilAborted(
|
|
155
|
+
executeInTransaction(
|
|
156
|
+
ctx,
|
|
157
|
+
databases,
|
|
158
|
+
options.tenantConfig ?? null,
|
|
159
|
+
timeoutMs,
|
|
160
|
+
run,
|
|
161
|
+
options.signal,
|
|
162
|
+
),
|
|
163
|
+
options.signal,
|
|
164
|
+
label,
|
|
165
|
+
own,
|
|
166
|
+
),
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** `[type] id`, `[type]`, `id`, or `(anonymous)` — whatever the caller gave us to name the job by. */
|
|
171
|
+
function jobLabel(options: ExecuteJobOptions): string {
|
|
172
|
+
const parts: string[] = []
|
|
173
|
+
if (options.jobType !== undefined) parts.push(`"${options.jobType}"`)
|
|
174
|
+
if (options.jobId !== undefined) parts.push(`(${options.jobId})`)
|
|
175
|
+
return parts.length === 0 ? '(anonymous)' : parts.join(' ')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The error an abort rejects with: the caller's own `Error` reason when they set
|
|
180
|
+
* one (the worker passes its timeout error this way), otherwise a
|
|
181
|
+
* `JobAbortedError` naming the job. `abort()` with no reason leaves a generic
|
|
182
|
+
* DOMException that names nothing — that is the case worth replacing.
|
|
183
|
+
*/
|
|
184
|
+
function abortReason(signal: AbortSignal, label: string): Error {
|
|
185
|
+
const reason: unknown = signal.reason
|
|
186
|
+
const isDefaultReason =
|
|
187
|
+
typeof DOMException === 'function' && reason instanceof DOMException && reason.name === 'AbortError'
|
|
188
|
+
|
|
189
|
+
return reason instanceof Error && !isDefaultReason
|
|
190
|
+
? reason
|
|
191
|
+
: new JobAbortedError(label, reason)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Rejects when the signal aborts, even if the handler is still running — the
|
|
196
|
+
* caller's deadline is the caller's, not the handler's. The work promise's own
|
|
197
|
+
* rejection is swallowed once we have rejected, so a later unwind (the cancelled
|
|
198
|
+
* query surfacing) does not become an unhandled rejection. The handler's own
|
|
199
|
+
* signal aborts with that same rejection first, so it sees the abort while it runs on.
|
|
200
|
+
*/
|
|
201
|
+
function untilAborted<T>(work: Promise<T>, signal: AbortSignal | undefined, label: string, own: AbortController): Promise<T> {
|
|
202
|
+
if (signal === undefined) return work
|
|
203
|
+
|
|
204
|
+
return new Promise<T>((resolve, reject) => {
|
|
205
|
+
const onAbort = (): void => {
|
|
206
|
+
work.catch(() => {})
|
|
207
|
+
const reason = abortReason(signal, label)
|
|
208
|
+
own.abort(reason)
|
|
209
|
+
reject(reason)
|
|
210
|
+
}
|
|
211
|
+
if (signal.aborted) {
|
|
212
|
+
onAbort()
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
signal.addEventListener('abort', onAbort, { once: true })
|
|
216
|
+
work.then(resolve, reject).finally(() => { signal.removeEventListener('abort', onAbort) })
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { executeJob } from './execute.js'
|
|
2
|
+
export type { ExecuteJobOptions } from './execute.js'
|
|
3
|
+
export { JobAbortedError, JobLaterError, JobPermanentError } from './errors.js'
|
|
4
|
+
export { createQueue } from './queue.js'
|
|
5
|
+
export type { Queue, QueueConfig, EnqueueOptions, EnqueueExclusion, ClaimedJob, JobClaim, JobClaimReason, ClaimedExclusion, DeadLetterInfo, ReapedJob, FailedAttempt, QueueTotals, QueueTypeTotals, JobResult, BackoffConfig } from './queue.js'
|
|
6
|
+
export type { ExclusionConfig } from './exclusion.js'
|
|
7
|
+
export type { WaitOptions, WaitResult, ListenClient, ListenHandle } from './listener.js'
|
|
8
|
+
export { parseCron, nextTick } from './cron.js'
|
|
9
|
+
export type { CronSchedule } from './cron.js'
|
|
10
|
+
export type { ScheduleSpec, ScheduleInfo, SchedulerOptions } from './scheduler.js'
|