@spine-event-engine/server 2.0.0-snapshot.24 → 2.0.0-snapshot.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -19
- package/REFERENCE.md +538 -150
- package/dist/agent/agent-acceptance-receipts.d.ts +69 -0
- package/dist/agent/agent-acceptance-receipts.d.ts.map +1 -0
- package/dist/agent/agent-acceptance-receipts.js +198 -0
- package/dist/agent/agent-acceptance-receipts.js.map +1 -0
- package/dist/agent/agent-execution-capacity.d.ts +37 -9
- package/dist/agent/agent-execution-capacity.d.ts.map +1 -1
- package/dist/agent/agent-execution-capacity.js +73 -15
- package/dist/agent/agent-execution-capacity.js.map +1 -1
- package/dist/agent/agent-history.d.ts +33 -12
- package/dist/agent/agent-history.d.ts.map +1 -1
- package/dist/agent/agent-history.js +61 -18
- package/dist/agent/agent-history.js.map +1 -1
- package/dist/agent/agent-live-ai-audit.d.ts +95 -0
- package/dist/agent/agent-live-ai-audit.d.ts.map +1 -0
- package/dist/agent/agent-live-ai-audit.js +290 -0
- package/dist/agent/agent-live-ai-audit.js.map +1 -0
- package/dist/agent/agent-live-ai-runtime.d.ts +300 -0
- package/dist/agent/agent-live-ai-runtime.d.ts.map +1 -0
- package/dist/agent/agent-live-ai-runtime.js +611 -0
- package/dist/agent/agent-live-ai-runtime.js.map +1 -0
- package/dist/agent/agent-live-audit.d.ts +67 -0
- package/dist/agent/agent-live-audit.d.ts.map +1 -0
- package/dist/agent/agent-live-audit.js +121 -0
- package/dist/agent/agent-live-audit.js.map +1 -0
- package/dist/agent/agent-live-budget.d.ts +84 -0
- package/dist/agent/agent-live-budget.d.ts.map +1 -0
- package/dist/agent/agent-live-budget.js +161 -0
- package/dist/agent/agent-live-budget.js.map +1 -0
- package/dist/agent/agent-live-fault.d.ts +18 -0
- package/dist/agent/agent-live-fault.d.ts.map +1 -0
- package/dist/agent/{agent-execution-fault.js → agent-live-fault.js} +7 -7
- package/dist/agent/agent-live-fault.js.map +1 -0
- package/dist/agent/agent-live-inputs.d.ts +74 -0
- package/dist/agent/agent-live-inputs.d.ts.map +1 -0
- package/dist/agent/agent-live-inputs.js +15 -0
- package/dist/agent/agent-live-inputs.js.map +1 -0
- package/dist/agent/agent-live-interaction-events.d.ts +46 -0
- package/dist/agent/agent-live-interaction-events.d.ts.map +1 -0
- package/dist/agent/agent-live-interaction-events.js +104 -0
- package/dist/agent/agent-live-interaction-events.js.map +1 -0
- package/dist/agent/agent-live-mcp-controls.d.ts +129 -0
- package/dist/agent/agent-live-mcp-controls.d.ts.map +1 -0
- package/dist/agent/agent-live-mcp-controls.js +228 -0
- package/dist/agent/agent-live-mcp-controls.js.map +1 -0
- package/dist/agent/agent-live-mcp-host.d.ts +88 -0
- package/dist/agent/agent-live-mcp-host.d.ts.map +1 -0
- package/dist/agent/{agent-mcp-host.js → agent-live-mcp-host.js} +1 -1
- package/dist/agent/agent-live-mcp-host.js.map +1 -0
- package/dist/agent/{agent-mcp-runtime.d.ts → agent-live-mcp-runtime.d.ts} +6 -6
- package/dist/agent/agent-live-mcp-runtime.d.ts.map +1 -0
- package/dist/agent/{agent-mcp-runtime.js → agent-live-mcp-runtime.js} +13 -42
- package/dist/agent/agent-live-mcp-runtime.js.map +1 -0
- package/dist/agent/agent-live-read-runtime.d.ts +72 -0
- package/dist/agent/agent-live-read-runtime.d.ts.map +1 -0
- package/dist/agent/agent-live-read-runtime.js +122 -0
- package/dist/agent/agent-live-read-runtime.js.map +1 -0
- package/dist/agent/agent-model-selection.d.ts +21 -34
- package/dist/agent/agent-model-selection.d.ts.map +1 -1
- package/dist/agent/agent-model-selection.js +61 -78
- package/dist/agent/agent-model-selection.js.map +1 -1
- package/dist/browser/browser-server.d.ts +163 -0
- package/dist/browser/browser-server.d.ts.map +1 -1
- package/dist/browser/browser-server.js +579 -188
- package/dist/browser/browser-server.js.map +1 -1
- package/dist/browser/durable-subscription-bindings.d.ts +5 -0
- package/dist/browser/durable-subscription-bindings.d.ts.map +1 -1
- package/dist/browser/durable-subscription-bindings.js +226 -38
- package/dist/browser/durable-subscription-bindings.js.map +1 -1
- package/dist/browser/options.d.ts +5 -0
- package/dist/browser/options.d.ts.map +1 -1
- package/dist/bus/command-bus.d.ts +17 -18
- package/dist/bus/command-bus.d.ts.map +1 -1
- package/dist/bus/command-bus.js +97 -54
- package/dist/bus/command-bus.js.map +1 -1
- package/dist/bus/command-errors.d.ts +20 -4
- package/dist/bus/command-errors.d.ts.map +1 -1
- package/dist/bus/command-errors.js +47 -7
- package/dist/bus/command-errors.js.map +1 -1
- package/dist/bus/event-bus.d.ts +20 -4
- package/dist/bus/event-bus.d.ts.map +1 -1
- package/dist/bus/event-bus.js +166 -14
- package/dist/bus/event-bus.js.map +1 -1
- package/dist/context/bounded-context.d.ts +169 -98
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +837 -503
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/context/entity-inbox.d.ts +7 -2
- package/dist/context/entity-inbox.d.ts.map +1 -1
- package/dist/context/entity-inbox.js +22 -13
- package/dist/context/entity-inbox.js.map +1 -1
- package/dist/context/local-inbox-handoff.d.ts +34 -34
- package/dist/context/local-inbox-handoff.d.ts.map +1 -1
- package/dist/context/local-inbox-handoff.js +108 -150
- package/dist/context/local-inbox-handoff.js.map +1 -1
- package/dist/context/projection-handoff.d.ts +2 -2
- package/dist/context/projection-handoff.d.ts.map +1 -1
- package/dist/context/projection-handoff.js +10 -8
- package/dist/context/projection-handoff.js.map +1 -1
- package/dist/context/tenant-index.d.ts +36 -31
- package/dist/context/tenant-index.d.ts.map +1 -1
- package/dist/context/tenant-index.js +123 -125
- package/dist/context/tenant-index.js.map +1 -1
- package/dist/context/tenant-unknown-error.d.ts +33 -0
- package/dist/context/tenant-unknown-error.d.ts.map +1 -0
- package/dist/context/tenant-unknown-error.js +75 -0
- package/dist/context/tenant-unknown-error.js.map +1 -0
- package/dist/delivery/agent-delivery-scope.d.ts +66 -0
- package/dist/delivery/agent-delivery-scope.d.ts.map +1 -0
- package/dist/delivery/agent-delivery-scope.js +44 -0
- package/dist/delivery/agent-delivery-scope.js.map +1 -0
- package/dist/delivery/delivery-builder.d.ts +25 -1
- package/dist/delivery/delivery-builder.d.ts.map +1 -1
- package/dist/delivery/delivery-builder.js +89 -0
- package/dist/delivery/delivery-builder.js.map +1 -1
- package/dist/delivery/delivery-monitor.d.ts +1 -1
- package/dist/delivery/delivery-monitor.js +1 -1
- package/dist/delivery/delivery-run-control.d.ts +6 -0
- package/dist/delivery/delivery-run-control.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.js +10 -0
- package/dist/delivery/delivery-run-control.js.map +1 -1
- package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
- package/dist/delivery/delivery-supervisor.js +28 -4
- package/dist/delivery/delivery-supervisor.js.map +1 -1
- package/dist/delivery/delivery-tenant.d.ts +17 -0
- package/dist/delivery/delivery-tenant.d.ts.map +1 -0
- package/dist/delivery/delivery-tenant.js +50 -0
- package/dist/delivery/delivery-tenant.js.map +1 -0
- package/dist/delivery/delivery.d.ts +96 -2
- package/dist/delivery/delivery.d.ts.map +1 -1
- package/dist/delivery/delivery.js +693 -53
- package/dist/delivery/delivery.js.map +1 -1
- package/dist/delivery/inbox-records.d.ts.map +1 -1
- package/dist/delivery/inbox-records.js +9 -16
- package/dist/delivery/inbox-records.js.map +1 -1
- package/dist/delivery/inbox-storage.d.ts +6 -0
- package/dist/delivery/inbox-storage.d.ts.map +1 -1
- package/dist/delivery/inbox-storage.js +43 -6
- package/dist/delivery/inbox-storage.js.map +1 -1
- package/dist/delivery/inbox.d.ts.map +1 -1
- package/dist/delivery/inbox.js +3 -2
- package/dist/delivery/inbox.js.map +1 -1
- package/dist/delivery/reception-observation.d.ts +12 -4
- package/dist/delivery/reception-observation.d.ts.map +1 -1
- package/dist/delivery/reception-observation.js +14 -3
- package/dist/delivery/reception-observation.js.map +1 -1
- package/dist/delivery/sharded-work-registry.d.ts +6 -0
- package/dist/delivery/sharded-work-registry.d.ts.map +1 -1
- package/dist/delivery/sharded-work-registry.js +41 -4
- package/dist/delivery/sharded-work-registry.js.map +1 -1
- package/dist/entity/entity-storage-descriptor.d.ts.map +1 -1
- package/dist/entity/entity-storage-descriptor.js +7 -4
- package/dist/entity/entity-storage-descriptor.js.map +1 -1
- package/dist/entity/entity.d.ts +59 -0
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +60 -0
- package/dist/entity/entity.js.map +1 -1
- package/dist/handler/app-query-handler.d.ts +60 -0
- package/dist/handler/app-query-handler.d.ts.map +1 -0
- package/dist/{bus/saved-dispatcher-binding.js → handler/app-query-handler.js} +8 -12
- package/dist/handler/app-query-handler.js.map +1 -0
- package/dist/handler/generated-registry-discovery.d.ts +6 -0
- package/dist/handler/generated-registry-discovery.d.ts.map +1 -1
- package/dist/handler/generated-registry-discovery.js +71 -2
- package/dist/handler/generated-registry-discovery.js.map +1 -1
- package/dist/handler/handler-decorators.d.ts +8 -29
- package/dist/handler/handler-decorators.d.ts.map +1 -1
- package/dist/handler/handler-decorators.js +33 -210
- package/dist/handler/handler-decorators.js.map +1 -1
- package/dist/handler/spine-metadata-inventory.d.ts +99 -0
- package/dist/handler/spine-metadata-inventory.d.ts.map +1 -0
- package/dist/handler/spine-metadata-inventory.js +162 -0
- package/dist/handler/spine-metadata-inventory.js.map +1 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/integration/external-messages.d.ts.map +1 -1
- package/dist/integration/external-messages.js +9 -15
- package/dist/integration/external-messages.js.map +1 -1
- package/dist/integration/integration-broker.d.ts.map +1 -1
- package/dist/integration/integration-broker.js +112 -6
- package/dist/integration/integration-broker.js.map +1 -1
- package/dist/integration/third-party-context.d.ts.map +1 -1
- package/dist/integration/third-party-context.js +7 -10
- package/dist/integration/third-party-context.js.map +1 -1
- package/dist/repository/primitive-id.js +26 -11
- package/dist/repository/primitive-id.js.map +1 -1
- package/dist/repository/repository.d.ts +75 -60
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +1757 -1818
- package/dist/repository/repository.js.map +1 -1
- package/dist/runtime/runtime.d.ts +13 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +18 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/signal-metadata.d.ts.map +1 -1
- package/dist/runtime/signal-metadata.js +6 -6
- package/dist/runtime/signal-metadata.js.map +1 -1
- package/dist/runtime/signal-publisher.d.ts +0 -6
- package/dist/runtime/signal-publisher.d.ts.map +1 -1
- package/dist/runtime/signal-publisher.js +1 -9
- package/dist/runtime/signal-publisher.js.map +1 -1
- package/dist/runtime/standalone-handler-runtime.d.ts +0 -7
- package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
- package/dist/runtime/standalone-handler-runtime.js +13 -99
- package/dist/runtime/standalone-handler-runtime.js.map +1 -1
- package/dist/server/managed-delivery-gate.d.ts +34 -0
- package/dist/server/managed-delivery-gate.d.ts.map +1 -0
- package/dist/server/managed-delivery-gate.js +70 -0
- package/dist/server/managed-delivery-gate.js.map +1 -0
- package/dist/server/managed-server-application.d.ts +12 -11
- package/dist/server/managed-server-application.d.ts.map +1 -1
- package/dist/server/managed-server-application.js +48 -29
- package/dist/server/managed-server-application.js.map +1 -1
- package/dist/server/node-coordinator.d.ts +18 -5
- package/dist/server/node-coordinator.d.ts.map +1 -1
- package/dist/server/node-coordinator.js +554 -84
- package/dist/server/node-coordinator.js.map +1 -1
- package/dist/server/reserved-spine-rpc-paths.json +1 -0
- package/dist/server/server-environment.d.ts +220 -25
- package/dist/server/server-environment.d.ts.map +1 -1
- package/dist/server/server-environment.js +734 -145
- package/dist/server/server-environment.js.map +1 -1
- package/dist/server/server-log.d.ts +7 -0
- package/dist/server/server-log.d.ts.map +1 -1
- package/dist/server/server-log.js +14 -1
- package/dist/server/server-log.js.map +1 -1
- package/dist/server/server.d.ts +60 -29
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +155 -201
- package/dist/server/server.js.map +1 -1
- package/dist/services/app-query-execution.d.ts +53 -0
- package/dist/services/app-query-execution.d.ts.map +1 -0
- package/dist/services/app-query-execution.js +408 -0
- package/dist/services/app-query-execution.js.map +1 -0
- package/dist/services/query-reader.d.ts +32 -7
- package/dist/services/query-reader.d.ts.map +1 -1
- package/dist/services/query-reader.js +22 -2
- package/dist/services/query-reader.js.map +1 -1
- package/dist/services/read-request-status.d.ts +65 -0
- package/dist/services/read-request-status.d.ts.map +1 -0
- package/dist/services/read-request-status.js +151 -0
- package/dist/services/read-request-status.js.map +1 -0
- package/dist/services/spine-services.d.ts +37 -8
- package/dist/services/spine-services.d.ts.map +1 -1
- package/dist/services/spine-services.js +1103 -470
- package/dist/services/spine-services.js.map +1 -1
- package/dist/services/trusted-reader-ingress.d.ts +92 -0
- package/dist/services/trusted-reader-ingress.d.ts.map +1 -0
- package/dist/services/trusted-reader-ingress.js +89 -0
- package/dist/services/trusted-reader-ingress.js.map +1 -0
- package/dist/spi/handler-registry.d.ts +2 -0
- package/dist/spi/handler-registry.d.ts.map +1 -1
- package/dist/spi/handler-registry.js +1 -1
- package/dist/spi/handler-registry.js.map +1 -1
- package/dist/stand/event-origin-filter.js +3 -3
- package/dist/stand/event-origin-filter.js.map +1 -1
- package/dist/stand/read-side-filter-engine.d.ts +46 -0
- package/dist/stand/read-side-filter-engine.d.ts.map +1 -0
- package/dist/stand/read-side-filter-engine.js +356 -0
- package/dist/stand/read-side-filter-engine.js.map +1 -0
- package/dist/stand/read-side-filter.d.ts +247 -0
- package/dist/stand/read-side-filter.d.ts.map +1 -0
- package/dist/stand/read-side-filter.js +39 -0
- package/dist/stand/read-side-filter.js.map +1 -0
- package/dist/stand/read-side-message.d.ts +66 -0
- package/dist/stand/read-side-message.d.ts.map +1 -0
- package/dist/stand/read-side-message.js +167 -0
- package/dist/stand/read-side-message.js.map +1 -0
- package/dist/stand/stand-direct-delivery.d.ts +161 -0
- package/dist/stand/stand-direct-delivery.d.ts.map +1 -0
- package/dist/stand/stand-direct-delivery.js +210 -0
- package/dist/stand/stand-direct-delivery.js.map +1 -0
- package/dist/stand/stand.d.ts +94 -42
- package/dist/stand/stand.d.ts.map +1 -1
- package/dist/stand/stand.js +460 -60
- package/dist/stand/stand.js.map +1 -1
- package/dist/stand/subscription-observer.d.ts.map +1 -1
- package/dist/stand/subscription-observer.js +157 -40
- package/dist/stand/subscription-observer.js.map +1 -1
- package/dist/stand/subscription-read-filters.d.ts +40 -0
- package/dist/stand/subscription-read-filters.d.ts.map +1 -0
- package/dist/stand/subscription-read-filters.js +91 -0
- package/dist/stand/subscription-read-filters.js.map +1 -0
- package/dist/stand/subscription-reader-binding.d.ts +20 -0
- package/dist/stand/subscription-reader-binding.d.ts.map +1 -0
- package/dist/stand/subscription-reader-binding.js +56 -0
- package/dist/stand/subscription-reader-binding.js.map +1 -0
- package/dist/stand/subscription-records.d.ts +30 -3
- package/dist/stand/subscription-records.d.ts.map +1 -1
- package/dist/stand/subscription-records.js +61 -16
- package/dist/stand/subscription-records.js.map +1 -1
- package/dist/stand/subscription-registry.d.ts +54 -15
- package/dist/stand/subscription-registry.d.ts.map +1 -1
- package/dist/stand/subscription-registry.js +164 -41
- package/dist/stand/subscription-registry.js.map +1 -1
- package/dist/stand/subscription-runtime.d.ts +12 -5
- package/dist/stand/subscription-runtime.d.ts.map +1 -1
- package/dist/stand/subscription-runtime.js +183 -34
- package/dist/stand/subscription-runtime.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +4 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/dist/agent/agent-admission.d.ts +0 -80
- package/dist/agent/agent-admission.d.ts.map +0 -1
- package/dist/agent/agent-admission.js +0 -127
- package/dist/agent/agent-admission.js.map +0 -1
- package/dist/agent/agent-ai-runtime.d.ts +0 -76
- package/dist/agent/agent-ai-runtime.d.ts.map +0 -1
- package/dist/agent/agent-ai-runtime.js +0 -1269
- package/dist/agent/agent-ai-runtime.js.map +0 -1
- package/dist/agent/agent-execution-fault.d.ts +0 -18
- package/dist/agent/agent-execution-fault.d.ts.map +0 -1
- package/dist/agent/agent-execution-fault.js.map +0 -1
- package/dist/agent/agent-execution-session.d.ts +0 -103
- package/dist/agent/agent-execution-session.d.ts.map +0 -1
- package/dist/agent/agent-execution-session.js +0 -238
- package/dist/agent/agent-execution-session.js.map +0 -1
- package/dist/agent/agent-interaction-audit.d.ts +0 -58
- package/dist/agent/agent-interaction-audit.d.ts.map +0 -1
- package/dist/agent/agent-interaction-audit.js +0 -114
- package/dist/agent/agent-interaction-audit.js.map +0 -1
- package/dist/agent/agent-interaction-events.d.ts +0 -40
- package/dist/agent/agent-interaction-events.d.ts.map +0 -1
- package/dist/agent/agent-interaction-events.js +0 -129
- package/dist/agent/agent-interaction-events.js.map +0 -1
- package/dist/agent/agent-mcp-budget.d.ts +0 -125
- package/dist/agent/agent-mcp-budget.d.ts.map +0 -1
- package/dist/agent/agent-mcp-budget.js +0 -566
- package/dist/agent/agent-mcp-budget.js.map +0 -1
- package/dist/agent/agent-mcp-host.d.ts +0 -125
- package/dist/agent/agent-mcp-host.d.ts.map +0 -1
- package/dist/agent/agent-mcp-host.js.map +0 -1
- package/dist/agent/agent-mcp-runtime.d.ts.map +0 -1
- package/dist/agent/agent-mcp-runtime.js.map +0 -1
- package/dist/agent/agent-read-runtime.d.ts +0 -70
- package/dist/agent/agent-read-runtime.d.ts.map +0 -1
- package/dist/agent/agent-read-runtime.js +0 -320
- package/dist/agent/agent-read-runtime.js.map +0 -1
- package/dist/agent/agent-revisions.d.ts +0 -35
- package/dist/agent/agent-revisions.d.ts.map +0 -1
- package/dist/agent/agent-revisions.js +0 -133
- package/dist/agent/agent-revisions.js.map +0 -1
- package/dist/agent/agent-scheduler.d.ts +0 -99
- package/dist/agent/agent-scheduler.d.ts.map +0 -1
- package/dist/agent/agent-scheduler.js +0 -398
- package/dist/agent/agent-scheduler.js.map +0 -1
- package/dist/bus/saved-dispatcher-binding.d.ts +0 -53
- package/dist/bus/saved-dispatcher-binding.d.ts.map +0 -1
- package/dist/bus/saved-dispatcher-binding.js.map +0 -1
- package/dist/delivery/delivery-run-coordinator.d.ts +0 -218
- package/dist/delivery/delivery-run-coordinator.d.ts.map +0 -1
- package/dist/delivery/delivery-run-coordinator.js +0 -609
- package/dist/delivery/delivery-run-coordinator.js.map +0 -1
- package/dist/delivery/parked-delivery-obligations.d.ts +0 -182
- package/dist/delivery/parked-delivery-obligations.d.ts.map +0 -1
- package/dist/delivery/parked-delivery-obligations.js +0 -390
- package/dist/delivery/parked-delivery-obligations.js.map +0 -1
- package/dist/server/environment-attachment.d.ts +0 -356
- package/dist/server/environment-attachment.d.ts.map +0 -1
- package/dist/server/environment-attachment.js +0 -2062
- package/dist/server/environment-attachment.js.map +0 -1
- package/dist/server/environment-delivery-records.d.ts +0 -77
- package/dist/server/environment-delivery-records.d.ts.map +0 -1
- package/dist/server/environment-delivery-records.js +0 -282
- package/dist/server/environment-delivery-records.js.map +0 -1
- package/dist/server/environment-delivery-worker.d.ts +0 -161
- package/dist/server/environment-delivery-worker.d.ts.map +0 -1
- package/dist/server/environment-delivery-worker.js +0 -973
- package/dist/server/environment-delivery-worker.js.map +0 -1
|
@@ -12,14 +12,20 @@
|
|
|
12
12
|
* the License.
|
|
13
13
|
*/
|
|
14
14
|
import { InMemoryStorageFactory } from "@spine-event-engine/storage";
|
|
15
|
+
import { TenantBoundary } from "@spine-event-engine/storage/provider";
|
|
15
16
|
import { LogLayer, StructuredTransport } from "loglayer";
|
|
16
17
|
import { InMemoryTransportFactory } from "@spine-event-engine/transport";
|
|
17
18
|
import { spineCoreRegistry } from "@spine-event-engine/core";
|
|
18
|
-
import { RetryableCloseGroup } from "./retryable-close.js";
|
|
19
|
-
import {
|
|
19
|
+
import { CloseErrors, RetryableCloseGroup } from "./retryable-close.js";
|
|
20
|
+
import { Delivery as CoreDelivery } from "../delivery/delivery.js";
|
|
21
|
+
import { deliveryControls, deliveryStrategyAccess } from "../delivery/delivery-builder.js";
|
|
22
|
+
import { DeliverySupervisor, deliverySupervisorAccess } from "../delivery/delivery-supervisor.js";
|
|
23
|
+
import { deliveryTenant } from "../delivery/delivery-tenant.js";
|
|
24
|
+
import { emitServerInfo, emitServerWarning } from "./server-log.js";
|
|
25
|
+
import { managedDeliveryGate } from "./managed-delivery-gate.js";
|
|
20
26
|
import { boundedContextAccess } from "../context/bounded-context.js";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
27
|
+
import { TenantIndexes } from "../context/tenant-index.js";
|
|
28
|
+
import { TenantUnknownError } from "../context/tenant-unknown-error.js";
|
|
23
29
|
import { Environment, EnvironmentTests, EnvironmentType } from "./environment.js";
|
|
24
30
|
const configuredSettings = new Map();
|
|
25
31
|
let resolvedEnvironment;
|
|
@@ -41,6 +47,18 @@ export class ServerEnvironment {
|
|
|
41
47
|
* Storage facility selected for server assembly, including server-added context builders.
|
|
42
48
|
*/
|
|
43
49
|
storageFactory;
|
|
50
|
+
/**
|
|
51
|
+
* Waiting updates per subscription beyond one active update.
|
|
52
|
+
*/
|
|
53
|
+
subscriptionQueueCapacity;
|
|
54
|
+
/**
|
|
55
|
+
* Live default tenant membership index.
|
|
56
|
+
*/
|
|
57
|
+
tenantIndex;
|
|
58
|
+
/**
|
|
59
|
+
* Default AI registry selected for Bounded Context assembly, when configured.
|
|
60
|
+
*/
|
|
61
|
+
ai;
|
|
44
62
|
/**
|
|
45
63
|
* Message-channel factory selected for private bounded-context integration.
|
|
46
64
|
*
|
|
@@ -54,45 +72,92 @@ export class ServerEnvironment {
|
|
|
54
72
|
*/
|
|
55
73
|
typeRegistry;
|
|
56
74
|
/**
|
|
57
|
-
* Optional closeable delivery
|
|
75
|
+
* Optional closeable remote delivery facility selected for this environment.
|
|
58
76
|
*/
|
|
59
|
-
|
|
77
|
+
#remoteDelivery;
|
|
78
|
+
/**
|
|
79
|
+
* Returns the actual shared Delivery after explicit environment setup.
|
|
80
|
+
* @returns The one public Delivery facade for this environment.
|
|
81
|
+
*/
|
|
82
|
+
get delivery() {
|
|
83
|
+
if (this.#publicDelivery === undefined)
|
|
84
|
+
throw new Error("ServerEnvironment.completeSetup() must finish before Delivery use.");
|
|
85
|
+
return this.#publicDelivery;
|
|
86
|
+
}
|
|
60
87
|
/**
|
|
61
88
|
* Optional tracing factory selected for this environment.
|
|
62
89
|
*/
|
|
63
90
|
tracerFactory;
|
|
64
91
|
#ownedCloseables;
|
|
65
92
|
#closeGroup;
|
|
93
|
+
#deliveryCloseGroup;
|
|
94
|
+
#deliveryStrategy;
|
|
95
|
+
#delivery;
|
|
96
|
+
#publicDelivery;
|
|
97
|
+
#supervisor;
|
|
98
|
+
#supervisorStart;
|
|
66
99
|
#close;
|
|
67
100
|
#deliveryOpen;
|
|
68
101
|
#deliveryOpened = false;
|
|
102
|
+
#closing = false;
|
|
103
|
+
#fatal;
|
|
104
|
+
/**
|
|
105
|
+
* Initializes resolved environment facilities.
|
|
106
|
+
*
|
|
107
|
+
* @param environment Selected process environment.
|
|
108
|
+
* @param settings Resolved facilities and settings.
|
|
109
|
+
*/
|
|
69
110
|
constructor(environment, settings) {
|
|
70
111
|
this.environment = environment;
|
|
71
112
|
this.nodeId = crypto.randomUUID();
|
|
72
113
|
this.storageFactory = settings.storageFactory;
|
|
114
|
+
this.subscriptionQueueCapacity = settings.subscriptionQueueCapacity;
|
|
115
|
+
this.tenantIndex = settings.tenantIndex ?? TenantIndexes.fromFactory(settings.storageFactory);
|
|
116
|
+
this.ai = settings.ai;
|
|
73
117
|
this.integrationChannelFactory = settings.integrationChannelFactory;
|
|
74
118
|
this.typeRegistry = settings.typeRegistry;
|
|
75
|
-
this
|
|
119
|
+
this.#remoteDelivery = settings.delivery;
|
|
120
|
+
this.#deliveryStrategy = settings.deliveryStrategy;
|
|
76
121
|
this.tracerFactory = settings.tracerFactory;
|
|
77
|
-
|
|
78
|
-
this.#
|
|
79
|
-
|
|
122
|
+
this.#registerRuntimeHooks(settings.logger);
|
|
123
|
+
this.#deliveryCloseGroup = new RetryableCloseGroup([
|
|
124
|
+
{ close: () => this.#supervisor?.close() },
|
|
125
|
+
{ close: () => this.#delivery?.close() },
|
|
126
|
+
this.#remoteDelivery,
|
|
127
|
+
], "Environment Delivery close failed.");
|
|
128
|
+
this.#ownedCloseables = ServerEnvironmentValues.facilitiesToClose(settings, this.#deliveryCloseGroup);
|
|
80
129
|
this.#closeGroup = new RetryableCloseGroup(this.#ownedCloseables, "ServerEnvironment close failed.");
|
|
81
|
-
environmentAttachments.set(this, new EnvironmentAttachments({
|
|
82
|
-
logger: ServerEnvironmentValues.loggerFor(this),
|
|
83
|
-
createWorker: () => {
|
|
84
|
-
const ports = ServerEnvironmentValues.ports(this.delivery);
|
|
85
|
-
return new EnvironmentDeliveryWorker({
|
|
86
|
-
...(ports === undefined ? {} : { ports }),
|
|
87
|
-
nodeId: this.nodeId,
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
deliveryPorts: () => ServerEnvironmentValues.ports(this.delivery),
|
|
91
|
-
}));
|
|
92
|
-
deliveryOpeners.set(this, () => this.#openDelivery());
|
|
93
|
-
testAttachmentsInstallable.add(this);
|
|
94
130
|
Object.freeze(this);
|
|
95
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Registers package-local callbacks for this environment's runtime.
|
|
134
|
+
* @param logger Receives diagnostics from these callbacks.
|
|
135
|
+
*/
|
|
136
|
+
#registerRuntimeHooks(logger) {
|
|
137
|
+
environmentLoggers.set(this, logger);
|
|
138
|
+
environmentContexts.set(this, new EnvironmentContextRegistrations());
|
|
139
|
+
startupControls.set(this, {
|
|
140
|
+
fail: (cause) => {
|
|
141
|
+
this.#failStartup(cause);
|
|
142
|
+
},
|
|
143
|
+
awaitFailure: () => this.#awaitStartupFailure(),
|
|
144
|
+
available: () => {
|
|
145
|
+
if (this.#closing)
|
|
146
|
+
throw new Error("ServerEnvironment is closed.");
|
|
147
|
+
},
|
|
148
|
+
failed: () => this.#fatal !== undefined,
|
|
149
|
+
recordCleanup: (error) => {
|
|
150
|
+
if (this.#fatal !== undefined)
|
|
151
|
+
CloseErrors.collect(error, this.#fatal.cleanupErrors);
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
warnedVolatileRegistries.set(this, new WeakSet());
|
|
155
|
+
supervisorStarters.set(this, () => this.#startSupervisor());
|
|
156
|
+
deliveryNotifiers.set(this, (shard) => {
|
|
157
|
+
this.#notifyDelivery(shard);
|
|
158
|
+
});
|
|
159
|
+
deliveryIdlers.set(this, () => this.#whenDeliveryIdle());
|
|
160
|
+
}
|
|
96
161
|
/**
|
|
97
162
|
* Sets facilities for an environment type before first resolution.
|
|
98
163
|
*
|
|
@@ -101,6 +166,9 @@ export class ServerEnvironment {
|
|
|
101
166
|
*/
|
|
102
167
|
static when(type) {
|
|
103
168
|
return Object.freeze({
|
|
169
|
+
/**
|
|
170
|
+
* Stores settings for this environment type unless reset or singleton resolution has started.
|
|
171
|
+
*/
|
|
104
172
|
use(settings) {
|
|
105
173
|
if (resetInProgress !== undefined) {
|
|
106
174
|
throw new Error("ServerEnvironment reset is in progress.");
|
|
@@ -123,6 +191,9 @@ export class ServerEnvironment {
|
|
|
123
191
|
}
|
|
124
192
|
return (resolvedEnvironment ??= this.#resolve());
|
|
125
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Resolves the current Environment and its configured or default facilities into the process-wide ServerEnvironment.
|
|
196
|
+
*/
|
|
126
197
|
static #resolve() {
|
|
127
198
|
const environment = Environment.instance();
|
|
128
199
|
const configured = configuredSettings.get(environment.type);
|
|
@@ -131,19 +202,165 @@ export class ServerEnvironment {
|
|
|
131
202
|
return new ServerEnvironment(environment, facilities);
|
|
132
203
|
}
|
|
133
204
|
/**
|
|
134
|
-
*
|
|
205
|
+
* Checks shared storage and initializes transport and Delivery before context startup.
|
|
135
206
|
*
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
207
|
+
* @returns The coalesced setup attempt for this environment lifetime.
|
|
208
|
+
*/
|
|
209
|
+
completeSetup() {
|
|
210
|
+
if (this.#closing)
|
|
211
|
+
return Promise.reject(new Error("ServerEnvironment is closed."));
|
|
212
|
+
const current = environmentSetups.get(this);
|
|
213
|
+
if (current !== undefined)
|
|
214
|
+
return current;
|
|
215
|
+
const started = this.#completeSetup();
|
|
216
|
+
environmentSetups.set(this, started);
|
|
217
|
+
return started;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Creates declared structures for the completed open contexts in this environment.
|
|
221
|
+
* Explicit IDs select matching multitenant contexts through their effective indexes.
|
|
222
|
+
* Database-backed providers require an existing database; this method does not
|
|
223
|
+
* provision one or register tenants.
|
|
224
|
+
* @param tenantIds Optional complete tenant identities; absence includes single-tenant
|
|
225
|
+
* contexts and pages current multitenant indexes.
|
|
226
|
+
* @returns Completion after participating contexts are prepared.
|
|
227
|
+
*/
|
|
228
|
+
createStorageStructures(...tenantIds) {
|
|
229
|
+
return this.#prepareContexts("create", tenantIds);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Checks existing structures without authorizing creation.
|
|
233
|
+
* Explicit IDs select matching multitenant contexts through their effective indexes.
|
|
234
|
+
* The operation does not provision databases or register tenants.
|
|
235
|
+
* @param tenantIds Optional complete tenant identities; absence includes single-tenant
|
|
236
|
+
* contexts and pages current multitenant indexes.
|
|
237
|
+
* @returns Completion after participating contexts pass read-only checks.
|
|
238
|
+
*/
|
|
239
|
+
checkStructureCompatibility(...tenantIds) {
|
|
240
|
+
return this.#prepareContexts("check", tenantIds);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Prevalidates selected tenant membership before starting provider work.
|
|
244
|
+
* @param contexts Captured completed context references.
|
|
245
|
+
* @param tenantIds Explicit complete tenant identities.
|
|
246
|
+
* @returns Participating contexts and their selected tenants.
|
|
247
|
+
*/
|
|
248
|
+
async #selectedContexts(contexts, tenantIds) {
|
|
249
|
+
const selected = new Map();
|
|
250
|
+
const boundaries = new Map();
|
|
251
|
+
for (const id of tenantIds) {
|
|
252
|
+
const boundary = TenantBoundary.from(id);
|
|
253
|
+
boundaries.set(boundary.key, boundary);
|
|
254
|
+
}
|
|
255
|
+
for (const boundary of boundaries.values()) {
|
|
256
|
+
let found = false;
|
|
257
|
+
for (const context of contexts) {
|
|
258
|
+
serverEnvironmentAccess.requireAvailable(this);
|
|
259
|
+
if (!context.isMultitenant)
|
|
260
|
+
continue;
|
|
261
|
+
const present = await context.tenantIndex.contains(boundary.tenantId);
|
|
262
|
+
serverEnvironmentAccess.requireAvailable(this);
|
|
263
|
+
if (!present)
|
|
264
|
+
continue;
|
|
265
|
+
const ids = selected.get(context) ?? [];
|
|
266
|
+
ids.push(boundary.tenantId);
|
|
267
|
+
selected.set(context, ids);
|
|
268
|
+
found = true;
|
|
269
|
+
}
|
|
270
|
+
if (!found)
|
|
271
|
+
throw new TenantUnknownError(boundary.tenantId, "ServerEnvironment");
|
|
272
|
+
}
|
|
273
|
+
return selected;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Prepares captured contexts after complete explicit-ID validation.
|
|
277
|
+
* @param mode Creation or read-only check.
|
|
278
|
+
* @param tenantIds Optional complete tenant identities.
|
|
279
|
+
* @returns Completion after every participating context settles.
|
|
280
|
+
*/
|
|
281
|
+
async #prepareContexts(mode, tenantIds) {
|
|
282
|
+
serverEnvironmentAccess.requireAvailable(this);
|
|
283
|
+
const captured = tenantIds.map((id) => TenantBoundary.from(id).tenantId);
|
|
284
|
+
const contexts = serverEnvironmentAccess
|
|
285
|
+
.openContexts(this)
|
|
286
|
+
.filter((context) => !boundedContextAccess.isClosing(context));
|
|
287
|
+
if (contexts.length === 0)
|
|
288
|
+
throw new Error("ServerEnvironment has no completed Bounded Context to prepare.");
|
|
289
|
+
const selection = Promise.withResolvers();
|
|
290
|
+
const admitted = contexts.map((context) => boundedContextAccess.admitServiceRegistryOperation(context, async () => {
|
|
291
|
+
const selected = await selection.promise;
|
|
292
|
+
const ids = selected?.get(context);
|
|
293
|
+
if (selected !== undefined && ids === undefined)
|
|
294
|
+
return;
|
|
295
|
+
await boundedContextAccess.prepareExplicit(context, mode, ids ?? []);
|
|
296
|
+
}));
|
|
297
|
+
if (captured.length === 0)
|
|
298
|
+
selection.resolve(undefined);
|
|
299
|
+
else
|
|
300
|
+
void this.#selectedContexts(contexts, captured).then(selection.resolve, selection.reject);
|
|
301
|
+
const results = await Promise.allSettled(admitted);
|
|
302
|
+
if (serverEnvironmentAccess.hasStartupFailure(this))
|
|
303
|
+
return serverEnvironmentAccess.awaitStartupFailure(this);
|
|
304
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
305
|
+
if (failure?.status === "rejected")
|
|
306
|
+
throw failure.reason;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Opens configured facilities, validates shared storage, and initializes shared Delivery before context startup.
|
|
310
|
+
*/
|
|
311
|
+
async #completeSetup() {
|
|
312
|
+
try {
|
|
313
|
+
if (typeof this.integrationChannelFactory.initialize !== "function")
|
|
314
|
+
throw new TypeError("TransportFactory.initialize is required.");
|
|
315
|
+
await this.storageFactory.checkConnection();
|
|
316
|
+
emitServerInfo(ServerEnvironmentValues.loggerFor(this), "Environment storage connection checked.", { operation: "server.setup_storage" });
|
|
317
|
+
await this.integrationChannelFactory.initialize();
|
|
318
|
+
emitServerInfo(ServerEnvironmentValues.loggerFor(this), "Environment transport initialized.", { operation: "server.setup_transport" });
|
|
319
|
+
await this.#openDelivery();
|
|
320
|
+
if (this.#closing)
|
|
321
|
+
throw new Error("ServerEnvironment closed during setup.");
|
|
322
|
+
emitServerInfo(ServerEnvironmentValues.loggerFor(this), "Environment Delivery initialized.", {
|
|
323
|
+
operation: "server.setup_delivery",
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
this.#closing = true;
|
|
328
|
+
const cleanup = await Promise.allSettled([this.#closeGroup.close()]);
|
|
329
|
+
const failures = cleanup.flatMap((result) => {
|
|
330
|
+
if (result.status !== "rejected")
|
|
331
|
+
return [];
|
|
332
|
+
return result.reason instanceof AggregateError
|
|
333
|
+
? result.reason.errors
|
|
334
|
+
: [result.reason];
|
|
335
|
+
});
|
|
336
|
+
if (failures.length)
|
|
337
|
+
throw new AggregateError([error, ...failures], "Environment setup failed.");
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Closes this environment after all Bounded Contexts close.
|
|
139
343
|
*
|
|
140
|
-
*
|
|
344
|
+
* A healthy environment with active contexts rejects without teardown. After
|
|
345
|
+
* required startup failure, this joins automatic cleanup and rejects with the
|
|
346
|
+
* original cause and any cleanup failures. Successful closure prevents reuse;
|
|
347
|
+
* failed facility closes during an ordinary close remain retryable.
|
|
141
348
|
*
|
|
349
|
+
* @returns Completion after facilities close or a rejection reporting failures.
|
|
142
350
|
*/
|
|
143
351
|
close() {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
352
|
+
if (this.#fatal !== undefined)
|
|
353
|
+
return this.#awaitStartupFailure();
|
|
354
|
+
if (EnvironmentContextRegistrations.forEnvironment(this).active)
|
|
355
|
+
return Promise.reject(new Error("Cannot close ServerEnvironment with active Bounded Contexts."));
|
|
356
|
+
this.#closing = true;
|
|
357
|
+
this.#delivery?.beginClose();
|
|
358
|
+
this.#close ??= Promise.resolve()
|
|
359
|
+
.then(async () => {
|
|
360
|
+
const setup = environmentSetups.get(this);
|
|
361
|
+
if (setup !== undefined)
|
|
362
|
+
await Promise.allSettled([setup]);
|
|
363
|
+
})
|
|
147
364
|
.then(() => this.#closeGroup.close())
|
|
148
365
|
.catch((error) => {
|
|
149
366
|
this.#close = undefined;
|
|
@@ -151,16 +368,86 @@ export class ServerEnvironment {
|
|
|
151
368
|
});
|
|
152
369
|
return this.#close;
|
|
153
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Fences a failed required startup phase and starts one automatic cleanup.
|
|
373
|
+
* @param cause Original required-phase failure.
|
|
374
|
+
*/
|
|
375
|
+
#failStartup(cause) {
|
|
376
|
+
if (this.#fatal !== undefined) {
|
|
377
|
+
this.#fatal.originals.push(cause);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
this.#closing = true;
|
|
381
|
+
const contexts = EnvironmentContextRegistrations.forEnvironment(this);
|
|
382
|
+
const cleanupErrors = [];
|
|
383
|
+
const cleanup = Promise.resolve().then(() => this.#cleanupStartup(contexts, cleanupErrors));
|
|
384
|
+
this.#fatal = { originals: [cause], cleanupErrors, cleanup };
|
|
385
|
+
for (const context of contexts.allContexts()) {
|
|
386
|
+
try {
|
|
387
|
+
boundedContextAccess.beginClose(context);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
CloseErrors.collect(error, cleanupErrors);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
this.#delivery?.beginStartupDrain();
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Waits for local rollbacks, then closes contexts and shared facilities.
|
|
397
|
+
* @param contexts Context registrations for this environment.
|
|
398
|
+
* @param cleanupErrors Mutable cleanup failures.
|
|
399
|
+
* @returns Completion after every cleanup attempt.
|
|
400
|
+
*/
|
|
401
|
+
async #cleanupStartup(contexts, cleanupErrors) {
|
|
402
|
+
const started = new Set(contexts.openContexts());
|
|
403
|
+
const observe = (context) => Promise.resolve()
|
|
404
|
+
.then(() => context.close())
|
|
405
|
+
.then(() => ({ status: "fulfilled", value: undefined }), (reason) => ({ status: "rejected", reason }));
|
|
406
|
+
const completed = [...started].map(observe);
|
|
407
|
+
await contexts.whenBuildsIdle();
|
|
408
|
+
const remaining = contexts
|
|
409
|
+
.allContexts()
|
|
410
|
+
.filter((context) => !started.has(context))
|
|
411
|
+
.map(observe);
|
|
412
|
+
for (const result of await Promise.all([...completed, ...remaining]))
|
|
413
|
+
if (result.status === "rejected")
|
|
414
|
+
CloseErrors.collect(result.reason, cleanupErrors);
|
|
415
|
+
this.#delivery?.beginClose();
|
|
416
|
+
try {
|
|
417
|
+
await this.#closeGroup.close();
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
CloseErrors.collect(error, cleanupErrors);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Reports all original and cleanup errors after automatic cleanup settles.
|
|
425
|
+
* @returns Rejection preserving the original failure when it is the only error.
|
|
426
|
+
*/
|
|
427
|
+
async #awaitStartupFailure() {
|
|
428
|
+
const fatal = this.#fatal;
|
|
429
|
+
if (fatal === undefined)
|
|
430
|
+
throw new Error("No startup failure was recorded.");
|
|
431
|
+
await fatal.cleanup;
|
|
432
|
+
const failures = [...fatal.originals, ...fatal.cleanupErrors];
|
|
433
|
+
if (failures.length === 1)
|
|
434
|
+
throw failures[0];
|
|
435
|
+
throw new AggregateError(failures, "Required environment initialization failed.");
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Opens the configured delivery facility once and records successful opening for later cleanup.
|
|
439
|
+
*/
|
|
154
440
|
#openDelivery() {
|
|
155
441
|
if (this.#deliveryOpened)
|
|
156
442
|
return Promise.resolve();
|
|
157
443
|
const opening = (this.#deliveryOpen ??= Promise.resolve()
|
|
158
|
-
.then(() => {
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
444
|
+
.then(async () => {
|
|
445
|
+
const remote = ServerEnvironmentValues.openableDelivery(this.#remoteDelivery);
|
|
446
|
+
if (remote !== undefined)
|
|
447
|
+
await remote.open();
|
|
448
|
+
if (this.#closing)
|
|
449
|
+
throw new Error("ServerEnvironment closed during Delivery setup.");
|
|
450
|
+
this.#constructDelivery(ServerEnvironmentValues.ports(this.#remoteDelivery));
|
|
164
451
|
})
|
|
165
452
|
.then(() => {
|
|
166
453
|
this.#deliveryOpened = true;
|
|
@@ -172,12 +459,98 @@ export class ServerEnvironment {
|
|
|
172
459
|
});
|
|
173
460
|
return opening;
|
|
174
461
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Constructs the one environment Delivery after configured ports open.
|
|
464
|
+
* @param ports Open remote ports when configured.
|
|
465
|
+
*/
|
|
466
|
+
#constructDelivery(ports) {
|
|
467
|
+
const delivery = new CoreDelivery({
|
|
468
|
+
context: { name: "__System_Delivery__", multitenant: false },
|
|
469
|
+
storageFactory: this.storageFactory,
|
|
470
|
+
node: this.nodeId,
|
|
471
|
+
...(ports?.source === undefined ? { logger: ServerEnvironmentValues.loggerFor(this) } : {}),
|
|
472
|
+
...(this.#deliveryStrategy === undefined
|
|
473
|
+
? {}
|
|
474
|
+
: { strategy: deliveryStrategyAccess.snapshot(this.#deliveryStrategy) }),
|
|
475
|
+
...(ports ?? {}),
|
|
476
|
+
});
|
|
477
|
+
delivery.setReplay((message) => this.#replayMessage(message), (message) => this.#acceptsMessage(message));
|
|
478
|
+
this.#delivery = delivery;
|
|
479
|
+
environmentDeliveryCores.set(this, delivery);
|
|
480
|
+
this.#publicDelivery = deliveryControls.supervised(delivery);
|
|
481
|
+
if (ports?.source !== undefined)
|
|
482
|
+
this.#installSupervisor(this.#publicDelivery, ports.source);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Checks whether a Delivery inbox message targets an Entity or Projection currently served by this environment.
|
|
486
|
+
*/
|
|
487
|
+
#acceptsMessage(message) {
|
|
488
|
+
return (EnvironmentContextRegistrations.forEnvironment(this).recipient(message.inboxId.targetTypeUrl) !== undefined);
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Creates the Delivery supervisor and connects inbox, work registry, and shard delivery notifications.
|
|
492
|
+
*/
|
|
493
|
+
#installSupervisor(delivery, source) {
|
|
494
|
+
const supervisor = new DeliverySupervisor({
|
|
495
|
+
source,
|
|
496
|
+
delivery,
|
|
497
|
+
onMessage: (message) => this.#replayMessage(message),
|
|
498
|
+
});
|
|
499
|
+
deliverySupervisorAccess.installAdmission(supervisor, (message) => this.#acceptsMessage(message));
|
|
500
|
+
deliverySupervisorAccess.installLogger(supervisor, ServerEnvironmentValues.loggerFor(this));
|
|
501
|
+
this.#supervisor = supervisor;
|
|
502
|
+
remoteSupervisedEnvironments.add(this);
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Starts the configured Delivery supervisor once and records fatal startup failures for environment cleanup.
|
|
506
|
+
*/
|
|
507
|
+
#startSupervisor() {
|
|
508
|
+
const supervisor = this.#supervisor;
|
|
509
|
+
return supervisor === undefined
|
|
510
|
+
? Promise.resolve()
|
|
511
|
+
: managedDeliveryGate.start(() => (this.#supervisorStart ??= supervisor.start()));
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Notifies the supervisor that work for a shard may now be available.
|
|
515
|
+
*/
|
|
516
|
+
#notifyDelivery(shard) {
|
|
517
|
+
if (this.#supervisor === undefined) {
|
|
518
|
+
this.#delivery?.wake(shard);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
this.#supervisor.notify(shard);
|
|
179
523
|
}
|
|
180
|
-
|
|
524
|
+
catch {
|
|
525
|
+
emitServerWarning(ServerEnvironmentValues.loggerFor(this), "Delivery notification failed.", {
|
|
526
|
+
operation: "delivery.notify",
|
|
527
|
+
reasonCode: "failed",
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Waits until the environment’s supervised Delivery has no active work.
|
|
533
|
+
*/
|
|
534
|
+
async #whenDeliveryIdle() {
|
|
535
|
+
const settled = await Promise.allSettled([
|
|
536
|
+
this.#supervisor?.whenIdle(),
|
|
537
|
+
this.#delivery?.whenIdle(),
|
|
538
|
+
]);
|
|
539
|
+
const failures = settled.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
540
|
+
if (failures.length === 1)
|
|
541
|
+
throw failures[0];
|
|
542
|
+
if (failures.length)
|
|
543
|
+
throw new AggregateError(failures, "Environment Delivery idle wait failed.");
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Replays a persisted Delivery inbox message through the matching context recipient and signals
|
|
547
|
+
* completion or failure.
|
|
548
|
+
*/
|
|
549
|
+
async #replayMessage(message) {
|
|
550
|
+
const context = EnvironmentContextRegistrations.forEnvironment(this).recipient(message.inboxId.targetTypeUrl);
|
|
551
|
+
if (context === undefined)
|
|
552
|
+
throw new Error("No open Bounded Context serves the Inbox target.");
|
|
553
|
+
await boundedContextAccess.trackReplay(context, () => boundedContextAccess.delivery(context).replay(message, deliveryTenant(message)));
|
|
181
554
|
}
|
|
182
555
|
}
|
|
183
556
|
/**
|
|
@@ -196,8 +569,19 @@ export const ServerEnvironmentLifecycle = Object.freeze({
|
|
|
196
569
|
return current;
|
|
197
570
|
}
|
|
198
571
|
const resolved = resolvedEnvironment;
|
|
572
|
+
if (resolved !== undefined && EnvironmentContextRegistrations.forEnvironment(resolved).active) {
|
|
573
|
+
return Promise.reject(new Error("Cannot reset ServerEnvironment with active Bounded Contexts."));
|
|
574
|
+
}
|
|
199
575
|
const reset = Promise.resolve()
|
|
200
|
-
.then(() =>
|
|
576
|
+
.then(() => {
|
|
577
|
+
if (resolved !== undefined && EnvironmentContextRegistrations.forEnvironment(resolved).active) {
|
|
578
|
+
throw new Error("Cannot reset ServerEnvironment with active Bounded Contexts.");
|
|
579
|
+
}
|
|
580
|
+
if (resolved !== undefined && startupControls.get(resolved)?.failed())
|
|
581
|
+
// spine-log-boundary: server.fatal_environment_test_reset
|
|
582
|
+
return resolved.close().catch(() => undefined);
|
|
583
|
+
return resolved?.close();
|
|
584
|
+
})
|
|
201
585
|
.then(() => {
|
|
202
586
|
resolvedEnvironment = undefined;
|
|
203
587
|
configuredSettings.clear();
|
|
@@ -210,112 +594,284 @@ export const ServerEnvironmentLifecycle = Object.freeze({
|
|
|
210
594
|
return reset;
|
|
211
595
|
},
|
|
212
596
|
});
|
|
213
|
-
const
|
|
597
|
+
const environmentSetups = new WeakMap();
|
|
598
|
+
const startupControls = new WeakMap();
|
|
599
|
+
const environmentDeliveryCores = new WeakMap();
|
|
600
|
+
const remoteSupervisedEnvironments = new WeakSet();
|
|
214
601
|
const environmentLoggers = new WeakMap();
|
|
215
|
-
const
|
|
216
|
-
const
|
|
602
|
+
const supervisorStarters = new WeakMap();
|
|
603
|
+
const deliveryNotifiers = new WeakMap();
|
|
604
|
+
const deliveryIdlers = new WeakMap();
|
|
217
605
|
const warnedVolatileRegistries = new WeakMap();
|
|
606
|
+
const environmentContexts = new WeakMap();
|
|
607
|
+
/**
|
|
608
|
+
* Records live domain contexts separately from build-phase reservations.
|
|
609
|
+
*/
|
|
610
|
+
class EnvironmentContextRegistrations {
|
|
611
|
+
#contexts = new Set();
|
|
612
|
+
#completed = new Set();
|
|
613
|
+
#states = new Map();
|
|
614
|
+
#recipients = new Map();
|
|
615
|
+
#builds = 0;
|
|
616
|
+
#buildsIdle;
|
|
617
|
+
/**
|
|
618
|
+
* Finds the registrations attached to one resolved environment.
|
|
619
|
+
*
|
|
620
|
+
* @param environment Resolved environment.
|
|
621
|
+
* @returns Its context registrations.
|
|
622
|
+
*/
|
|
623
|
+
static forEnvironment(environment) {
|
|
624
|
+
const contexts = environmentContexts.get(environment);
|
|
625
|
+
if (contexts === undefined)
|
|
626
|
+
throw new TypeError("Context registration requires an environment.");
|
|
627
|
+
return contexts;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Checks whether a full singleton reset would discard context state.
|
|
631
|
+
*
|
|
632
|
+
* @returns Whether a context or build remains active.
|
|
633
|
+
*/
|
|
634
|
+
get active() {
|
|
635
|
+
return this.#builds > 0 || this.#contexts.size > 0;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Records a build until asynchronous assembly settles.
|
|
639
|
+
*
|
|
640
|
+
* @returns A callback that finishes this build exactly once.
|
|
641
|
+
*/
|
|
642
|
+
beginBuild() {
|
|
643
|
+
if (this.#builds === 0)
|
|
644
|
+
this.#buildsIdle = Promise.withResolvers();
|
|
645
|
+
this.#builds++;
|
|
646
|
+
let finished = false;
|
|
647
|
+
return () => {
|
|
648
|
+
if (finished)
|
|
649
|
+
return;
|
|
650
|
+
finished = true;
|
|
651
|
+
this.#builds--;
|
|
652
|
+
if (this.#builds === 0)
|
|
653
|
+
this.#buildsIdle?.resolve(undefined);
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Waits until every admitted build releases its local assembly ticket.
|
|
658
|
+
* @returns Completion when no build remains.
|
|
659
|
+
*/
|
|
660
|
+
whenBuildsIdle() {
|
|
661
|
+
return this.#buildsIdle?.promise ?? Promise.resolve();
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Lists constructed contexts, including incomplete registrations.
|
|
665
|
+
* @returns Snapshot of all constructed contexts.
|
|
666
|
+
*/
|
|
667
|
+
allContexts() {
|
|
668
|
+
return [...this.#contexts];
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Records an open or partly constructed context.
|
|
672
|
+
*
|
|
673
|
+
* @param context Context to track.
|
|
674
|
+
*/
|
|
675
|
+
add(context) {
|
|
676
|
+
this.#contexts.add(context);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Marks a tracked context ready for public cleanup enumeration.
|
|
680
|
+
*
|
|
681
|
+
* @param context Context whose integration opened successfully.
|
|
682
|
+
*/
|
|
683
|
+
complete(context) {
|
|
684
|
+
if (!this.#contexts.has(context))
|
|
685
|
+
throw new Error("Context completed after cleanup.");
|
|
686
|
+
this.#completed.add(context);
|
|
687
|
+
for (const endpoint of boundedContextAccess.delivery(context).endpoints())
|
|
688
|
+
this.#recipients.set(endpoint.targetTypeUrl, context);
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Finds the completed context registered for a delivery target.
|
|
692
|
+
* @param typeUrl Identifies the target message type.
|
|
693
|
+
* @returns The matching context, if one completed registration.
|
|
694
|
+
*/
|
|
695
|
+
recipient(typeUrl) {
|
|
696
|
+
return this.#recipients.get(typeUrl);
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Registers one state type without overwriting a different context.
|
|
700
|
+
*
|
|
701
|
+
* @param context Context registering the state.
|
|
702
|
+
* @param typeUrl Full wire type URL of the state.
|
|
703
|
+
* @returns The conflicting context, if another context registered it.
|
|
704
|
+
*/
|
|
705
|
+
reserve(context, typeUrl) {
|
|
706
|
+
const prior = this.#states.get(typeUrl);
|
|
707
|
+
if (prior !== undefined)
|
|
708
|
+
return prior === context ? undefined : prior;
|
|
709
|
+
this.#states.set(typeUrl, context);
|
|
710
|
+
return undefined;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Removes only registrations made by the selected context.
|
|
714
|
+
*
|
|
715
|
+
* @param context Context that completed shutdown.
|
|
716
|
+
*/
|
|
717
|
+
remove(context) {
|
|
718
|
+
this.#contexts.delete(context);
|
|
719
|
+
this.#completed.delete(context);
|
|
720
|
+
this.stopRecipients(context);
|
|
721
|
+
for (const [typeUrl, registered] of this.#states) {
|
|
722
|
+
if (registered === context)
|
|
723
|
+
this.#states.delete(typeUrl);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Removes fresh delivery endpoints while retaining state reservations.
|
|
728
|
+
* @param context Context entering close.
|
|
729
|
+
*/
|
|
730
|
+
stopRecipients(context) {
|
|
731
|
+
for (const [typeUrl, recipient] of this.#recipients)
|
|
732
|
+
if (recipient === context)
|
|
733
|
+
this.#recipients.delete(typeUrl);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Lists the context currently serving a state type.
|
|
737
|
+
*
|
|
738
|
+
* @param typeUrl Full wire type URL of the state.
|
|
739
|
+
* @returns Zero or one context names.
|
|
740
|
+
*/
|
|
741
|
+
serving(typeUrl) {
|
|
742
|
+
const context = this.#states.get(typeUrl);
|
|
743
|
+
return context === undefined ? [] : [context.name.value];
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Returns completed context references without releasing them.
|
|
747
|
+
*
|
|
748
|
+
* @returns References to integrated open contexts.
|
|
749
|
+
*/
|
|
750
|
+
openContexts() {
|
|
751
|
+
return [...this.#completed];
|
|
752
|
+
}
|
|
753
|
+
}
|
|
218
754
|
/**
|
|
219
755
|
* Provides package-only environment delivery attachment access for server lifecycle owners.
|
|
220
756
|
*
|
|
221
757
|
* @internal
|
|
222
758
|
*/
|
|
223
759
|
export const serverEnvironmentAccess = Object.freeze({
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return Promise.reject(new TypeError("Attachment requires a ServerEnvironment instance."));
|
|
233
|
-
}
|
|
234
|
-
return openDelivery().then(() => attachments.attach(options));
|
|
760
|
+
/**
|
|
761
|
+
* Returns the initialized internal Delivery engine, failing before environment setup completes.
|
|
762
|
+
*/
|
|
763
|
+
coreDelivery(environment) {
|
|
764
|
+
const core = environmentDeliveryCores.get(environment);
|
|
765
|
+
if (core === undefined)
|
|
766
|
+
throw new Error("ServerEnvironment.completeSetup() must finish before Delivery use.");
|
|
767
|
+
return core;
|
|
235
768
|
},
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return attachments.failedStartPending;
|
|
769
|
+
/**
|
|
770
|
+
* Reports whether this environment uses a remote Delivery source supervised by the runtime.
|
|
771
|
+
*/
|
|
772
|
+
remoteSupervised(environment) {
|
|
773
|
+
return remoteSupervisedEnvironments.has(environment);
|
|
242
774
|
},
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return attachments.failedStartRetryPending(error);
|
|
775
|
+
/**
|
|
776
|
+
* Waits for supervised Delivery work to become idle.
|
|
777
|
+
*/
|
|
778
|
+
whenDeliveryIdle(environment) {
|
|
779
|
+
return deliveryIdlers.get(environment)?.() ?? Promise.resolve();
|
|
249
780
|
},
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
return attachments.retryFailedStart();
|
|
781
|
+
/**
|
|
782
|
+
* Signals that the supplied shard may have Delivery work ready.
|
|
783
|
+
*/
|
|
784
|
+
notifyDelivery(environment, shard) {
|
|
785
|
+
deliveryNotifiers.get(environment)?.(shard);
|
|
257
786
|
},
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
787
|
+
/**
|
|
788
|
+
* Requires an available environment and waits for its shared setup promise.
|
|
789
|
+
*/
|
|
790
|
+
awaitSetup(environment) {
|
|
791
|
+
this.requireAvailable(environment);
|
|
792
|
+
return (environmentSetups.get(environment) ??
|
|
793
|
+
Promise.reject(new Error("Await ServerEnvironment.completeSetup() before building a Bounded Context."))).then(() => {
|
|
794
|
+
this.requireAvailable(environment);
|
|
795
|
+
});
|
|
265
796
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return attachments.retryDetach(attachment);
|
|
797
|
+
/**
|
|
798
|
+
* Starts tracking an in-progress context build in the environment lifecycle registry.
|
|
799
|
+
*/
|
|
800
|
+
beginContextBuild(environment) {
|
|
801
|
+
this.requireAvailable(environment);
|
|
802
|
+
return EnvironmentContextRegistrations.forEnvironment(environment).beginBuild();
|
|
273
803
|
},
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
804
|
+
/**
|
|
805
|
+
* Starts automatic cleanup after a required startup failure.
|
|
806
|
+
*
|
|
807
|
+
* @param environment Failed environment.
|
|
808
|
+
* @param cause Original required-phase error.
|
|
809
|
+
*/
|
|
810
|
+
failStartup(environment, cause) {
|
|
811
|
+
startupControls.get(environment)?.fail(cause);
|
|
280
812
|
},
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
813
|
+
/**
|
|
814
|
+
* Waits for the environment’s fatal startup failure, rejecting if the environment is unknown.
|
|
815
|
+
*/
|
|
816
|
+
awaitStartupFailure(environment) {
|
|
817
|
+
const control = startupControls.get(environment);
|
|
818
|
+
if (control === undefined)
|
|
819
|
+
return Promise.reject(new Error("Unknown ServerEnvironment."));
|
|
820
|
+
return control.awaitFailure();
|
|
287
821
|
},
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
return attachments.stopDelivery();
|
|
822
|
+
/**
|
|
823
|
+
* Reports whether a required environment startup phase has failed.
|
|
824
|
+
*/
|
|
825
|
+
hasStartupFailure(environment) {
|
|
826
|
+
return startupControls.get(environment)?.failed() ?? false;
|
|
295
827
|
},
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
828
|
+
/**
|
|
829
|
+
* Adds an independent partial-context rollback failure to the fatal result.
|
|
830
|
+
*
|
|
831
|
+
* @param environment Failed environment.
|
|
832
|
+
* @param error Local rollback failure.
|
|
833
|
+
*/
|
|
834
|
+
recordStartupCleanup(environment, error) {
|
|
835
|
+
startupControls.get(environment)?.recordCleanup(error);
|
|
303
836
|
},
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
createWorker,
|
|
314
|
-
}));
|
|
837
|
+
/**
|
|
838
|
+
* Throws when the environment is closing or unavailable after startup failure.
|
|
839
|
+
*/
|
|
840
|
+
requireAvailable(environment) {
|
|
841
|
+
startupControls.get(environment)?.available();
|
|
842
|
+
},
|
|
843
|
+
addContext: (environment, context) => {
|
|
844
|
+
serverEnvironmentAccess.requireAvailable(environment);
|
|
845
|
+
EnvironmentContextRegistrations.forEnvironment(environment).add(context);
|
|
315
846
|
},
|
|
847
|
+
completeContext: async (environment, context) => {
|
|
848
|
+
serverEnvironmentAccess.requireAvailable(environment);
|
|
849
|
+
EnvironmentContextRegistrations.forEnvironment(environment).complete(context);
|
|
850
|
+
const endpoints = boundedContextAccess.delivery(context).endpoints();
|
|
851
|
+
if (endpoints.length > 0)
|
|
852
|
+
await supervisorStarters.get(environment)?.();
|
|
853
|
+
serverEnvironmentAccess.requireAvailable(environment);
|
|
854
|
+
for (const endpoint of endpoints)
|
|
855
|
+
deliveryNotifiers.get(environment)?.(endpoint.shard);
|
|
856
|
+
},
|
|
857
|
+
reserveState: (environment, context, typeUrl) => EnvironmentContextRegistrations.forEnvironment(environment).reserve(context, typeUrl),
|
|
858
|
+
stopRecipients: (environment, context) => {
|
|
859
|
+
EnvironmentContextRegistrations.forEnvironment(environment).stopRecipients(context);
|
|
860
|
+
},
|
|
861
|
+
removeContext: (environment, context) => {
|
|
862
|
+
EnvironmentContextRegistrations.forEnvironment(environment).remove(context);
|
|
863
|
+
},
|
|
864
|
+
contextsServing: (environment, typeUrl) => EnvironmentContextRegistrations.forEnvironment(environment).serving(typeUrl),
|
|
865
|
+
openContexts: (environment) => EnvironmentContextRegistrations.forEnvironment(environment).openContexts(),
|
|
866
|
+
/**
|
|
867
|
+
* Returns the logger configured for this server environment.
|
|
868
|
+
*/
|
|
316
869
|
loggerFor(environment) {
|
|
317
870
|
return ServerEnvironmentValues.loggerFor(environment);
|
|
318
871
|
},
|
|
872
|
+
/**
|
|
873
|
+
* Emits one production warning when a context uses a non-persistent subscription registry.
|
|
874
|
+
*/
|
|
319
875
|
warnVolatileRegistry(environment, context) {
|
|
320
876
|
if (environment.environment.type !== EnvironmentType.Production)
|
|
321
877
|
return;
|
|
@@ -337,12 +893,24 @@ export const serverEnvironmentAccess = Object.freeze({
|
|
|
337
893
|
* @internal Groups private facility-assembly operations for the environment singleton.
|
|
338
894
|
*/
|
|
339
895
|
const ServerEnvironmentValues = Object.freeze({
|
|
896
|
+
/**
|
|
897
|
+
* Returns the installed environment logger.
|
|
898
|
+
*
|
|
899
|
+
* @param environment Resolved server environment.
|
|
900
|
+
* @returns Its logger.
|
|
901
|
+
*/
|
|
340
902
|
loggerFor(environment) {
|
|
341
903
|
const logger = environmentLoggers.get(environment);
|
|
342
904
|
if (logger === undefined)
|
|
343
905
|
throw new TypeError("ServerEnvironment logger is not available.");
|
|
344
906
|
return logger;
|
|
345
907
|
},
|
|
908
|
+
/**
|
|
909
|
+
* Gets an openable delivery facility when configured.
|
|
910
|
+
*
|
|
911
|
+
* @param delivery Configured delivery facility.
|
|
912
|
+
* @returns Openable delivery or undefined.
|
|
913
|
+
*/
|
|
346
914
|
openableDelivery(delivery) {
|
|
347
915
|
if (delivery === undefined)
|
|
348
916
|
return undefined;
|
|
@@ -356,6 +924,12 @@ const ServerEnvironmentValues = Object.freeze({
|
|
|
356
924
|
}
|
|
357
925
|
return candidate;
|
|
358
926
|
},
|
|
927
|
+
/**
|
|
928
|
+
* Maps delivery to its environment ports.
|
|
929
|
+
*
|
|
930
|
+
* @param delivery Configured delivery facility.
|
|
931
|
+
* @returns Ports when delivery is openable.
|
|
932
|
+
*/
|
|
359
933
|
ports(delivery) {
|
|
360
934
|
const remote = ServerEnvironmentValues.openableDelivery(delivery);
|
|
361
935
|
if (remote === undefined)
|
|
@@ -366,14 +940,27 @@ const ServerEnvironmentValues = Object.freeze({
|
|
|
366
940
|
...(remote.source === undefined ? {} : { source: remote.source }),
|
|
367
941
|
};
|
|
368
942
|
},
|
|
369
|
-
|
|
943
|
+
/**
|
|
944
|
+
* Lists facilities closed by the environment.
|
|
945
|
+
*
|
|
946
|
+
* @param options Resolved facilities.
|
|
947
|
+
* @param deliveryCloseGroup Closes the shared Delivery before other facilities.
|
|
948
|
+
* @returns Facilities in shutdown order.
|
|
949
|
+
*/
|
|
950
|
+
facilitiesToClose(options, deliveryCloseGroup) {
|
|
370
951
|
return Object.freeze([
|
|
371
|
-
|
|
952
|
+
deliveryCloseGroup,
|
|
372
953
|
options.integrationChannelFactory,
|
|
373
954
|
...(options.tracerFactory === undefined ? [] : [options.tracerFactory]),
|
|
374
955
|
options.storageFactory,
|
|
375
956
|
]);
|
|
376
957
|
},
|
|
958
|
+
/**
|
|
959
|
+
* Creates a default logger when none was supplied.
|
|
960
|
+
*
|
|
961
|
+
* @param logger Optional application logger.
|
|
962
|
+
* @returns Logger child for this environment.
|
|
963
|
+
*/
|
|
377
964
|
logger(logger) {
|
|
378
965
|
return (logger ??
|
|
379
966
|
new LogLayer({
|
|
@@ -388,28 +975,30 @@ const ServerEnvironmentValues = Object.freeze({
|
|
|
388
975
|
}),
|
|
389
976
|
})).child();
|
|
390
977
|
},
|
|
978
|
+
/**
|
|
979
|
+
* Resolves configured facilities with local defaults where supported.
|
|
980
|
+
*
|
|
981
|
+
* @param type Selected environment type.
|
|
982
|
+
* @param settings Configured facilities.
|
|
983
|
+
* @returns Complete resolved facilities.
|
|
984
|
+
*/
|
|
391
985
|
resolveFacilities(type, settings) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
return {
|
|
400
|
-
storageFactory: settings.storageFactory,
|
|
401
|
-
integrationChannelFactory: settings.integrationChannelFactory ?? new InMemoryTransportFactory(),
|
|
402
|
-
typeRegistry: settings.typeRegistry,
|
|
403
|
-
delivery: settings.delivery,
|
|
404
|
-
tracerFactory: settings.tracerFactory,
|
|
405
|
-
logger: ServerEnvironmentValues.logger(settings.logger),
|
|
406
|
-
};
|
|
407
|
-
}
|
|
986
|
+
const configuredCapacity = settings.subscriptionQueueCapacity;
|
|
987
|
+
if (configuredCapacity !== undefined &&
|
|
988
|
+
(!Number.isSafeInteger(configuredCapacity) || configuredCapacity < 0))
|
|
989
|
+
throw new RangeError("ServerEnvironment subscriptionQueueCapacity must be a nonnegative safe integer.");
|
|
990
|
+
const capacity = configuredCapacity ?? 100;
|
|
991
|
+
if (type === EnvironmentType.Production && settings.typeRegistry === undefined)
|
|
992
|
+
throw new Error("Production ServerEnvironment requires typeRegistry.");
|
|
408
993
|
return {
|
|
994
|
+
subscriptionQueueCapacity: capacity,
|
|
409
995
|
storageFactory: settings.storageFactory ?? new InMemoryStorageFactory(),
|
|
996
|
+
tenantIndex: settings.tenantIndex,
|
|
997
|
+
ai: settings.ai,
|
|
410
998
|
integrationChannelFactory: settings.integrationChannelFactory ?? new InMemoryTransportFactory(),
|
|
411
999
|
typeRegistry: settings.typeRegistry ?? spineCoreRegistry,
|
|
412
1000
|
delivery: settings.delivery,
|
|
1001
|
+
deliveryStrategy: settings.deliveryStrategy,
|
|
413
1002
|
tracerFactory: settings.tracerFactory,
|
|
414
1003
|
logger: ServerEnvironmentValues.logger(settings.logger),
|
|
415
1004
|
};
|