@qlever-llc/trellis 0.10.22 → 0.11.0-rc.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/esm/auth/mod.d.ts +1 -1
- package/esm/auth/mod.d.ts.map +1 -1
- package/esm/auth/mod.js +1 -1
- package/esm/auth/protocol.d.ts +55 -0
- package/esm/auth/protocol.d.ts.map +1 -1
- package/esm/browser.d.ts +3 -3
- package/esm/browser.d.ts.map +1 -1
- package/esm/browser.js +1 -1
- package/esm/client_connect.d.ts +12 -3
- package/esm/client_connect.d.ts.map +1 -1
- package/esm/client_connect.js +112 -7
- package/esm/codec.d.ts +7 -6
- package/esm/codec.d.ts.map +1 -1
- package/esm/codec.js +125 -6
- package/esm/contract_support/canonical.d.ts +3 -0
- package/esm/contract_support/canonical.d.ts.map +1 -1
- package/esm/contract_support/canonical.js +3 -0
- package/esm/contract_support/mod.d.ts +125 -10
- package/esm/contract_support/mod.d.ts.map +1 -1
- package/esm/contract_support/mod.js +159 -5
- package/esm/contract_support/protocol.d.ts +92 -7
- package/esm/contract_support/protocol.d.ts.map +1 -1
- package/esm/contract_support/protocol.js +41 -7
- package/esm/contract_support/runtime.d.ts +4 -1
- package/esm/contract_support/runtime.d.ts.map +1 -1
- package/esm/errors/SchemaValidationError.d.ts +49 -0
- package/esm/errors/SchemaValidationError.d.ts.map +1 -0
- package/esm/errors/SchemaValidationError.js +67 -0
- package/esm/errors/index.d.ts +38 -9
- package/esm/errors/index.d.ts.map +1 -1
- package/esm/errors/index.js +16 -0
- package/esm/generated-sdk/auth/api.d.ts +33 -605
- package/esm/generated-sdk/auth/api.d.ts.map +1 -1
- package/esm/generated-sdk/auth/api.js +6 -1
- package/esm/generated-sdk/auth/client.d.ts +129 -134
- package/esm/generated-sdk/auth/client.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.d.ts +2 -601
- package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.js +310 -93
- package/esm/generated-sdk/auth/mod.d.ts +1 -1
- package/esm/generated-sdk/auth/mod.d.ts.map +1 -1
- package/esm/generated-sdk/auth/owned_api.d.ts +88 -86
- package/esm/generated-sdk/auth/owned_api.d.ts.map +1 -1
- package/esm/generated-sdk/auth/owned_api.js +6 -0
- package/esm/generated-sdk/auth/schemas.d.ts +284 -136
- package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/auth/schemas.js +231 -92
- package/esm/generated-sdk/auth/types.d.ts +565 -89
- package/esm/generated-sdk/auth/types.d.ts.map +1 -1
- package/esm/generated-sdk/auth/types.js +1 -1
- package/esm/generated-sdk/health/api.d.ts +29 -18
- package/esm/generated-sdk/health/api.d.ts.map +1 -1
- package/esm/generated-sdk/health/client.d.ts +7 -21
- package/esm/generated-sdk/health/client.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.d.ts +2 -15
- package/esm/generated-sdk/health/contract.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.js +2 -10
- package/esm/generated-sdk/health/mod.d.ts +1 -1
- package/esm/generated-sdk/health/mod.d.ts.map +1 -1
- package/esm/generated-sdk/health/owned_api.d.ts +2 -2
- package/esm/generated-sdk/health/schemas.d.ts +1 -14
- package/esm/generated-sdk/health/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/health/schemas.js +1 -9
- package/esm/generated-sdk/health/types.d.ts +10 -5
- package/esm/generated-sdk/health/types.d.ts.map +1 -1
- package/esm/generated-sdk/health/types.js +1 -2
- package/esm/generated-sdk/jobs/api.d.ts +29 -109
- package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/client.d.ts +21 -33
- package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts +2 -106
- package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.js +268 -1
- package/esm/generated-sdk/jobs/mod.d.ts +1 -1
- package/esm/generated-sdk/jobs/mod.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/owned_api.d.ts +22 -9
- package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/owned_api.js +20 -1
- package/esm/generated-sdk/jobs/schemas.d.ts +437 -0
- package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/schemas.js +211 -0
- package/esm/generated-sdk/jobs/types.d.ts +195 -12
- package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/types.js +1 -1
- package/esm/generated-sdk/state/api.d.ts +29 -68
- package/esm/generated-sdk/state/api.d.ts.map +1 -1
- package/esm/generated-sdk/state/client.d.ts +17 -31
- package/esm/generated-sdk/state/client.d.ts.map +1 -1
- package/esm/generated-sdk/state/contract.d.ts +1 -64
- package/esm/generated-sdk/state/contract.d.ts.map +1 -1
- package/esm/generated-sdk/state/mod.d.ts +1 -1
- package/esm/generated-sdk/state/mod.d.ts.map +1 -1
- package/esm/generated-sdk/state/owned_api.d.ts +7 -7
- package/esm/generated-sdk/state/types.d.ts +52 -9
- package/esm/generated-sdk/state/types.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.d.ts +33 -45
- package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.js +6 -1
- package/esm/generated-sdk/trellis-core/client.d.ts +31 -20
- package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts +2 -41
- package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.js +91 -1
- package/esm/generated-sdk/trellis-core/mod.d.ts +1 -1
- package/esm/generated-sdk/trellis-core/mod.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/owned_api.d.ts +4 -4
- package/esm/generated-sdk/trellis-core/schemas.d.ts +113 -0
- package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/schemas.js +81 -0
- package/esm/generated-sdk/trellis-core/types.d.ts +54 -7
- package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/types.js +1 -1
- package/esm/health.d.ts +1 -1
- package/esm/health.d.ts.map +1 -1
- package/esm/health.js +1 -1
- package/esm/index.d.ts +4 -4
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -2
- package/esm/jobs.d.ts +69 -3
- package/esm/jobs.d.ts.map +1 -1
- package/esm/jobs.js +92 -3
- package/esm/server/health.d.ts +2 -6
- package/esm/server/health.d.ts.map +1 -1
- package/esm/server/health_schemas.d.ts +0 -8
- package/esm/server/health_schemas.d.ts.map +1 -1
- package/esm/server/health_schemas.js +0 -5
- package/esm/server/internal_jobs/bindings.d.ts +11 -0
- package/esm/server/internal_jobs/bindings.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.d.ts +58 -2
- package/esm/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/server/internal_jobs/job-manager.js +429 -55
- package/esm/server/internal_jobs/key-coordinator.d.ts +269 -0
- package/esm/server/internal_jobs/key-coordinator.d.ts.map +1 -0
- package/esm/server/internal_jobs/key-coordinator.js +677 -0
- package/esm/server/internal_jobs/projection.d.ts.map +1 -1
- package/esm/server/internal_jobs/projection.js +2 -0
- package/esm/server/internal_jobs/runtime-worker.d.ts +5 -1
- package/esm/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/esm/server/internal_jobs/runtime-worker.js +14 -2
- package/esm/server/internal_jobs/types.d.ts +5 -5
- package/esm/server/internal_jobs/types.d.ts.map +1 -1
- package/esm/server/internal_jobs/types.js +6 -0
- package/esm/server/runtime.d.ts.map +1 -1
- package/esm/server/service.d.ts +81 -112
- package/esm/server/service.d.ts.map +1 -1
- package/esm/server/service.js +372 -130
- package/esm/server.d.ts +3 -3
- package/esm/server.d.ts.map +1 -1
- package/esm/service/deno.d.ts +1 -1
- package/esm/service/deno.d.ts.map +1 -1
- package/esm/service/drizzle.d.ts +52 -0
- package/esm/service/drizzle.d.ts.map +1 -0
- package/esm/service/drizzle.js +108 -0
- package/esm/service/mod.d.ts +3 -3
- package/esm/service/mod.d.ts.map +1 -1
- package/esm/service/mod.js +2 -2
- package/esm/service/node.d.ts +1 -1
- package/esm/service/node.d.ts.map +1 -1
- package/esm/service/outbox_inbox.d.ts +76 -22
- package/esm/service/outbox_inbox.d.ts.map +1 -1
- package/esm/service/outbox_inbox.js +231 -70
- package/esm/telemetry/metrics.d.ts +55 -0
- package/esm/telemetry/metrics.d.ts.map +1 -1
- package/esm/telemetry/metrics.js +86 -0
- package/esm/telemetry/mod.d.ts +2 -1
- package/esm/telemetry/mod.d.ts.map +1 -1
- package/esm/telemetry/mod.js +1 -1
- package/esm/trellis.d.ts +62 -30
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +125 -42
- package/package.json +14 -2
- package/script/auth/mod.d.ts +1 -1
- package/script/auth/mod.d.ts.map +1 -1
- package/script/auth/mod.js +11 -4
- package/script/auth/protocol.d.ts +55 -0
- package/script/auth/protocol.d.ts.map +1 -1
- package/script/browser.d.ts +3 -3
- package/script/browser.d.ts.map +1 -1
- package/script/browser.js +3 -2
- package/script/client_connect.d.ts +12 -3
- package/script/client_connect.d.ts.map +1 -1
- package/script/client_connect.js +111 -6
- package/script/codec.d.ts +7 -6
- package/script/codec.d.ts.map +1 -1
- package/script/codec.js +124 -5
- package/script/contract_support/canonical.d.ts +3 -0
- package/script/contract_support/canonical.d.ts.map +1 -1
- package/script/contract_support/canonical.js +3 -0
- package/script/contract_support/mod.d.ts +125 -10
- package/script/contract_support/mod.d.ts.map +1 -1
- package/script/contract_support/mod.js +165 -5
- package/script/contract_support/protocol.d.ts +92 -7
- package/script/contract_support/protocol.d.ts.map +1 -1
- package/script/contract_support/protocol.js +42 -8
- package/script/contract_support/runtime.d.ts +4 -1
- package/script/contract_support/runtime.d.ts.map +1 -1
- package/script/errors/SchemaValidationError.d.ts +49 -0
- package/script/errors/SchemaValidationError.d.ts.map +1 -0
- package/script/errors/SchemaValidationError.js +74 -0
- package/script/errors/index.d.ts +38 -9
- package/script/errors/index.d.ts.map +1 -1
- package/script/errors/index.js +20 -1
- package/script/generated-sdk/auth/api.d.ts +33 -605
- package/script/generated-sdk/auth/api.d.ts.map +1 -1
- package/script/generated-sdk/auth/api.js +6 -1
- package/script/generated-sdk/auth/client.d.ts +129 -134
- package/script/generated-sdk/auth/client.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.d.ts +2 -601
- package/script/generated-sdk/auth/contract.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.js +310 -93
- package/script/generated-sdk/auth/mod.d.ts +1 -1
- package/script/generated-sdk/auth/mod.d.ts.map +1 -1
- package/script/generated-sdk/auth/owned_api.d.ts +88 -86
- package/script/generated-sdk/auth/owned_api.d.ts.map +1 -1
- package/script/generated-sdk/auth/owned_api.js +6 -0
- package/script/generated-sdk/auth/schemas.d.ts +284 -136
- package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/script/generated-sdk/auth/schemas.js +231 -92
- package/script/generated-sdk/auth/types.d.ts +565 -89
- package/script/generated-sdk/auth/types.d.ts.map +1 -1
- package/script/generated-sdk/auth/types.js +1 -1
- package/script/generated-sdk/health/api.d.ts +29 -18
- package/script/generated-sdk/health/api.d.ts.map +1 -1
- package/script/generated-sdk/health/client.d.ts +7 -21
- package/script/generated-sdk/health/client.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.d.ts +2 -15
- package/script/generated-sdk/health/contract.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.js +2 -10
- package/script/generated-sdk/health/mod.d.ts +1 -1
- package/script/generated-sdk/health/mod.d.ts.map +1 -1
- package/script/generated-sdk/health/owned_api.d.ts +2 -2
- package/script/generated-sdk/health/schemas.d.ts +1 -14
- package/script/generated-sdk/health/schemas.d.ts.map +1 -1
- package/script/generated-sdk/health/schemas.js +1 -9
- package/script/generated-sdk/health/types.d.ts +10 -5
- package/script/generated-sdk/health/types.d.ts.map +1 -1
- package/script/generated-sdk/health/types.js +1 -2
- package/script/generated-sdk/jobs/api.d.ts +29 -109
- package/script/generated-sdk/jobs/api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/client.d.ts +21 -33
- package/script/generated-sdk/jobs/client.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.d.ts +2 -106
- package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.js +268 -1
- package/script/generated-sdk/jobs/mod.d.ts +1 -1
- package/script/generated-sdk/jobs/mod.d.ts.map +1 -1
- package/script/generated-sdk/jobs/owned_api.d.ts +22 -9
- package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/owned_api.js +19 -0
- package/script/generated-sdk/jobs/schemas.d.ts +437 -0
- package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/script/generated-sdk/jobs/schemas.js +212 -1
- package/script/generated-sdk/jobs/types.d.ts +195 -12
- package/script/generated-sdk/jobs/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/types.js +1 -1
- package/script/generated-sdk/state/api.d.ts +29 -68
- package/script/generated-sdk/state/api.d.ts.map +1 -1
- package/script/generated-sdk/state/client.d.ts +17 -31
- package/script/generated-sdk/state/client.d.ts.map +1 -1
- package/script/generated-sdk/state/contract.d.ts +1 -64
- package/script/generated-sdk/state/contract.d.ts.map +1 -1
- package/script/generated-sdk/state/mod.d.ts +1 -1
- package/script/generated-sdk/state/mod.d.ts.map +1 -1
- package/script/generated-sdk/state/owned_api.d.ts +7 -7
- package/script/generated-sdk/state/types.d.ts +52 -9
- package/script/generated-sdk/state/types.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.d.ts +33 -45
- package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.js +6 -1
- package/script/generated-sdk/trellis-core/client.d.ts +31 -20
- package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts +2 -41
- package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.js +91 -1
- package/script/generated-sdk/trellis-core/mod.d.ts +1 -1
- package/script/generated-sdk/trellis-core/mod.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/owned_api.d.ts +4 -4
- package/script/generated-sdk/trellis-core/schemas.d.ts +113 -0
- package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/schemas.js +81 -0
- package/script/generated-sdk/trellis-core/types.d.ts +54 -7
- package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/types.js +1 -1
- package/script/health.d.ts +1 -1
- package/script/health.d.ts.map +1 -1
- package/script/health.js +1 -2
- package/script/index.d.ts +4 -4
- package/script/index.d.ts.map +1 -1
- package/script/index.js +2 -2
- package/script/jobs.d.ts +69 -3
- package/script/jobs.d.ts.map +1 -1
- package/script/jobs.js +93 -3
- package/script/server/health.d.ts +2 -6
- package/script/server/health.d.ts.map +1 -1
- package/script/server/health_schemas.d.ts +0 -8
- package/script/server/health_schemas.d.ts.map +1 -1
- package/script/server/health_schemas.js +1 -6
- package/script/server/internal_jobs/bindings.d.ts +11 -0
- package/script/server/internal_jobs/bindings.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.d.ts +58 -2
- package/script/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/server/internal_jobs/job-manager.js +429 -54
- package/script/server/internal_jobs/key-coordinator.d.ts +269 -0
- package/script/server/internal_jobs/key-coordinator.d.ts.map +1 -0
- package/script/server/internal_jobs/key-coordinator.js +690 -0
- package/script/server/internal_jobs/projection.d.ts.map +1 -1
- package/script/server/internal_jobs/projection.js +2 -0
- package/script/server/internal_jobs/runtime-worker.d.ts +5 -1
- package/script/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/script/server/internal_jobs/runtime-worker.js +14 -2
- package/script/server/internal_jobs/types.d.ts +5 -5
- package/script/server/internal_jobs/types.d.ts.map +1 -1
- package/script/server/internal_jobs/types.js +6 -0
- package/script/server/runtime.d.ts.map +1 -1
- package/script/server/service.d.ts +81 -112
- package/script/server/service.d.ts.map +1 -1
- package/script/server/service.js +369 -127
- package/script/server.d.ts +3 -3
- package/script/server.d.ts.map +1 -1
- package/script/service/deno.d.ts +1 -1
- package/script/service/deno.d.ts.map +1 -1
- package/script/service/drizzle.d.ts +52 -0
- package/script/service/drizzle.d.ts.map +1 -0
- package/script/service/drizzle.js +113 -0
- package/script/service/mod.d.ts +3 -3
- package/script/service/mod.d.ts.map +1 -1
- package/script/service/mod.js +4 -3
- package/script/service/node.d.ts +1 -1
- package/script/service/node.d.ts.map +1 -1
- package/script/service/outbox_inbox.d.ts +76 -22
- package/script/service/outbox_inbox.d.ts.map +1 -1
- package/script/service/outbox_inbox.js +233 -70
- package/script/telemetry/metrics.d.ts +55 -0
- package/script/telemetry/metrics.d.ts.map +1 -1
- package/script/telemetry/metrics.js +88 -0
- package/script/telemetry/mod.d.ts +2 -1
- package/script/telemetry/mod.d.ts.map +1 -1
- package/script/telemetry/mod.js +3 -1
- package/script/trellis.d.ts +62 -30
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +124 -41
- package/src/auth/mod.ts +7 -0
- package/src/browser.ts +5 -7
- package/src/client_connect.ts +200 -12
- package/src/codec.ts +186 -11
- package/src/contract_support/canonical.ts +3 -0
- package/src/contract_support/mod.ts +380 -9
- package/src/contract_support/protocol.ts +57 -10
- package/src/contract_support/runtime.ts +7 -0
- package/src/errors/SchemaValidationError.ts +67 -0
- package/src/errors/index.ts +28 -0
- package/src/health.ts +0 -1
- package/src/index.ts +7 -8
- package/src/jobs.ts +138 -1
- package/src/sdk/_generated/auth/api.ts +38 -7
- package/src/sdk/_generated/auth/client.ts +168 -530
- package/src/sdk/_generated/auth/contract.ts +310 -93
- package/src/sdk/_generated/auth/mod.ts +0 -1
- package/src/sdk/_generated/auth/owned_api.ts +92 -86
- package/src/sdk/_generated/auth/schemas.ts +231 -92
- package/src/sdk/_generated/auth/types.ts +1069 -273
- package/src/sdk/_generated/core/api.ts +38 -7
- package/src/sdk/_generated/core/client.ts +47 -73
- package/src/sdk/_generated/core/contract.ts +91 -1
- package/src/sdk/_generated/core/mod.ts +0 -1
- package/src/sdk/_generated/core/owned_api.ts +4 -4
- package/src/sdk/_generated/core/schemas.ts +81 -0
- package/src/sdk/_generated/core/types.ts +79 -15
- package/src/sdk/_generated/health/api.ts +29 -5
- package/src/sdk/_generated/health/client.ts +11 -58
- package/src/sdk/_generated/health/contract.ts +2 -10
- package/src/sdk/_generated/health/mod.ts +0 -1
- package/src/sdk/_generated/health/owned_api.ts +2 -2
- package/src/sdk/_generated/health/schemas.ts +1 -9
- package/src/sdk/_generated/health/types.ts +23 -2
- package/src/sdk/_generated/jobs/api.ts +29 -5
- package/src/sdk/_generated/jobs/client.ts +25 -109
- package/src/sdk/_generated/jobs/contract.ts +269 -1
- package/src/sdk/_generated/jobs/mod.ts +0 -1
- package/src/sdk/_generated/jobs/owned_api.ts +30 -9
- package/src/sdk/_generated/jobs/schemas.ts +213 -0
- package/src/sdk/_generated/jobs/types.ts +252 -18
- package/src/sdk/_generated/state/api.ts +29 -5
- package/src/sdk/_generated/state/client.ts +18 -95
- package/src/sdk/_generated/state/mod.ts +0 -1
- package/src/sdk/_generated/state/owned_api.ts +7 -7
- package/src/sdk/_generated/state/types.ts +91 -15
- package/src/server/health.ts +2 -6
- package/src/server/health_schemas.ts +0 -6
- package/src/server/internal_jobs/bindings.ts +11 -0
- package/src/server/internal_jobs/job-manager.ts +553 -24
- package/src/server/internal_jobs/key-coordinator.ts +1080 -0
- package/src/server/internal_jobs/projection.ts +2 -0
- package/src/server/internal_jobs/runtime-worker.ts +17 -1
- package/src/server/internal_jobs/types.ts +6 -0
- package/src/server/runtime.ts +4 -0
- package/src/server/service.ts +645 -625
- package/src/server.ts +14 -7
- package/src/service/deno.ts +0 -5
- package/src/service/drizzle.ts +184 -0
- package/src/service/mod.ts +17 -7
- package/src/service/node.ts +0 -5
- package/src/service/outbox_inbox.ts +354 -88
- package/src/telemetry/metrics.ts +198 -1
- package/src/telemetry/mod.ts +6 -0
- package/src/trellis.ts +286 -105
|
@@ -10,63 +10,131 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
12
|
var _MemoryOutboxRepository_messages, _MemoryInboxRepository_seen, _OutboxDispatcher_instances, _OutboxDispatcher_repository, _OutboxDispatcher_runtime, _OutboxDispatcher_options, _OutboxDispatcher_wakeTimer, _OutboxDispatcher_retryTimer, _OutboxDispatcher_idleTimer, _OutboxDispatcher_running, _OutboxDispatcher_pending, _OutboxDispatcher_retryDue, _OutboxDispatcher_stopped, _OutboxDispatcher_scheduleWakeup, _OutboxDispatcher_scheduleRetryWakeup, _OutboxDispatcher_scheduleIdleRetry, _OutboxDispatcher_run, _OutboxDispatcher_dispatchBatch, _OutboxDispatcher_retryDelayMs, _OutboxDispatcher_clearTimer;
|
|
13
|
-
import { isErr } from "@qlever-llc/result";
|
|
13
|
+
import { isErr, } from "@qlever-llc/result";
|
|
14
14
|
import { Type } from "typebox";
|
|
15
15
|
import { recordTrellisError } from "../telemetry/mod.js";
|
|
16
|
+
/** Default Trellis helper-table names for SQL outbox and inbox storage. */
|
|
16
17
|
export const defaultSqlOutboxTables = Object.freeze({
|
|
17
18
|
outbox: "trellis_outbox",
|
|
18
19
|
inbox: "trellis_inbox",
|
|
19
20
|
});
|
|
21
|
+
const sqlIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
20
22
|
/**
|
|
21
|
-
* Creates SQL outbox/inbox repositories plus
|
|
23
|
+
* Creates SQL outbox/inbox repositories plus current helper-table DDL.
|
|
22
24
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* equivalent Drizzle table definition using these table and column names, in
|
|
26
|
-
* their own Drizzle-managed migration flow.
|
|
25
|
+
* Use {@link getSqlOutboxMigrations} when services need versioned Trellis-owned
|
|
26
|
+
* migration artifacts for their normal database migration tooling.
|
|
27
27
|
*/
|
|
28
28
|
export function createSqlOutboxAdapter(executor, dialect, tables = defaultSqlOutboxTables) {
|
|
29
|
+
const sqlTables = validateSqlOutboxTables(tables);
|
|
29
30
|
return {
|
|
30
|
-
outbox: new SqlOutboxRepository(executor, dialect,
|
|
31
|
-
inbox: new SqlInboxRepository(executor, dialect,
|
|
31
|
+
outbox: new SqlOutboxRepository(executor, dialect, sqlTables),
|
|
32
|
+
inbox: new SqlInboxRepository(executor, dialect, sqlTables),
|
|
32
33
|
ddl: dialect === "postgres"
|
|
33
|
-
? createPostgresOutboxSchema(
|
|
34
|
-
: createSqliteOutboxSchema(
|
|
34
|
+
? createPostgresOutboxSchema(sqlTables)
|
|
35
|
+
: createSqliteOutboxSchema(sqlTables),
|
|
35
36
|
};
|
|
36
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns Trellis-owned SQL outbox/inbox migration artifacts for a dialect.
|
|
40
|
+
*
|
|
41
|
+
* Trellis generates the helper-table SQL, but services remain responsible for
|
|
42
|
+
* running these artifacts through their normal database migration tooling.
|
|
43
|
+
*/
|
|
44
|
+
export function getSqlOutboxMigrations(options) {
|
|
45
|
+
const tables = resolveSqlOutboxTables(options.tables);
|
|
46
|
+
const up = options.dialect === "postgres"
|
|
47
|
+
? createPostgresOutboxSchema(tables)
|
|
48
|
+
: createSqliteOutboxSchema(tables);
|
|
49
|
+
const down = createSqlOutboxDownSchema(tables);
|
|
50
|
+
return Object.freeze([
|
|
51
|
+
Object.freeze({
|
|
52
|
+
id: `trellis_sql_outbox_inbox_${options.dialect}_v1`,
|
|
53
|
+
version: 1,
|
|
54
|
+
dialect: options.dialect,
|
|
55
|
+
up,
|
|
56
|
+
down,
|
|
57
|
+
checksum: checksumMigrationSql(up, down),
|
|
58
|
+
}),
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
37
61
|
/** Returns SQLite DDL for Trellis outbox and inbox tables. */
|
|
38
62
|
export function createSqliteOutboxSchema(tables = defaultSqlOutboxTables) {
|
|
63
|
+
const sqlTables = validateSqlOutboxTables(tables);
|
|
39
64
|
return [
|
|
40
|
-
`CREATE TABLE IF NOT EXISTS ${
|
|
41
|
-
`CREATE INDEX IF NOT EXISTS ${
|
|
42
|
-
`CREATE TABLE IF NOT EXISTS ${
|
|
65
|
+
`CREATE TABLE IF NOT EXISTS ${sqlTables.outbox} (id TEXT PRIMARY KEY, kind TEXT NOT NULL, name TEXT NOT NULL, subject TEXT NOT NULL, payload TEXT NOT NULL, headers TEXT NOT NULL, state TEXT NOT NULL, attempts INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL, next_attempt_at TEXT, last_error TEXT, outcome TEXT)`,
|
|
66
|
+
`CREATE INDEX IF NOT EXISTS ${sqlTables.outbox}_due_idx ON ${sqlTables.outbox} (state, next_attempt_at)`,
|
|
67
|
+
`CREATE TABLE IF NOT EXISTS ${sqlTables.inbox} (message_id TEXT PRIMARY KEY, received_at TEXT NOT NULL)`,
|
|
43
68
|
];
|
|
44
69
|
}
|
|
45
70
|
/** Returns Postgres DDL for Trellis outbox and inbox tables. */
|
|
46
71
|
export function createPostgresOutboxSchema(tables = defaultSqlOutboxTables) {
|
|
72
|
+
const sqlTables = validateSqlOutboxTables(tables);
|
|
47
73
|
return [
|
|
48
|
-
`CREATE TABLE IF NOT EXISTS ${
|
|
49
|
-
`CREATE INDEX IF NOT EXISTS ${
|
|
50
|
-
`CREATE TABLE IF NOT EXISTS ${
|
|
74
|
+
`CREATE TABLE IF NOT EXISTS ${sqlTables.outbox} (id text PRIMARY KEY, kind text NOT NULL, name text NOT NULL, subject text NOT NULL, payload text NOT NULL, headers jsonb NOT NULL, state text NOT NULL, attempts integer NOT NULL, created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, next_attempt_at timestamptz, last_error text, outcome jsonb)`,
|
|
75
|
+
`CREATE INDEX IF NOT EXISTS ${sqlTables.outbox}_due_idx ON ${sqlTables.outbox} (state, next_attempt_at)`,
|
|
76
|
+
`CREATE TABLE IF NOT EXISTS ${sqlTables.inbox} (message_id text PRIMARY KEY, received_at timestamptz NOT NULL)`,
|
|
51
77
|
];
|
|
52
78
|
}
|
|
79
|
+
function createSqlOutboxDownSchema(tables) {
|
|
80
|
+
const sqlTables = validateSqlOutboxTables(tables);
|
|
81
|
+
return [
|
|
82
|
+
`DROP INDEX IF EXISTS ${sqlTables.outbox}_due_idx`,
|
|
83
|
+
`DROP TABLE IF EXISTS ${sqlTables.inbox}`,
|
|
84
|
+
`DROP TABLE IF EXISTS ${sqlTables.outbox}`,
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
function resolveSqlOutboxTables(tables) {
|
|
88
|
+
return validateSqlOutboxTables({
|
|
89
|
+
outbox: tables?.outbox ?? defaultSqlOutboxTables.outbox,
|
|
90
|
+
inbox: tables?.inbox ?? defaultSqlOutboxTables.inbox,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function validateSqlOutboxTables(tables) {
|
|
94
|
+
validateSqlIdentifier("outbox", tables.outbox);
|
|
95
|
+
validateSqlIdentifier("inbox", tables.inbox);
|
|
96
|
+
return Object.freeze({ outbox: tables.outbox, inbox: tables.inbox });
|
|
97
|
+
}
|
|
98
|
+
function validateSqlIdentifier(kind, name) {
|
|
99
|
+
if (!sqlIdentifierPattern.test(name)) {
|
|
100
|
+
throw new Error(`Invalid SQL ${kind} table name "${name}". Use a simple identifier matching ${sqlIdentifierPattern.source}.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function checksumMigrationSql(up, down) {
|
|
104
|
+
return `fnv1a64:${fnv1a64Hex([
|
|
105
|
+
"-- up",
|
|
106
|
+
...up,
|
|
107
|
+
"-- down",
|
|
108
|
+
...down,
|
|
109
|
+
].join("\n"))}`;
|
|
110
|
+
}
|
|
111
|
+
function fnv1a64Hex(input) {
|
|
112
|
+
let hash = 0xcbf29ce484222325n;
|
|
113
|
+
const prime = 0x100000001b3n;
|
|
114
|
+
for (const character of input) {
|
|
115
|
+
hash ^= BigInt(character.codePointAt(0) ?? 0);
|
|
116
|
+
hash = BigInt.asUintN(64, hash * prime);
|
|
117
|
+
}
|
|
118
|
+
return hash.toString(16).padStart(16, "0");
|
|
119
|
+
}
|
|
53
120
|
/** In-memory outbox repository intended for tests and local process adapters. */
|
|
54
121
|
export class MemoryOutboxRepository {
|
|
55
122
|
constructor() {
|
|
56
123
|
_MemoryOutboxRepository_messages.set(this, new Map());
|
|
57
124
|
}
|
|
58
|
-
async enqueue(
|
|
125
|
+
async enqueue(record) {
|
|
59
126
|
const now = new Date().toISOString();
|
|
60
|
-
const id =
|
|
127
|
+
const id = record.id;
|
|
61
128
|
const existing = __classPrivateFieldGet(this, _MemoryOutboxRepository_messages, "f").get(id);
|
|
62
129
|
if (existing)
|
|
63
130
|
return existing;
|
|
64
131
|
const message = {
|
|
65
132
|
id,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
133
|
+
kind: record.kind,
|
|
134
|
+
name: record.name,
|
|
135
|
+
subject: record.subject,
|
|
136
|
+
payload: record.payload,
|
|
137
|
+
headers: { ...record.headers },
|
|
70
138
|
state: "pending",
|
|
71
139
|
attempts: 0,
|
|
72
140
|
createdAt: now,
|
|
@@ -90,7 +158,7 @@ export class MemoryOutboxRepository {
|
|
|
90
158
|
}
|
|
91
159
|
return claimed;
|
|
92
160
|
}
|
|
93
|
-
async markDispatched(id, now) {
|
|
161
|
+
async markDispatched(id, now, outcome) {
|
|
94
162
|
const message = __classPrivateFieldGet(this, _MemoryOutboxRepository_messages, "f").get(id);
|
|
95
163
|
if (!message)
|
|
96
164
|
return;
|
|
@@ -100,6 +168,7 @@ export class MemoryOutboxRepository {
|
|
|
100
168
|
updatedAt: now.toISOString(),
|
|
101
169
|
nextAttemptAt: undefined,
|
|
102
170
|
lastError: undefined,
|
|
171
|
+
outcome: outcome ?? message.outcome,
|
|
103
172
|
});
|
|
104
173
|
}
|
|
105
174
|
async markFailed(id, failure) {
|
|
@@ -155,17 +224,19 @@ export class SqlOutboxRepository {
|
|
|
155
224
|
enumerable: true,
|
|
156
225
|
configurable: true,
|
|
157
226
|
writable: true,
|
|
158
|
-
value:
|
|
227
|
+
value: void 0
|
|
159
228
|
});
|
|
229
|
+
this.tables = validateSqlOutboxTables(tables);
|
|
160
230
|
}
|
|
161
|
-
async enqueue(
|
|
231
|
+
async enqueue(record) {
|
|
162
232
|
const now = new Date().toISOString();
|
|
163
233
|
const message = {
|
|
164
|
-
id:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
234
|
+
id: record.id,
|
|
235
|
+
kind: record.kind,
|
|
236
|
+
name: record.name,
|
|
237
|
+
subject: record.subject,
|
|
238
|
+
payload: record.payload,
|
|
239
|
+
headers: { ...record.headers },
|
|
169
240
|
state: "pending",
|
|
170
241
|
attempts: 0,
|
|
171
242
|
createdAt: now,
|
|
@@ -175,9 +246,10 @@ export class SqlOutboxRepository {
|
|
|
175
246
|
const conflict = this.dialect === "postgres"
|
|
176
247
|
? "ON CONFLICT (id) DO NOTHING"
|
|
177
248
|
: "ON CONFLICT(id) DO NOTHING";
|
|
178
|
-
await this.executor.execute(`INSERT INTO ${this.tables.outbox} (id,
|
|
249
|
+
await this.executor.execute(`INSERT INTO ${this.tables.outbox} (id, kind, name, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error, outcome) VALUES (${placeholders(this.dialect, 13)}) ${conflict}`, [
|
|
179
250
|
message.id,
|
|
180
|
-
message.
|
|
251
|
+
message.kind,
|
|
252
|
+
message.name,
|
|
181
253
|
message.subject,
|
|
182
254
|
message.payload,
|
|
183
255
|
headers,
|
|
@@ -187,15 +259,17 @@ export class SqlOutboxRepository {
|
|
|
187
259
|
message.updatedAt,
|
|
188
260
|
null,
|
|
189
261
|
null,
|
|
262
|
+
null,
|
|
190
263
|
]);
|
|
191
264
|
return message;
|
|
192
265
|
}
|
|
193
266
|
async claimDue(limit, now) {
|
|
194
|
-
const rows = await this.executor.query(`SELECT id,
|
|
267
|
+
const rows = await this.executor.query(`SELECT id, kind, name, subject, payload, headers, state, attempts, created_at, updated_at, next_attempt_at, last_error, outcome FROM ${this.tables.outbox} WHERE state != ${placeholder(this.dialect, 1)} AND (next_attempt_at IS NULL OR next_attempt_at <= ${placeholder(this.dialect, 2)}) ORDER BY created_at LIMIT ${placeholder(this.dialect, 3)}`, ["dispatched", now.toISOString(), limit]);
|
|
195
268
|
return rows.map(rowToOutboxMessage);
|
|
196
269
|
}
|
|
197
|
-
async markDispatched(id, now) {
|
|
198
|
-
|
|
270
|
+
async markDispatched(id, now, outcome) {
|
|
271
|
+
const outcomeJson = outcome !== undefined ? JSON.stringify(outcome) : null;
|
|
272
|
+
await this.executor.execute(`UPDATE ${this.tables.outbox} SET state = ${placeholder(this.dialect, 1)}, updated_at = ${placeholder(this.dialect, 2)}, next_attempt_at = NULL, last_error = NULL, outcome = ${placeholder(this.dialect, 3)} WHERE id = ${placeholder(this.dialect, 4)}`, ["dispatched", now.toISOString(), outcomeJson, id]);
|
|
199
273
|
}
|
|
200
274
|
async markFailed(id, failure) {
|
|
201
275
|
await this.executor.execute(`UPDATE ${this.tables.outbox} SET state = ${placeholder(this.dialect, 1)}, attempts = attempts + 1, updated_at = ${placeholder(this.dialect, 2)}, next_attempt_at = ${placeholder(this.dialect, 3)}, last_error = ${placeholder(this.dialect, 4)} WHERE id = ${placeholder(this.dialect, 5)}`, [
|
|
@@ -226,8 +300,9 @@ export class SqlInboxRepository {
|
|
|
226
300
|
enumerable: true,
|
|
227
301
|
configurable: true,
|
|
228
302
|
writable: true,
|
|
229
|
-
value:
|
|
303
|
+
value: void 0
|
|
230
304
|
});
|
|
305
|
+
this.tables = validateSqlOutboxTables(tables);
|
|
231
306
|
}
|
|
232
307
|
async record(messageId, now = new Date()) {
|
|
233
308
|
try {
|
|
@@ -254,7 +329,8 @@ const KvInboxRecordSchema = Type.Object({
|
|
|
254
329
|
});
|
|
255
330
|
export const KvOutboxRecordSchema = Type.Object({
|
|
256
331
|
id: Type.String(),
|
|
257
|
-
|
|
332
|
+
kind: Type.String(),
|
|
333
|
+
name: Type.String(),
|
|
258
334
|
subject: Type.String(),
|
|
259
335
|
payload: Type.String(),
|
|
260
336
|
headers: Type.Record(Type.String(), Type.String()),
|
|
@@ -269,6 +345,7 @@ export const KvOutboxRecordSchema = Type.Object({
|
|
|
269
345
|
updatedAt: Type.String(),
|
|
270
346
|
nextAttemptAt: Type.Optional(Type.String()),
|
|
271
347
|
lastError: Type.Optional(Type.String()),
|
|
348
|
+
outcome: Type.Optional(Type.String()),
|
|
272
349
|
});
|
|
273
350
|
/** Durable NATS KV outbox repository for services without SQL state. */
|
|
274
351
|
export class NatsKvOutboxRepository {
|
|
@@ -280,14 +357,15 @@ export class NatsKvOutboxRepository {
|
|
|
280
357
|
value: kv
|
|
281
358
|
});
|
|
282
359
|
}
|
|
283
|
-
async enqueue(
|
|
360
|
+
async enqueue(rec) {
|
|
284
361
|
const now = new Date().toISOString();
|
|
285
362
|
const record = {
|
|
286
|
-
id:
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
363
|
+
id: rec.id,
|
|
364
|
+
kind: rec.kind,
|
|
365
|
+
name: rec.name,
|
|
366
|
+
subject: rec.subject,
|
|
367
|
+
payload: rec.payload,
|
|
368
|
+
headers: { ...rec.headers },
|
|
291
369
|
state: "pending",
|
|
292
370
|
attempts: 0,
|
|
293
371
|
createdAt: now,
|
|
@@ -341,19 +419,23 @@ export class NatsKvOutboxRepository {
|
|
|
341
419
|
}
|
|
342
420
|
return claimed;
|
|
343
421
|
}
|
|
344
|
-
async markDispatched(id, now) {
|
|
422
|
+
async markDispatched(id, now, outcome) {
|
|
345
423
|
const loaded = await this.kv.get(id).take();
|
|
346
424
|
if (isErr(loaded)) {
|
|
347
425
|
if (hasKvReason(loaded.error, "not found"))
|
|
348
426
|
return;
|
|
349
427
|
throw loaded.error;
|
|
350
428
|
}
|
|
429
|
+
const outcomeStr = outcome !== undefined
|
|
430
|
+
? JSON.stringify(outcome)
|
|
431
|
+
: undefined;
|
|
351
432
|
const stored = await loaded.put({
|
|
352
433
|
...loaded.value,
|
|
353
434
|
state: "dispatched",
|
|
354
435
|
updatedAt: now.toISOString(),
|
|
355
436
|
nextAttemptAt: undefined,
|
|
356
437
|
lastError: undefined,
|
|
438
|
+
outcome: outcomeStr ?? loaded.value.outcome,
|
|
357
439
|
}, true).take();
|
|
358
440
|
if (isErr(stored))
|
|
359
441
|
throw stored.error;
|
|
@@ -550,7 +632,7 @@ _OutboxDispatcher_repository = new WeakMap(), _OutboxDispatcher_runtime = new We
|
|
|
550
632
|
__classPrivateFieldSet(this, _OutboxDispatcher_idleTimer, undefined, "f");
|
|
551
633
|
}
|
|
552
634
|
};
|
|
553
|
-
/** Dispatches due outbox messages through a
|
|
635
|
+
/** Dispatches due outbox messages through a dispatch runtime. */
|
|
554
636
|
export async function dispatchOutbox(repository, runtime, options = {}) {
|
|
555
637
|
const now = options.now ?? new Date();
|
|
556
638
|
const retryDelayMs = options.retryDelayMs ?? 1000;
|
|
@@ -558,47 +640,115 @@ export async function dispatchOutbox(repository, runtime, options = {}) {
|
|
|
558
640
|
let dispatched = 0;
|
|
559
641
|
let failed = 0;
|
|
560
642
|
for (const message of messages) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
643
|
+
if (message.kind === "event.publish") {
|
|
644
|
+
const result = await runtime.publishPreparedEvent(outboxMessageToPreparedEvent(message));
|
|
645
|
+
const value = result.take();
|
|
646
|
+
if (isErr(value)) {
|
|
647
|
+
recordTrellisError(value.error, {
|
|
648
|
+
surface: "outbox",
|
|
649
|
+
direction: "dispatcher",
|
|
650
|
+
operation: message.name,
|
|
651
|
+
phase: "publish",
|
|
652
|
+
messagingSystem: "nats",
|
|
653
|
+
});
|
|
654
|
+
failed += 1;
|
|
655
|
+
await repository.markFailed(message.id, {
|
|
656
|
+
error: value.error.message,
|
|
657
|
+
nextAttemptAt: new Date(now.getTime() + retryDelayMs),
|
|
658
|
+
now,
|
|
659
|
+
});
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
dispatched += 1;
|
|
663
|
+
await repository.markDispatched(message.id, now);
|
|
664
|
+
}
|
|
665
|
+
else if (message.kind === "job.create" || message.kind === "job.submit") {
|
|
666
|
+
if (runtime.dispatchJobSubmission) {
|
|
667
|
+
const result = await runtime.dispatchJobSubmission(message);
|
|
668
|
+
const value = result.take();
|
|
669
|
+
if (isErr(value)) {
|
|
670
|
+
recordTrellisError(value.error, {
|
|
671
|
+
surface: "outbox",
|
|
672
|
+
direction: "dispatcher",
|
|
673
|
+
operation: message.name,
|
|
674
|
+
phase: "job.dispatch",
|
|
675
|
+
});
|
|
676
|
+
failed += 1;
|
|
677
|
+
await repository.markFailed(message.id, {
|
|
678
|
+
error: value.error.message,
|
|
679
|
+
nextAttemptAt: new Date(now.getTime() + retryDelayMs),
|
|
680
|
+
now,
|
|
681
|
+
});
|
|
682
|
+
continue;
|
|
683
|
+
}
|
|
684
|
+
dispatched += 1;
|
|
685
|
+
await repository.markDispatched(message.id, now);
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
recordTrellisError(new Error(`job dispatch not supported`), {
|
|
689
|
+
surface: "outbox",
|
|
690
|
+
direction: "dispatcher",
|
|
691
|
+
operation: message.name,
|
|
692
|
+
phase: "dispatch",
|
|
693
|
+
});
|
|
694
|
+
await repository.markDispatched(message.id, now, {
|
|
695
|
+
error: "job dispatch not supported",
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
const error = `Unknown outbox record kind: ${message.kind}`;
|
|
701
|
+
recordTrellisError(new Error(error), {
|
|
565
702
|
surface: "outbox",
|
|
566
703
|
direction: "dispatcher",
|
|
567
|
-
operation: message.
|
|
568
|
-
phase: "
|
|
569
|
-
messagingSystem: "nats",
|
|
704
|
+
operation: message.name,
|
|
705
|
+
phase: "dispatch",
|
|
570
706
|
});
|
|
571
|
-
|
|
572
|
-
await repository.markFailed(message.id, {
|
|
573
|
-
error: value.error.message,
|
|
574
|
-
nextAttemptAt: new Date(now.getTime() + retryDelayMs),
|
|
575
|
-
now,
|
|
576
|
-
});
|
|
577
|
-
continue;
|
|
707
|
+
await repository.markDispatched(message.id, now, { error });
|
|
578
708
|
}
|
|
579
|
-
dispatched += 1;
|
|
580
|
-
await repository.markDispatched(message.id, now);
|
|
581
709
|
}
|
|
582
710
|
return { dispatched, failed };
|
|
583
711
|
}
|
|
584
|
-
/** Rehydrates a persisted outbox row into a prepared event. */
|
|
585
|
-
export function
|
|
712
|
+
/** Rehydrates a persisted outbox event row into a prepared event. */
|
|
713
|
+
export function outboxMessageToPreparedEvent(message) {
|
|
714
|
+
if (message.kind !== "event.publish") {
|
|
715
|
+
throw new Error(`Expected event.publish kind, got ${message.kind}`);
|
|
716
|
+
}
|
|
717
|
+
const payload = JSON.parse(message.payload);
|
|
718
|
+
const header = eventHeaderFromMessage(message.headers);
|
|
586
719
|
return Object.freeze({
|
|
587
|
-
event: message.
|
|
720
|
+
event: message.name,
|
|
588
721
|
subject: message.subject,
|
|
589
|
-
|
|
722
|
+
header: Object.freeze(header),
|
|
723
|
+
payload: Object.freeze(payload),
|
|
590
724
|
encodedPayload: message.payload,
|
|
591
725
|
headers: Object.freeze({ ...message.headers }),
|
|
592
726
|
});
|
|
593
727
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
728
|
+
/** Adapts a prepared Trellis event into a generic outbox record. */
|
|
729
|
+
export function preparedTrellisEventToOutboxRecord(event) {
|
|
730
|
+
return {
|
|
731
|
+
id: event.headers["Nats-Msg-Id"] ?? event.header.id,
|
|
732
|
+
kind: "event.publish",
|
|
733
|
+
name: event.event,
|
|
734
|
+
subject: event.subject,
|
|
735
|
+
payload: event.encodedPayload,
|
|
736
|
+
headers: event.headers,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
function eventHeaderFromMessage(headers) {
|
|
740
|
+
const id = headers["Nats-Msg-Id"] ?? headers["nats-msg-id"];
|
|
741
|
+
const time = headers["Trellis-Event-Time"] ?? headers["trellis-event-time"];
|
|
742
|
+
return {
|
|
743
|
+
id: typeof id === "string" ? id : "",
|
|
744
|
+
time: typeof time === "string" ? time : new Date(0).toISOString(),
|
|
745
|
+
};
|
|
597
746
|
}
|
|
598
747
|
function rowToOutboxMessage(row) {
|
|
599
748
|
return {
|
|
600
749
|
id: stringField(row, "id"),
|
|
601
|
-
|
|
750
|
+
kind: kindField(row, "kind"),
|
|
751
|
+
name: stringField(row, "name"),
|
|
602
752
|
subject: stringField(row, "subject"),
|
|
603
753
|
payload: stringField(row, "payload"),
|
|
604
754
|
headers: parseHeaders(row["headers"]),
|
|
@@ -608,12 +758,14 @@ function rowToOutboxMessage(row) {
|
|
|
608
758
|
updatedAt: stringField(row, "updated_at"),
|
|
609
759
|
nextAttemptAt: optionalStringField(row, "next_attempt_at"),
|
|
610
760
|
lastError: optionalStringField(row, "last_error"),
|
|
761
|
+
outcome: optionalStringField(row, "outcome"),
|
|
611
762
|
};
|
|
612
763
|
}
|
|
613
764
|
function kvRecordToOutboxMessage(record) {
|
|
614
765
|
return {
|
|
615
766
|
id: record.id,
|
|
616
|
-
|
|
767
|
+
kind: record.kind,
|
|
768
|
+
name: record.name,
|
|
617
769
|
subject: record.subject,
|
|
618
770
|
payload: record.payload,
|
|
619
771
|
headers: { ...record.headers },
|
|
@@ -623,6 +775,7 @@ function kvRecordToOutboxMessage(record) {
|
|
|
623
775
|
updatedAt: record.updatedAt,
|
|
624
776
|
nextAttemptAt: record.nextAttemptAt,
|
|
625
777
|
lastError: record.lastError,
|
|
778
|
+
outcome: record.outcome,
|
|
626
779
|
};
|
|
627
780
|
}
|
|
628
781
|
function placeholder(dialect, index) {
|
|
@@ -677,6 +830,14 @@ function numberField(row, field) {
|
|
|
677
830
|
}
|
|
678
831
|
return value;
|
|
679
832
|
}
|
|
833
|
+
function kindField(row, field) {
|
|
834
|
+
const value = stringField(row, field);
|
|
835
|
+
if (value === "event.publish" || value === "job.create" ||
|
|
836
|
+
value === "job.submit") {
|
|
837
|
+
return value;
|
|
838
|
+
}
|
|
839
|
+
throw new Error(`Expected SQL field ${field} to be an outbox record kind`);
|
|
840
|
+
}
|
|
680
841
|
function stateField(row, field) {
|
|
681
842
|
const value = stringField(row, field);
|
|
682
843
|
if (value === "pending" || value === "dispatched" || value === "failed") {
|
|
@@ -20,8 +20,63 @@ export type TrellisErrorMetricAttributes = {
|
|
|
20
20
|
/** Static messaging operation name, when already known. */
|
|
21
21
|
messagingOperation?: string;
|
|
22
22
|
};
|
|
23
|
+
/** Duration metric names accepted by {@link recordTrellisDuration}. */
|
|
24
|
+
export type TrellisDurationMetricName = "trellis.connect.duration" | "trellis.auth.flow.duration" | "trellis.auth.approval_resolution.duration" | "trellis.auth.callout.duration" | "trellis.admin.workflow.duration" | "trellis.contract.analysis.duration";
|
|
25
|
+
/** Low-cardinality attributes accepted by {@link recordTrellisDuration}. */
|
|
26
|
+
export type TrellisDurationMetricAttributes = {
|
|
27
|
+
/** Stable Trellis surface name, such as `rpc`, `jobs`, or `operations`. */
|
|
28
|
+
surface?: string;
|
|
29
|
+
/** Stable operation kind or method name. Do not pass IDs, subjects, or URLs. */
|
|
30
|
+
operation?: string;
|
|
31
|
+
/** Stable lifecycle phase such as `bootstrap`, `encode`, or `total`. */
|
|
32
|
+
phase?: string;
|
|
33
|
+
/** Stable outcome label such as `ok` or `error`. */
|
|
34
|
+
outcome?: string;
|
|
35
|
+
/** Participant kind such as `admin`, `client`, `service`, or `device`. */
|
|
36
|
+
participantKind?: string;
|
|
37
|
+
/** Session kind such as `user`, `service`, or `device`. */
|
|
38
|
+
sessionKind?: string;
|
|
39
|
+
/** Auth flow such as `local`, `oauth`, `device`, or `bootstrap`. */
|
|
40
|
+
authFlow?: string;
|
|
41
|
+
/** Auth approval outcome such as `approved`, `denied`, `required`, or `none`. */
|
|
42
|
+
authApproval?: string;
|
|
43
|
+
/** Whether a deployment authority is present. */
|
|
44
|
+
authorityPresent?: boolean;
|
|
45
|
+
/** Plan classification such as `install`, `update`, `migration`, `noop`, or `unknown`. */
|
|
46
|
+
planClassification?: string;
|
|
47
|
+
/** Contract kind such as `app`, `service`, `device`, `builtin`, or `unknown`. */
|
|
48
|
+
contractKind?: string;
|
|
49
|
+
/** Static messaging system name, when already known. */
|
|
50
|
+
messagingSystem?: string;
|
|
51
|
+
/** Static messaging operation name, when already known. */
|
|
52
|
+
messagingOperation?: string;
|
|
53
|
+
};
|
|
23
54
|
/** Returns the shared Trellis OpenTelemetry meter. */
|
|
24
55
|
export declare function getTrellisMeter(): Meter;
|
|
25
56
|
/** Records one Trellis error with only stable, low-cardinality attributes. */
|
|
26
57
|
export declare function recordTrellisError(error: unknown, attributes?: TrellisErrorMetricAttributes): void;
|
|
58
|
+
/**
|
|
59
|
+
* Records one duration measurement on the given Trellis histogram.
|
|
60
|
+
*
|
|
61
|
+
* Converts `durationMs` to seconds. Negative, NaN, and infinite values are
|
|
62
|
+
* silently ignored.
|
|
63
|
+
*
|
|
64
|
+
* Histogram instruments are cached by metric name so `createHistogram` is
|
|
65
|
+
* called at most once per metric name.
|
|
66
|
+
*
|
|
67
|
+
* @param name - The duration metric name.
|
|
68
|
+
* @param durationMs - The measured duration in milliseconds.
|
|
69
|
+
* @param attributes - Optional low-cardinality attributes. Only values that
|
|
70
|
+
* pass sanitization are included.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* recordTrellisDuration("trellis.connect.duration", 42.5, {
|
|
75
|
+
* phase: "nats_connect",
|
|
76
|
+
* outcome: "ok",
|
|
77
|
+
* participantKind: "client",
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function recordTrellisDuration(name: TrellisDurationMetricName, durationMs: number, attributes?: TrellisDurationMetricAttributes): void;
|
|
27
82
|
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/telemetry/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,KAAK,EAAW,MAAM,oBAAoB,CAAC;AAiDzE,yEAAyE;AACzE,MAAM,MAAM,4BAA4B,GAAG;IACzC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,yBAAyB,GACjC,0BAA0B,GAC1B,4BAA4B,GAC5B,2CAA2C,GAC3C,+BAA+B,GAC/B,iCAAiC,GACjC,oCAAoC,CAAC;AAEzC,4EAA4E;AAC5E,MAAM,MAAM,+BAA+B,GAAG;IAC5C,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0FAA0F;IAC1F,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAWF,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAEvC;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,UAAU,GAAE,4BAAiC,GAC5C,IAAI,CAWN;AAsJD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,yBAAyB,EAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,+BAA+B,GAC3C,IAAI,CAaN"}
|
package/esm/telemetry/metrics.js
CHANGED
|
@@ -42,6 +42,7 @@ const AUTH_REASONS = new Set([
|
|
|
42
42
|
"device_identity_key_mismatch",
|
|
43
43
|
"invalid_device_qr_mac",
|
|
44
44
|
]);
|
|
45
|
+
const DURATION_HISTOGRAM_CACHE = new Map();
|
|
45
46
|
/** Returns the shared Trellis OpenTelemetry meter. */
|
|
46
47
|
export function getTrellisMeter() {
|
|
47
48
|
return metrics.getMeter(TRELLIS_METER_NAME);
|
|
@@ -79,6 +80,91 @@ export function buildTrellisErrorMetricAttributes(error, attributes = {}) {
|
|
|
79
80
|
setLowCardinalityAttribute(metricAttributes, "messaging.operation", attributes.messagingOperation);
|
|
80
81
|
return metricAttributes;
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Builds sanitized, low-cardinality attributes for duration histograms.
|
|
85
|
+
*
|
|
86
|
+
* @internal Exported for focused tests; runtime callers should use
|
|
87
|
+
* {@link recordTrellisDuration}.
|
|
88
|
+
*/
|
|
89
|
+
export function buildTrellisDurationMetricAttributes(attributes = {}) {
|
|
90
|
+
const metricAttributes = {};
|
|
91
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.surface", attributes.surface);
|
|
92
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.operation", attributes.operation);
|
|
93
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.phase", attributes.phase);
|
|
94
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.outcome", attributes.outcome);
|
|
95
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.participant.kind", attributes.participantKind);
|
|
96
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.session.kind", attributes.sessionKind);
|
|
97
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.auth.flow", attributes.authFlow);
|
|
98
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.auth.approval", attributes.authApproval);
|
|
99
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.plan.classification", attributes.planClassification);
|
|
100
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.contract.kind", attributes.contractKind);
|
|
101
|
+
setLowCardinalityAttribute(metricAttributes, "messaging.system", attributes.messagingSystem);
|
|
102
|
+
setLowCardinalityAttribute(metricAttributes, "messaging.operation", attributes.messagingOperation);
|
|
103
|
+
if (attributes.authorityPresent !== undefined) {
|
|
104
|
+
setLowCardinalityAttribute(metricAttributes, "trellis.authority.present", String(attributes.authorityPresent));
|
|
105
|
+
}
|
|
106
|
+
return metricAttributes;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Records one duration measurement on the given Trellis histogram.
|
|
110
|
+
*
|
|
111
|
+
* Converts `durationMs` to seconds. Negative, NaN, and infinite values are
|
|
112
|
+
* silently ignored.
|
|
113
|
+
*
|
|
114
|
+
* Histogram instruments are cached by metric name so `createHistogram` is
|
|
115
|
+
* called at most once per metric name.
|
|
116
|
+
*
|
|
117
|
+
* @param name - The duration metric name.
|
|
118
|
+
* @param durationMs - The measured duration in milliseconds.
|
|
119
|
+
* @param attributes - Optional low-cardinality attributes. Only values that
|
|
120
|
+
* pass sanitization are included.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* recordTrellisDuration("trellis.connect.duration", 42.5, {
|
|
125
|
+
* phase: "nats_connect",
|
|
126
|
+
* outcome: "ok",
|
|
127
|
+
* participantKind: "client",
|
|
128
|
+
* });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export function recordTrellisDuration(name, durationMs, attributes) {
|
|
132
|
+
if (typeof durationMs !== "number" ||
|
|
133
|
+
durationMs < 0 ||
|
|
134
|
+
!Number.isFinite(durationMs)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const histogram = getDurationHistogram(name);
|
|
138
|
+
const metricAttributes = buildTrellisDurationMetricAttributes(attributes);
|
|
139
|
+
histogram.record(durationMs / 1000, metricAttributes);
|
|
140
|
+
}
|
|
141
|
+
function getDurationHistogram(name) {
|
|
142
|
+
let histogram = DURATION_HISTOGRAM_CACHE.get(name);
|
|
143
|
+
if (!histogram) {
|
|
144
|
+
histogram = getTrellisMeter().createHistogram(name, {
|
|
145
|
+
description: histogramDescription(name),
|
|
146
|
+
unit: "s",
|
|
147
|
+
});
|
|
148
|
+
DURATION_HISTOGRAM_CACHE.set(name, histogram);
|
|
149
|
+
}
|
|
150
|
+
return histogram;
|
|
151
|
+
}
|
|
152
|
+
function histogramDescription(name) {
|
|
153
|
+
switch (name) {
|
|
154
|
+
case "trellis.connect.duration":
|
|
155
|
+
return "Duration of connection lifecycle phases.";
|
|
156
|
+
case "trellis.auth.flow.duration":
|
|
157
|
+
return "Duration of auth flow phases.";
|
|
158
|
+
case "trellis.auth.approval_resolution.duration":
|
|
159
|
+
return "Duration of approval resolution phases.";
|
|
160
|
+
case "trellis.auth.callout.duration":
|
|
161
|
+
return "Duration of NATS auth callout phases.";
|
|
162
|
+
case "trellis.admin.workflow.duration":
|
|
163
|
+
return "Duration of admin workflow phases.";
|
|
164
|
+
case "trellis.contract.analysis.duration":
|
|
165
|
+
return "Duration of contract analysis phases.";
|
|
166
|
+
}
|
|
167
|
+
}
|
|
82
168
|
function trellisErrorType(error, serializable, override) {
|
|
83
169
|
const overrideType = lowCardinalityValue(override);
|
|
84
170
|
if (overrideType)
|