@spine-event-engine/server 2.0.0-snapshot.2
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/LICENSE +201 -0
- package/README.md +569 -0
- package/REFERENCE.md +488 -0
- package/dist/bus/command-bus.d.ts +61 -0
- package/dist/bus/command-bus.d.ts.map +1 -0
- package/dist/bus/command-bus.js +201 -0
- package/dist/bus/command-bus.js.map +1 -0
- package/dist/bus/command-dispatcher-registry.d.ts +33 -0
- package/dist/bus/command-dispatcher-registry.d.ts.map +1 -0
- package/dist/bus/command-dispatcher-registry.js +75 -0
- package/dist/bus/command-dispatcher-registry.js.map +1 -0
- package/dist/bus/command-dispatcher.d.ts +25 -0
- package/dist/bus/command-dispatcher.d.ts.map +1 -0
- package/dist/bus/command-dispatcher.js +15 -0
- package/dist/bus/command-dispatcher.js.map +1 -0
- package/dist/bus/command-errors.d.ts +23 -0
- package/dist/bus/command-errors.d.ts.map +1 -0
- package/dist/bus/command-errors.js +52 -0
- package/dist/bus/command-errors.js.map +1 -0
- package/dist/bus/event-bus.d.ts +113 -0
- package/dist/bus/event-bus.d.ts.map +1 -0
- package/dist/bus/event-bus.js +518 -0
- package/dist/bus/event-bus.js.map +1 -0
- package/dist/bus/event-dispatcher-origin-schemas.d.ts +17 -0
- package/dist/bus/event-dispatcher-origin-schemas.d.ts.map +1 -0
- package/dist/bus/event-dispatcher-origin-schemas.js +32 -0
- package/dist/bus/event-dispatcher-origin-schemas.js.map +1 -0
- package/dist/bus/event-dispatcher-registry.d.ts +48 -0
- package/dist/bus/event-dispatcher-registry.d.ts.map +1 -0
- package/dist/bus/event-dispatcher-registry.js +176 -0
- package/dist/bus/event-dispatcher-registry.js.map +1 -0
- package/dist/bus/event-dispatcher.d.ts +48 -0
- package/dist/bus/event-dispatcher.d.ts.map +1 -0
- package/dist/bus/event-dispatcher.js +15 -0
- package/dist/bus/event-dispatcher.js.map +1 -0
- package/dist/context/bounded-context.d.ts +606 -0
- package/dist/context/bounded-context.d.ts.map +1 -0
- package/dist/context/bounded-context.js +1780 -0
- package/dist/context/bounded-context.js.map +1 -0
- package/dist/context/entity-inbox.d.ts +63 -0
- package/dist/context/entity-inbox.d.ts.map +1 -0
- package/dist/context/entity-inbox.js +380 -0
- package/dist/context/entity-inbox.js.map +1 -0
- package/dist/context/local-inbox-handoff.d.ts +244 -0
- package/dist/context/local-inbox-handoff.d.ts.map +1 -0
- package/dist/context/local-inbox-handoff.js +334 -0
- package/dist/context/local-inbox-handoff.js.map +1 -0
- package/dist/context/projection-handoff.d.ts +46 -0
- package/dist/context/projection-handoff.d.ts.map +1 -0
- package/dist/context/projection-handoff.js +172 -0
- package/dist/context/projection-handoff.js.map +1 -0
- package/dist/context/tenant-index.d.ts +41 -0
- package/dist/context/tenant-index.d.ts.map +1 -0
- package/dist/context/tenant-index.js +92 -0
- package/dist/context/tenant-index.js.map +1 -0
- package/dist/delivery/conditional-pickup.d.ts +25 -0
- package/dist/delivery/conditional-pickup.d.ts.map +1 -0
- package/dist/delivery/conditional-pickup.js +26 -0
- package/dist/delivery/conditional-pickup.js.map +1 -0
- package/dist/delivery/delivery-builder.d.ts +216 -0
- package/dist/delivery/delivery-builder.d.ts.map +1 -0
- package/dist/delivery/delivery-builder.js +323 -0
- package/dist/delivery/delivery-builder.js.map +1 -0
- package/dist/delivery/delivery-lease.d.ts +15 -0
- package/dist/delivery/delivery-lease.d.ts.map +1 -0
- package/dist/delivery/delivery-lease.js +44 -0
- package/dist/delivery/delivery-lease.js.map +1 -0
- package/dist/delivery/delivery-loop.d.ts +113 -0
- package/dist/delivery/delivery-loop.d.ts.map +1 -0
- package/dist/delivery/delivery-loop.js +119 -0
- package/dist/delivery/delivery-loop.js.map +1 -0
- package/dist/delivery/delivery-monitor.d.ts +165 -0
- package/dist/delivery/delivery-monitor.d.ts.map +1 -0
- package/dist/delivery/delivery-monitor.js +168 -0
- package/dist/delivery/delivery-monitor.js.map +1 -0
- package/dist/delivery/delivery-ports.d.ts +141 -0
- package/dist/delivery/delivery-ports.d.ts.map +1 -0
- package/dist/delivery/delivery-ports.js +15 -0
- package/dist/delivery/delivery-ports.js.map +1 -0
- package/dist/delivery/delivery-run-control.d.ts +50 -0
- package/dist/delivery/delivery-run-control.d.ts.map +1 -0
- package/dist/delivery/delivery-run-control.js +66 -0
- package/dist/delivery/delivery-run-control.js.map +1 -0
- package/dist/delivery/delivery-run-coordinator.d.ts +218 -0
- package/dist/delivery/delivery-run-coordinator.d.ts.map +1 -0
- package/dist/delivery/delivery-run-coordinator.js +609 -0
- package/dist/delivery/delivery-run-coordinator.js.map +1 -0
- package/dist/delivery/delivery-storage-error.d.ts +13 -0
- package/dist/delivery/delivery-storage-error.d.ts.map +1 -0
- package/dist/delivery/delivery-storage-error.js +30 -0
- package/dist/delivery/delivery-storage-error.js.map +1 -0
- package/dist/delivery/delivery-supervisor.d.ts +175 -0
- package/dist/delivery/delivery-supervisor.d.ts.map +1 -0
- package/dist/delivery/delivery-supervisor.js +469 -0
- package/dist/delivery/delivery-supervisor.js.map +1 -0
- package/dist/delivery/delivery-worker.d.ts +180 -0
- package/dist/delivery/delivery-worker.d.ts.map +1 -0
- package/dist/delivery/delivery-worker.js +232 -0
- package/dist/delivery/delivery-worker.js.map +1 -0
- package/dist/delivery/delivery.d.ts +238 -0
- package/dist/delivery/delivery.d.ts.map +1 -0
- package/dist/delivery/delivery.js +400 -0
- package/dist/delivery/delivery.js.map +1 -0
- package/dist/delivery/inbox-records.d.ts +19 -0
- package/dist/delivery/inbox-records.d.ts.map +1 -0
- package/dist/delivery/inbox-records.js +291 -0
- package/dist/delivery/inbox-records.js.map +1 -0
- package/dist/delivery/inbox-storage.d.ts +81 -0
- package/dist/delivery/inbox-storage.d.ts.map +1 -0
- package/dist/delivery/inbox-storage.js +353 -0
- package/dist/delivery/inbox-storage.js.map +1 -0
- package/dist/delivery/inbox.d.ts +263 -0
- package/dist/delivery/inbox.d.ts.map +1 -0
- package/dist/delivery/inbox.js +172 -0
- package/dist/delivery/inbox.js.map +1 -0
- package/dist/delivery/parked-delivery-obligations.d.ts +182 -0
- package/dist/delivery/parked-delivery-obligations.d.ts.map +1 -0
- package/dist/delivery/parked-delivery-obligations.js +390 -0
- package/dist/delivery/parked-delivery-obligations.js.map +1 -0
- package/dist/delivery/shard-index.d.ts +41 -0
- package/dist/delivery/shard-index.d.ts.map +1 -0
- package/dist/delivery/shard-index.js +67 -0
- package/dist/delivery/shard-index.js.map +1 -0
- package/dist/delivery/sharded-work-registry.d.ts +114 -0
- package/dist/delivery/sharded-work-registry.d.ts.map +1 -0
- package/dist/delivery/sharded-work-registry.js +360 -0
- package/dist/delivery/sharded-work-registry.js.map +1 -0
- package/dist/entity/entity-metadata.d.ts +173 -0
- package/dist/entity/entity-metadata.d.ts.map +1 -0
- package/dist/entity/entity-metadata.js +187 -0
- package/dist/entity/entity-metadata.js.map +1 -0
- package/dist/entity/entity-storage-descriptor.d.ts +64 -0
- package/dist/entity/entity-storage-descriptor.d.ts.map +1 -0
- package/dist/entity/entity-storage-descriptor.js +227 -0
- package/dist/entity/entity-storage-descriptor.js.map +1 -0
- package/dist/entity/entity-transaction.d.ts +372 -0
- package/dist/entity/entity-transaction.d.ts.map +1 -0
- package/dist/entity/entity-transaction.js +413 -0
- package/dist/entity/entity-transaction.js.map +1 -0
- package/dist/entity/entity-transition-validation.d.ts +47 -0
- package/dist/entity/entity-transition-validation.d.ts.map +1 -0
- package/dist/entity/entity-transition-validation.js +327 -0
- package/dist/entity/entity-transition-validation.js.map +1 -0
- package/dist/entity/entity.d.ts +499 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entity.js +829 -0
- package/dist/entity/entity.js.map +1 -0
- package/dist/entity/implicit-required-id.d.ts +15 -0
- package/dist/entity/implicit-required-id.d.ts.map +1 -0
- package/dist/entity/implicit-required-id.js +123 -0
- package/dist/entity/implicit-required-id.js.map +1 -0
- package/dist/entity/spec-scanner.d.ts +14 -0
- package/dist/entity/spec-scanner.d.ts.map +1 -0
- package/dist/entity/spec-scanner.js +37 -0
- package/dist/entity/spec-scanner.js.map +1 -0
- package/dist/handler/build-time-handler-analyzer.d.ts +150 -0
- package/dist/handler/build-time-handler-analyzer.d.ts.map +1 -0
- package/dist/handler/build-time-handler-analyzer.js +1101 -0
- package/dist/handler/build-time-handler-analyzer.js.map +1 -0
- package/dist/handler/command-registration-readiness.d.ts +99 -0
- package/dist/handler/command-registration-readiness.d.ts.map +1 -0
- package/dist/handler/command-registration-readiness.js +118 -0
- package/dist/handler/command-registration-readiness.js.map +1 -0
- package/dist/handler/event-handler-filter.d.ts +43 -0
- package/dist/handler/event-handler-filter.d.ts.map +1 -0
- package/dist/handler/event-handler-filter.js +128 -0
- package/dist/handler/event-handler-filter.js.map +1 -0
- package/dist/handler/event-registration-readiness.d.ts +196 -0
- package/dist/handler/event-registration-readiness.d.ts.map +1 -0
- package/dist/handler/event-registration-readiness.js +187 -0
- package/dist/handler/event-registration-readiness.js.map +1 -0
- package/dist/handler/external.d.ts +10 -0
- package/dist/handler/external.d.ts.map +1 -0
- package/dist/handler/external.js +15 -0
- package/dist/handler/external.js.map +1 -0
- package/dist/handler/generated-handler-registry.d.ts +154 -0
- package/dist/handler/generated-handler-registry.d.ts.map +1 -0
- package/dist/handler/generated-handler-registry.js +223 -0
- package/dist/handler/generated-handler-registry.js.map +1 -0
- package/dist/handler/generated-registry-discovery.d.ts +94 -0
- package/dist/handler/generated-registry-discovery.d.ts.map +1 -0
- package/dist/handler/generated-registry-discovery.js +228 -0
- package/dist/handler/generated-registry-discovery.js.map +1 -0
- package/dist/handler/generated-registry-writer.d.ts +58 -0
- package/dist/handler/generated-registry-writer.d.ts.map +1 -0
- package/dist/handler/generated-registry-writer.js +458 -0
- package/dist/handler/generated-registry-writer.js.map +1 -0
- package/dist/handler/handler-codegen.d.ts +48 -0
- package/dist/handler/handler-codegen.d.ts.map +1 -0
- package/dist/handler/handler-codegen.js +214 -0
- package/dist/handler/handler-codegen.js.map +1 -0
- package/dist/handler/handler-decorators.d.ts +134 -0
- package/dist/handler/handler-decorators.d.ts.map +1 -0
- package/dist/handler/handler-decorators.js +239 -0
- package/dist/handler/handler-decorators.js.map +1 -0
- package/dist/handler/handler-metadata.d.ts +510 -0
- package/dist/handler/handler-metadata.d.ts.map +1 -0
- package/dist/handler/handler-metadata.js +391 -0
- package/dist/handler/handler-metadata.js.map +1 -0
- package/dist/handler/registration-readiness-metadata.d.ts +68 -0
- package/dist/handler/registration-readiness-metadata.d.ts.map +1 -0
- package/dist/handler/registration-readiness-metadata.js +170 -0
- package/dist/handler/registration-readiness-metadata.js.map +1 -0
- package/dist/handler/rejection-source.d.ts +11 -0
- package/dist/handler/rejection-source.d.ts.map +1 -0
- package/dist/handler/rejection-source.js +25 -0
- package/dist/handler/rejection-source.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/external-messages.d.ts +49 -0
- package/dist/integration/external-messages.d.ts.map +1 -0
- package/dist/integration/external-messages.js +112 -0
- package/dist/integration/external-messages.js.map +1 -0
- package/dist/integration/integration-broker.d.ts +74 -0
- package/dist/integration/integration-broker.d.ts.map +1 -0
- package/dist/integration/integration-broker.js +444 -0
- package/dist/integration/integration-broker.js.map +1 -0
- package/dist/integration/third-party-context.d.ts +56 -0
- package/dist/integration/third-party-context.d.ts.map +1 -0
- package/dist/integration/third-party-context.js +130 -0
- package/dist/integration/third-party-context.js.map +1 -0
- package/dist/repository/command-errors.d.ts +25 -0
- package/dist/repository/command-errors.d.ts.map +1 -0
- package/dist/repository/command-errors.js +43 -0
- package/dist/repository/command-errors.js.map +1 -0
- package/dist/repository/command-routing.d.ts +72 -0
- package/dist/repository/command-routing.d.ts.map +1 -0
- package/dist/repository/command-routing.js +98 -0
- package/dist/repository/command-routing.js.map +1 -0
- package/dist/repository/commit-fence.d.ts +22 -0
- package/dist/repository/commit-fence.d.ts.map +1 -0
- package/dist/repository/commit-fence.js +37 -0
- package/dist/repository/commit-fence.js.map +1 -0
- package/dist/repository/event-routing.d.ts +71 -0
- package/dist/repository/event-routing.d.ts.map +1 -0
- package/dist/repository/event-routing.js +96 -0
- package/dist/repository/event-routing.js.map +1 -0
- package/dist/repository/primitive-id.d.ts +86 -0
- package/dist/repository/primitive-id.d.ts.map +1 -0
- package/dist/repository/primitive-id.js +110 -0
- package/dist/repository/primitive-id.js.map +1 -0
- package/dist/repository/repository.d.ts +670 -0
- package/dist/repository/repository.d.ts.map +1 -0
- package/dist/repository/repository.js +3298 -0
- package/dist/repository/repository.js.map +1 -0
- package/dist/repository/routing-declarations.d.ts +75 -0
- package/dist/repository/routing-declarations.d.ts.map +1 -0
- package/dist/repository/routing-declarations.js +101 -0
- package/dist/repository/routing-declarations.js.map +1 -0
- package/dist/repository/state-update-routing.d.ts +66 -0
- package/dist/repository/state-update-routing.d.ts.map +1 -0
- package/dist/repository/state-update-routing.js +91 -0
- package/dist/repository/state-update-routing.js.map +1 -0
- package/dist/runtime/runtime.d.ts +156 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +215 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/signal-intake.d.ts +84 -0
- package/dist/runtime/signal-intake.d.ts.map +1 -0
- package/dist/runtime/signal-intake.js +94 -0
- package/dist/runtime/signal-intake.js.map +1 -0
- package/dist/runtime/signal-metadata.d.ts +242 -0
- package/dist/runtime/signal-metadata.d.ts.map +1 -0
- package/dist/runtime/signal-metadata.js +368 -0
- package/dist/runtime/signal-metadata.js.map +1 -0
- package/dist/server/browser-server.d.ts +49 -0
- package/dist/server/browser-server.d.ts.map +1 -0
- package/dist/server/browser-server.js +633 -0
- package/dist/server/browser-server.js.map +1 -0
- package/dist/server/durable-subscription-bindings.d.ts +122 -0
- package/dist/server/durable-subscription-bindings.d.ts.map +1 -0
- package/dist/server/durable-subscription-bindings.js +524 -0
- package/dist/server/durable-subscription-bindings.js.map +1 -0
- package/dist/server/environment-attachment.d.ts +356 -0
- package/dist/server/environment-attachment.d.ts.map +1 -0
- package/dist/server/environment-attachment.js +2061 -0
- package/dist/server/environment-attachment.js.map +1 -0
- package/dist/server/environment-delivery-records.d.ts +77 -0
- package/dist/server/environment-delivery-records.d.ts.map +1 -0
- package/dist/server/environment-delivery-records.js +282 -0
- package/dist/server/environment-delivery-records.js.map +1 -0
- package/dist/server/environment-delivery-worker.d.ts +161 -0
- package/dist/server/environment-delivery-worker.d.ts.map +1 -0
- package/dist/server/environment-delivery-worker.js +664 -0
- package/dist/server/environment-delivery-worker.js.map +1 -0
- package/dist/server/environment.d.ts +43 -0
- package/dist/server/environment.d.ts.map +1 -0
- package/dist/server/environment.js +90 -0
- package/dist/server/environment.js.map +1 -0
- package/dist/server/managed-child-subscription.d.ts +11 -0
- package/dist/server/managed-child-subscription.d.ts.map +1 -0
- package/dist/server/managed-child-subscription.js +44 -0
- package/dist/server/managed-child-subscription.js.map +1 -0
- package/dist/server/managed-server-application.d.ts +324 -0
- package/dist/server/managed-server-application.d.ts.map +1 -0
- package/dist/server/managed-server-application.js +937 -0
- package/dist/server/managed-server-application.js.map +1 -0
- package/dist/server/node-coordinator.d.ts +191 -0
- package/dist/server/node-coordinator.d.ts.map +1 -0
- package/dist/server/node-coordinator.js +552 -0
- package/dist/server/node-coordinator.js.map +1 -0
- package/dist/server/process-server-coordinator.d.ts +15 -0
- package/dist/server/process-server-coordinator.d.ts.map +1 -0
- package/dist/server/process-server-coordinator.js +112 -0
- package/dist/server/process-server-coordinator.js.map +1 -0
- package/dist/server/reserved-spine-rpc-paths.json +8 -0
- package/dist/server/retryable-close.d.ts +28 -0
- package/dist/server/retryable-close.d.ts.map +1 -0
- package/dist/server/retryable-close.js +129 -0
- package/dist/server/retryable-close.js.map +1 -0
- package/dist/server/server-environment.d.ts +180 -0
- package/dist/server/server-environment.d.ts.map +1 -0
- package/dist/server/server-environment.js +418 -0
- package/dist/server/server-environment.js.map +1 -0
- package/dist/server/server-log.d.ts +18 -0
- package/dist/server/server-log.d.ts.map +1 -0
- package/dist/server/server-log.js +96 -0
- package/dist/server/server-log.js.map +1 -0
- package/dist/server/server.d.ts +389 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +752 -0
- package/dist/server/server.js.map +1 -0
- package/dist/services/spine-services.d.ts +88 -0
- package/dist/services/spine-services.d.ts.map +1 -0
- package/dist/services/spine-services.js +1586 -0
- package/dist/services/spine-services.js.map +1 -0
- package/dist/stand/stand.d.ts +294 -0
- package/dist/stand/stand.d.ts.map +1 -0
- package/dist/stand/stand.js +680 -0
- package/dist/stand/stand.js.map +1 -0
- package/dist/stand/subscription-observer.d.ts +53 -0
- package/dist/stand/subscription-observer.d.ts.map +1 -0
- package/dist/stand/subscription-observer.js +444 -0
- package/dist/stand/subscription-observer.js.map +1 -0
- package/dist/stand/subscription-records.d.ts +12 -0
- package/dist/stand/subscription-records.d.ts.map +1 -0
- package/dist/stand/subscription-records.js +99 -0
- package/dist/stand/subscription-records.js.map +1 -0
- package/dist/stand/subscription-registry.d.ts +285 -0
- package/dist/stand/subscription-registry.d.ts.map +1 -0
- package/dist/stand/subscription-registry.js +403 -0
- package/dist/stand/subscription-registry.js.map +1 -0
- package/dist/stand/subscription-runtime.d.ts +102 -0
- package/dist/stand/subscription-runtime.d.ts.map +1 -0
- package/dist/stand/subscription-runtime.js +380 -0
- package/dist/stand/subscription-runtime.js.map +1 -0
- package/dist/testing/index.d.ts +14 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +34 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +65 -0
package/REFERENCE.md
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# @spine-event-engine/server reference
|
|
2
|
+
|
|
3
|
+
This reference describes the public server contracts for coding agents.
|
|
4
|
+
|
|
5
|
+
## Integration broker and event origin
|
|
6
|
+
|
|
7
|
+
Each `BoundedContext` creates and closes exactly one private integration broker.
|
|
8
|
+
The broker has distinct status, configuration, and event exchanges. Event
|
|
9
|
+
export is requested-only: a context installs a domestic publisher only for
|
|
10
|
+
event types requested by another context, and withdrawal removes only that
|
|
11
|
+
requester's interest. The broker does not enforce ownership; the supported
|
|
12
|
+
shape is many consumers and one domain producer per event type at a time.
|
|
13
|
+
|
|
14
|
+
The status exchange announces `BoundedContextOnline`; observing a foreign
|
|
15
|
+
announcement resends the local complete wanted-event document. The
|
|
16
|
+
configuration exchange treats each `ExternalEventsWanted` as a complete
|
|
17
|
+
replacement, installs producer publication on the first requester, avoids
|
|
18
|
+
duplicate unchanged broadcasts, and removes publication after the last
|
|
19
|
+
withdrawal. The event exchange uses one logical channel per event message type
|
|
20
|
+
and retains the original Event ID and complete Event. Self-origin and paired
|
|
21
|
+
domain/System Context messages are ignored.
|
|
22
|
+
|
|
23
|
+
`External<T>` is exported as a transparent type alias (`type External<T> = T`)
|
|
24
|
+
and has no runtime value or brand. The build-time handler analyzer recognizes
|
|
25
|
+
the canonical server declaration only when it is the direct first receptor
|
|
26
|
+
parameter. Missing markers mean `domestic`; a valid marker means `external`.
|
|
27
|
+
External commands are rejected, while external event/rejection handlers and
|
|
28
|
+
the supported state-subscription path are filtered by `EventContext.external`.
|
|
29
|
+
Repository selection applies the filter per handler, including mixed-origin
|
|
30
|
+
repositories. This is also the loop rule: domestic publication and origin
|
|
31
|
+
filtering prevent self-origin and paired-context traffic; no hop count, origin
|
|
32
|
+
ledger, Inbox, retry, replay, deduplication, cursor, fencing, or election is
|
|
33
|
+
added.
|
|
34
|
+
|
|
35
|
+
Incoming broker frames must contain a valid `ExternalMessage` wrapper and a
|
|
36
|
+
complete `Event`. The server unpacks and validates the event, obtains the
|
|
37
|
+
tenant from its explicit event origin, validates that tenant at the existing
|
|
38
|
+
boundary, copies only `EventContext.external = true`, and posts the ordinary
|
|
39
|
+
domain `EventBus`, whose admitted schemas are the destination's authority for
|
|
40
|
+
incoming payload decoding. Unknown or malformed received payloads are logged safely,
|
|
41
|
+
dropped, and do not stop the broker loop. Zero-byte control messages are valid
|
|
42
|
+
where the Proto contract permits an empty payload.
|
|
43
|
+
|
|
44
|
+
Malformed, unknown-schema, or undecodable received events emit the fixed ERROR
|
|
45
|
+
message `Dropped corrupt external event.` with safe `contextName`, `eventType`,
|
|
46
|
+
`operation: external-event-intake`, and
|
|
47
|
+
`reasonCode: corrupt_external_event`; the callback resolves, the event is
|
|
48
|
+
dropped, and later valid events continue. Application intake failures after a
|
|
49
|
+
valid decode remain observable.
|
|
50
|
+
|
|
51
|
+
Context readiness includes broker open. Close gates new EventBus intake before
|
|
52
|
+
awaiting transport work, broadcasts an empty wanted document, detaches domestic
|
|
53
|
+
publishers and external subscribers, drains accepted work, and closes acquired
|
|
54
|
+
channels. Failed cleanup remains retryable and concurrent close callers share
|
|
55
|
+
one attempt.
|
|
56
|
+
|
|
57
|
+
`ThirdPartyContext` is the sole public third-party import API. Its
|
|
58
|
+
`singleTenant()` form forbids an actor tenant; `multitenant()` requires one.
|
|
59
|
+
`emittedEvent(event, actor)` accepts a registered generated Protobuf message used as an event
|
|
60
|
+
payload and `ActorContext` (or a
|
|
61
|
+
`UserId` in the single-tenant form), preserves actor identity and timestamp,
|
|
62
|
+
and publishes through its hidden context. An unknown local schema throws; a
|
|
63
|
+
valid event with no interested external receptor is simply not delivered.
|
|
64
|
+
|
|
65
|
+
## Server environment facilities
|
|
66
|
+
|
|
67
|
+
`ServerEnvironment.instance()` is a process-wide singleton. Production
|
|
68
|
+
resolution requires storage and the complete application schema registry:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { EnvironmentType, ServerEnvironment } from "@spine-event-engine/server";
|
|
72
|
+
import type { TypeRegistryLookup } from "@spine-event-engine/core";
|
|
73
|
+
import type { StorageFactory } from "@spine-event-engine/storage";
|
|
74
|
+
|
|
75
|
+
declare const storageFactory: StorageFactory;
|
|
76
|
+
declare const typeRegistry: TypeRegistryLookup;
|
|
77
|
+
|
|
78
|
+
ServerEnvironment.when(EnvironmentType.Production).use({
|
|
79
|
+
storageFactory,
|
|
80
|
+
typeRegistry,
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`storageFactory` supplies records and events. `typeRegistry` is the complete
|
|
85
|
+
application schema universe used by `ThirdPartyContext` to encode outgoing
|
|
86
|
+
imported events. An optional `integrationChannelFactory` overrides the
|
|
87
|
+
process-wide private
|
|
88
|
+
integration message channel factory. When it is absent, all local bounded
|
|
89
|
+
contexts share one in-memory factory, including in production. Local and test
|
|
90
|
+
environments default storage in memory and use the core registry only as a
|
|
91
|
+
fallback; those defaults are not production configuration.
|
|
92
|
+
|
|
93
|
+
To override the default channel factory, add
|
|
94
|
+
`integrationChannelFactory: customFactory` to the same settings object.
|
|
95
|
+
|
|
96
|
+
## Routing lifecycle
|
|
97
|
+
|
|
98
|
+
Event, command, and state-update routing accepts exact schemas and nominal
|
|
99
|
+
message-interface tokens. It selects exact, first registered matching token,
|
|
100
|
+
then replacement/default. The route runs once at accepted admission; its
|
|
101
|
+
validated typed targets are stored and reused for retries. The legacy-named
|
|
102
|
+
local `catchUpReadSide()` helper is unrelated to retry: it resets and replays
|
|
103
|
+
the whole local read side, and is not Projection catch-up.
|
|
104
|
+
|
|
105
|
+
## Handler routing and operations
|
|
106
|
+
|
|
107
|
+
Generated handler metadata routes a command, event, or state update by its
|
|
108
|
+
exact generated message type. A declared default route is considered only when
|
|
109
|
+
there is no exact route. This is TypeScript routing; it does not consume
|
|
110
|
+
`(is).java_type` or `(every_is).java_type`, and it has no decorator-based
|
|
111
|
+
route registration API.
|
|
112
|
+
|
|
113
|
+
One `@Where({ eventField, equals })` equality filter may narrow an event- or
|
|
114
|
+
rejection-consuming `@Subscribe`, `@React`, or `@Command` handler after type
|
|
115
|
+
routing. `eventField` and `equals` are typed string literals; invalid or
|
|
116
|
+
repeated declarations fail closed. It is not an alternative routing mechanism.
|
|
117
|
+
|
|
118
|
+
Configure logging through `ServerEnvironment` when assembling the server. The
|
|
119
|
+
server installs that logger into its runtime components, where warnings and
|
|
120
|
+
failures carry operation context. Durable facts belong in events or storage.
|
|
121
|
+
Entity Inbox replay sends persisted accepted work through the normal handler
|
|
122
|
+
path, so handler effects must be replay-safe.
|
|
123
|
+
|
|
124
|
+
## Context assembly and entities
|
|
125
|
+
|
|
126
|
+
Create a context with `BoundedContext.singleTenant(name)` or
|
|
127
|
+
`BoundedContext.multitenant(name)`. Names are immutable. Use
|
|
128
|
+
`withStorageFactory(factory)` to supply record/event storage.
|
|
129
|
+
`withGeneratedRegistryRoot(root)` enables framework discovery of the generated
|
|
130
|
+
handler registry for classes registered with `add(EntityClass)`;
|
|
131
|
+
`buildAsync()` performs that discovery and assembly. `build()` remains for
|
|
132
|
+
explicit `Repository` registration. A built context contains `CommandBus`,
|
|
133
|
+
`EventBus`, `Stand`, repositories, and its storage lifecycle.
|
|
134
|
+
|
|
135
|
+
### Stand subscription registry
|
|
136
|
+
|
|
137
|
+
Each built context also has one `StandSubscriptionRegistry`. By default the
|
|
138
|
+
builder creates a storage-backed registry from the resolved context
|
|
139
|
+
`StorageFactory` (including the `ServerEnvironment` factory used for a builder
|
|
140
|
+
added to a server). It stores one `spine.client.SubscriptionRecord` under each
|
|
141
|
+
explicit `SubscriptionId`. A complete custom implementation can instead be
|
|
142
|
+
supplied with `withSubscriptionRegistry(registry)`; responsibility transfers to
|
|
143
|
+
the builder on the first build attempt.
|
|
144
|
+
|
|
145
|
+
`SubscriptionService` streams are live best-effort notifications, not replay,
|
|
146
|
+
ordering, or completeness contracts. A standalone Server defaults to the
|
|
147
|
+
persistent registry. In a managed complete-replica cohort, the framework owns
|
|
148
|
+
each child Server and accepts only every context's actual
|
|
149
|
+
`InMemorySubscriptionRegistry`; a persistent or custom registry is rejected
|
|
150
|
+
and the assembled child is closed before READY. Durable logical bindings remain
|
|
151
|
+
Gateway-only. The Coordinator fans each logical definition to ready children,
|
|
152
|
+
merges updates, propagates cancellation, and carries no subscription payload on
|
|
153
|
+
parent/child IPC. A late or replacement child synchronizes retained definitions
|
|
154
|
+
before it is eligible for normal requests. Active definitions attach their
|
|
155
|
+
child streams before admission; subscribed but inactive definitions do not
|
|
156
|
+
block readiness. Each child observes application-configured remote/shared
|
|
157
|
+
Delivery directly. During DRAINING, new unary and shard admission stops while
|
|
158
|
+
active Delivery and its subscription updates finish before child close. The
|
|
159
|
+
application owns Delivery facility and shard-strategy selection; managed mode
|
|
160
|
+
does not infer or certify configuration provenance.
|
|
161
|
+
|
|
162
|
+
Create records begin `pending` and expire after 30 seconds unless activated.
|
|
163
|
+
Active records have no framework TTL. Cancellation physically deletes the
|
|
164
|
+
definition; no tombstone remains. A stored definition is at most 1 MiB
|
|
165
|
+
(1,048,576 bytes). Its physical provider columns are `status` and
|
|
166
|
+
`when_activation_expires`. `cleanup()` asks the provider for 26 pending rows
|
|
167
|
+
ordered by `when_activation_expires` then ID, validates that finite result,
|
|
168
|
+
deletes at most 25 expired definitions, and reports `more` only when its
|
|
169
|
+
observed 26th row is expired. Cleanup can run idempotently on every node.
|
|
170
|
+
|
|
171
|
+
Context close drains and closes Stand before its registry, then closes tenant,
|
|
172
|
+
repository, and storage resources; it attempts every close and reports
|
|
173
|
+
aggregate failures. An in-memory registry reports `persistent === false`.
|
|
174
|
+
Attaching such a context to a production `ServerEnvironment` emits one
|
|
175
|
+
context-name-only warning without failing startup; Local environments do not
|
|
176
|
+
warn.
|
|
177
|
+
|
|
178
|
+
Creation writes the pending record only when that ID is absent. Activation
|
|
179
|
+
replaces that pending record only when it remains unchanged. Cancellation and
|
|
180
|
+
expiry cleanup delete the observed record only when it remains unchanged. Each
|
|
181
|
+
node reconciles its local snapshot immediately after context assembly and then
|
|
182
|
+
every ten seconds. Physical deletion detaches the local observer after its next
|
|
183
|
+
completed cycle. This is best-effort per-node convergence, not a
|
|
184
|
+
cluster-completeness, replay, ordering, gap-repair, or exactly-once guarantee.
|
|
185
|
+
|
|
186
|
+
The registry accepts only a generated `SubscriptionId` for activate, get, and
|
|
187
|
+
delete. `create(subscription)` returns `{ kind: "created", entry }` or
|
|
188
|
+
`{ kind: "existing", entry }`; the latter requires byte-equivalent canonical
|
|
189
|
+
content and a different definition with the same ID throws `StandConflictError`.
|
|
190
|
+
`activate(id)` returns `activated`, `active`, `missing`, or `expired`.
|
|
191
|
+
`delete(id)` returns `deleted` or `missing`. Blank IDs or topics and malformed
|
|
192
|
+
durable records fail closed.
|
|
193
|
+
|
|
194
|
+
Entries and nested subscriptions returned by create, activate, get, and
|
|
195
|
+
snapshot are clone-safe views. Protobuf byte arrays remain mutable runtime
|
|
196
|
+
views but are cloned so they never alias caller storage. Snapshots are ordered
|
|
197
|
+
by identifier. A durable provider must implement atomic compare-and-set for
|
|
198
|
+
`SubscriptionRecord`; construction rejects a provider that cannot. MySQL table
|
|
199
|
+
configuration and Datastore custom record storage registered for
|
|
200
|
+
`SubscriptionRecord` are used by the registry. The registry uses one
|
|
201
|
+
record-storage handle, while the context closes the registry.
|
|
202
|
+
|
|
203
|
+
`Entity` is the state base class. `Aggregate`, `Projection`, and
|
|
204
|
+
`ProcessManager` identify the three entity families. Handler decorators are
|
|
205
|
+
`@Assign`, `@Command`, `@React`, `@Subscribe`, and `@Apply`. In a transactional
|
|
206
|
+
handler, `update(mutator)` changes the active draft and returns the draft;
|
|
207
|
+
`tryUpdate(mutator)` validates a scratch draft and returns violations without
|
|
208
|
+
applying an invalid change. Entity lifecycle and version changes are committed
|
|
209
|
+
only after the transaction accepts.
|
|
210
|
+
|
|
211
|
+
## Signals, validation, and rejection behavior
|
|
212
|
+
|
|
213
|
+
`CommandBus` validates every accepted command from Proto validation options
|
|
214
|
+
before dispatcher or repository handler code runs. It raises the framework's
|
|
215
|
+
command-validation failure, which `SpineServices` maps to
|
|
216
|
+
`COMMAND_VALIDATION_ERROR` with a packed `spine.validation.ValidationError`.
|
|
217
|
+
Entity transition validation failures map to
|
|
218
|
+
`COMMAND_STATE_TRANSITION_VALIDATION_FAILED` with the same detail type.
|
|
219
|
+
|
|
220
|
+
An application handler throws a generated core `RejectionThrowable` for a
|
|
221
|
+
domain rejection. The repository rolls back state, version, lifecycle, and
|
|
222
|
+
output; it schedules the typed rejection event independently. Command service
|
|
223
|
+
acknowledgement remains an accepted `Ack`. Rejection-event posting can be
|
|
224
|
+
unobserved by inactive, full, or closed subscriptions and a posting failure is
|
|
225
|
+
an internal diagnostic, not a retry guarantee.
|
|
226
|
+
|
|
227
|
+
Every domain context has an internal paired System Context. Domain events use
|
|
228
|
+
the domain `EventBus` and domain `EventStore`. System events use only the
|
|
229
|
+
System Context `EventBus`, so they never enter the domain EventStore. System
|
|
230
|
+
event persistence is optional: `persistSystemEvents()` enables the paired
|
|
231
|
+
System Context's separate storage; otherwise the bus validates, dispatches,
|
|
232
|
+
and notifies without appending. Schemas may come from an external dispatcher or
|
|
233
|
+
a registered internal repository producer. A producer-only schema is not
|
|
234
|
+
thereby an external dispatch route.
|
|
235
|
+
|
|
236
|
+
## Services, reads, and lifecycle
|
|
237
|
+
|
|
238
|
+
`SpineServices({ contexts }).register(router)` registers the JVM-compatible
|
|
239
|
+
CommandService, QueryService, and SubscriptionService contracts. `Server`
|
|
240
|
+
opens the local Node HTTP/2 listener; default host is `127.0.0.1`. Set
|
|
241
|
+
`readMaxBytes` and `writeMaxBytes` only to integers 1–4294967295; defaults are 4194304. `RunningServer.close()` stops intake, closes sessions, waits for active
|
|
242
|
+
work to stop using dependencies, then closes contexts. Caller-managed `start()`
|
|
243
|
+
does not close global process facilities; close `ServerEnvironment.instance()`
|
|
244
|
+
separately when used. The final run-managed `run()` close closes its environment.
|
|
245
|
+
|
|
246
|
+
`Stand` registers entity state for point/list reads, updates current state, and
|
|
247
|
+
offers in-process subscriptions. The legacy-named local reset/replay helper
|
|
248
|
+
`catchUpReadSide(options?)` clears every registered Projection state and replays
|
|
249
|
+
the whole stored event history through matching Projection subscribers; it does
|
|
250
|
+
not append events. Single-tenant contexts reject a tenant option; multitenant
|
|
251
|
+
contexts require one. It cannot target a Projection repository, entity IDs, or
|
|
252
|
+
a starting time, and has no durable operation identity, progress, Inbox
|
|
253
|
+
catch-up delivery, restart, resumption, or historical/live coordination. It is
|
|
254
|
+
not JVM-equivalent Projection catch-up.
|
|
255
|
+
|
|
256
|
+
Active subscription streams and queues are process-local. `Stand` serves
|
|
257
|
+
authoritative queries from current state and Entity subscriptions observe
|
|
258
|
+
committed `EntityStateChanged` messages on the paired System Context EventBus,
|
|
259
|
+
so a direct Stand write alone does not produce a subscription update. Consumer
|
|
260
|
+
callback failures are isolated from post-commit observation and other
|
|
261
|
+
consumers. The package does not guarantee cluster-complete observations,
|
|
262
|
+
subscription replay, event-gap repair, or exactly-once effects.
|
|
263
|
+
|
|
264
|
+
### Standalone and browser hosting
|
|
265
|
+
|
|
266
|
+
`Server.start()` installs no process signal handlers, never closes its
|
|
267
|
+
environment, and shares only a caller-managed active generation. `Server.run()`
|
|
268
|
+
coalesces concurrent calls on one builder, shares a run-managed generation with
|
|
269
|
+
other `run()` servers, and rejects mixed admission before listener open. The
|
|
270
|
+
coordinator uses one `SIGINT`/`SIGTERM` listener pair, closes servers in reverse
|
|
271
|
+
successful-start order, retains failed final environment closure for later
|
|
272
|
+
signal or explicit-close retry, and sets `process.exitCode` to `1` after a
|
|
273
|
+
signal-driven failure.
|
|
274
|
+
|
|
275
|
+
`ManagedServerApplication.run()` is the Node-only deployment entrypoint for a
|
|
276
|
+
complete-replica process cohort when the framework owns process shutdown.
|
|
277
|
+
`ManagedServerApplication.start()` starts the same cohort for an embedding host
|
|
278
|
+
and installs no process signal handlers; that host closes the returned handle.
|
|
279
|
+
Both require a positive safe-integer
|
|
280
|
+
`processCount` and an ESM `moduleUrl`; it never derives a process count from
|
|
281
|
+
the machine. Its optional `host` and required nonzero `port` bind the public
|
|
282
|
+
Coordinator listener. Every child executes that same module and calls its own
|
|
283
|
+
`createServer({ host: "127.0.0.1", port: 0 })`. The child reports its actual
|
|
284
|
+
loopback endpoint only after its local readiness gates settle. The parent
|
|
285
|
+
initially waits until every configured child is ready. Afterwards it is ready
|
|
286
|
+
while at least one child is ready; it remains alive and keeps replacing while
|
|
287
|
+
degraded, and reports unready if no child is ready. It replaces an unexpected
|
|
288
|
+
child exit after a bounded exponential delay (250 ms initially, capped at 30 s;
|
|
289
|
+
reset after 60 s READY). It does not restart a child being closed. Restart
|
|
290
|
+
values are optional `restart` settings and must be positive safe integers;
|
|
291
|
+
concurrent starts default to `min(4, processCount)`. `run()` parent `SIGINT`
|
|
292
|
+
and `SIGTERM` use the same shared child-close path; `start()` leaves those
|
|
293
|
+
signals to its caller. This private lifecycle channel
|
|
294
|
+
does not transport application signals. The Coordinator forwards generated
|
|
295
|
+
Command and Query unary calls once to a READY child; process count does not
|
|
296
|
+
inspect CPU availability and does not constrain the application's independently
|
|
297
|
+
chosen `DeliveryStrategy` or shard count. Direct `Server.run()` and browser
|
|
298
|
+
hosting remain independent of managed Node deployment.
|
|
299
|
+
|
|
300
|
+
If no child is READY, Command and Query return gRPC `UNAVAILABLE`. The
|
|
301
|
+
Coordinator does not enter application intake and does not retry the selected
|
|
302
|
+
call on a sibling child. Subscription fan-out follows current READY members;
|
|
303
|
+
later and replacement members attach the retained subscription before managed
|
|
304
|
+
admission.
|
|
305
|
+
|
|
306
|
+
`ServerOptions.browser` changes the public listener, not the bounded-context
|
|
307
|
+
services. The native HTTP/2 backend binds to an ephemeral loopback port and is
|
|
308
|
+
never returned. After it is ready, the server creates `UnaryGateway`,
|
|
309
|
+
`SubscriptionGateway`, and native gateway services, then binds one HTTP/1.1
|
|
310
|
+
Connect/gRPC-Web listener. A public bind failure closes subscription resources
|
|
311
|
+
and the native backend; multiple rollback failures are aggregated.
|
|
312
|
+
|
|
313
|
+
Browser unary gateway admission has a fixed 1 MiB (1,048,576-byte) request
|
|
314
|
+
limit. A larger unary gateway request is rejected with `ResourceExhausted`.
|
|
315
|
+
This is an additional boundary: `readMaxBytes` still limits the Connect or
|
|
316
|
+
gRPC-Web transport message accepted by the public listener, so the effective
|
|
317
|
+
inbound limit is the stricter applicable limit. `writeMaxBytes` limits public
|
|
318
|
+
transport responses independently.
|
|
319
|
+
|
|
320
|
+
Browser origins must be unique canonical HTTP(S) origins with no path, query,
|
|
321
|
+
fragment, or trailing slash. Requests without an allowed exact `Origin` receive
|
|
322
|
+
403 before RPC handling. Allowed responses include credentialed exact-origin
|
|
323
|
+
CORS, `Vary: Origin`, protocol request headers, and exposed gRPC status headers.
|
|
324
|
+
|
|
325
|
+
Supplying `browser.backend.baseUrl` selects standalone mode. It is one canonical
|
|
326
|
+
HTTP(S) origin for a Spine TS or JVM backend; the gateway never closes
|
|
327
|
+
that backend. Every standalone mode, including local development and tests,
|
|
328
|
+
requires explicit subscription bindings; production additionally requires an
|
|
329
|
+
application type registry and named durable bindings. `ResolveContext` stays in the gateway;
|
|
330
|
+
Post, Read, Subscribe, Activate, and Cancel use the same authenticated policy,
|
|
331
|
+
context-replacement, and native descriptors before reaching the backend.
|
|
332
|
+
|
|
333
|
+
`browser.backend.baseUrls` is exclusive with `baseUrl` and configures a
|
|
334
|
+
non-empty ordered unique static node set. Unary calls use bounded round-robin
|
|
335
|
+
without retry; native streams fan out best-effort. Durable bindings retain only
|
|
336
|
+
logical definitions, not topology. Clients
|
|
337
|
+
re-query authoritative state after duplicate updates or generic loss notices.
|
|
338
|
+
|
|
339
|
+
`browser.authRoutes` is deliberately a bounded callback seam, not a router.
|
|
340
|
+
Each registration has one exact `GET` or `POST` canonical path, one method per
|
|
341
|
+
path, exact canonical origins, finite request bytes, and a finite timeout. A
|
|
342
|
+
missing Origin is rejected unless that route explicitly permits it for an OAuth
|
|
343
|
+
callback. Unknown paths, method/origin failures, body overflow, timeout, and
|
|
344
|
+
handler failure return fixed 404, 405, 403, 413, 504, and 500 responses without
|
|
345
|
+
calling application code on rejected input. The 404 unknown-path result applies
|
|
346
|
+
only after framework Origin admission. Auth admission is bounded to 64 active
|
|
347
|
+
requests by default or a configured positive `maxActiveAuthRequests`; excess
|
|
348
|
+
requests receive 503 before handler invocation and capacity returns when work
|
|
349
|
+
settles. The route deadline covers body intake, handler work, and response
|
|
350
|
+
transfer. Response bodies use `writeMaxBytes`; overflow returns 413 before any
|
|
351
|
+
application status or headers are committed. Listener close ultimately aborts
|
|
352
|
+
an active request through its disconnect signal.
|
|
353
|
+
|
|
354
|
+
With `cookies`, `OpaqueSessionCookies` performs strict bearer-first or
|
|
355
|
+
CSRF-protected cookie extraction. A strict rejection becomes an unusable
|
|
356
|
+
credential and never falls back to permissive header parsing. Without cookies,
|
|
357
|
+
the host accepts exactly one non-whitespace bearer token. Credentials and raw
|
|
358
|
+
transport metadata do not reach the private backend. The application-supplied
|
|
359
|
+
context resolver replaces caller actor and tenant facts before forwarding.
|
|
360
|
+
|
|
361
|
+
Browser close stops new listener intake, closes subscription admission and
|
|
362
|
+
bindings so active streams settle, awaits listener closure, then closes the
|
|
363
|
+
native backend. Concurrent calls share an attempt; a failed unfinished phase
|
|
364
|
+
can be retried without repeating completed native cleanup.
|
|
365
|
+
|
|
366
|
+
Browser subscription bindings are separate from service subscription records.
|
|
367
|
+
`BrowserAdmission` selects their ownership. Authenticated mode supplies
|
|
368
|
+
`sessions` and may supply `BrowserServerOptions.bindings`; production then
|
|
369
|
+
requires the Server package's `DurableSubscriptionBindings` and rejects a
|
|
370
|
+
missing or in-memory binding store before listener open. Public mode supplies
|
|
371
|
+
`publicAccess: true`, cannot supply bindings, and uses framework-owned
|
|
372
|
+
process-local bindings. The durable registry receives an explicit application
|
|
373
|
+
namespace, storage factory, identifier source, and cleanup callback. It closes
|
|
374
|
+
only its independently opened record-storage handle, not the application
|
|
375
|
+
storage factory or a Spine JVM/TS backend. It stores canonical public
|
|
376
|
+
Subscription definitions, never backend envelopes or membership topology, and
|
|
377
|
+
never returns private native data through public subscription responses.
|
|
378
|
+
|
|
379
|
+
The durable registry preserves one approved `GatewayAuthenticatedSubscription`
|
|
380
|
+
per public subscription through a process restart. It validates the record ID,
|
|
381
|
+
full Subscription, and expiry before use. The trusted Actor and Tenant remain
|
|
382
|
+
inside the stored Topic and are checked for Activate and Cancel. Create assigns
|
|
383
|
+
the public ID directly; no quota, reservation, fingerprint, or lease is
|
|
384
|
+
persisted. Cleanup remains bounded and restart-safe at the record level. It
|
|
385
|
+
cleans the backend definition before deleting its record. It is not a cleaner
|
|
386
|
+
lease or fence: this direct store supports one Gateway process. Active streams do not resume,
|
|
387
|
+
updates are not replayed, and the registry provides neither exactly-once
|
|
388
|
+
delivery, global update ordering, nor cluster-complete notification delivery.
|
|
389
|
+
|
|
390
|
+
## Delivery and environment
|
|
391
|
+
|
|
392
|
+
`Inbox`, `InboxStorage`, `ShardIndex`, and `ShardedWorkRegistry` provide the
|
|
393
|
+
local durable-row abstraction. Read limits are 1–1000; work leases are
|
|
394
|
+
1000–2147483647 ms. Framework replay supports command handling, projection
|
|
395
|
+
updates, and process-manager reactions. Callbacks are at-least-once/replay-safe:
|
|
396
|
+
lost renewal can prevent stale finalization but cannot undo a callback already
|
|
397
|
+
run. The package exposes no general raw worker callback API.
|
|
398
|
+
|
|
399
|
+
Shard ownership is the only delivery exclusion mechanism and excludes
|
|
400
|
+
concurrent delivery within that shard. Pending and delivered `InboxMessage`
|
|
401
|
+
rows are direct records; a delivered row is the deduplication fact. A handler
|
|
402
|
+
effect and the exact pending-to-delivered compare-and-set are not one
|
|
403
|
+
transaction, so a lost acknowledgement can redeliver after restart. Downstream
|
|
404
|
+
signal handling must be idempotent. A customized `DeliveryWorkRegistry`
|
|
405
|
+
implements `validateOwnership()` so delivery can validate before dispatch, at
|
|
406
|
+
repository commit time, and before acknowledgement. Validation is a fence
|
|
407
|
+
against an observed takeover, not a distributed transaction with handler
|
|
408
|
+
storage.
|
|
409
|
+
|
|
410
|
+
`keepUntil` is the optional deduplication-protection deadline, not a second
|
|
411
|
+
retention setting. A delivered row is cleanup-eligible when that deadline is
|
|
412
|
+
absent or elapsed. Under current shard ownership, environment delivery performs
|
|
413
|
+
one bounded cleanup page, plus at most one continuation after a full protected
|
|
414
|
+
page makes no removal. Each removal atomically verifies ownership and the exact
|
|
415
|
+
delivered snapshot. Pending, retryable, non-delivered, and still-protected rows
|
|
416
|
+
remain. There is no additional retention configuration, timer, or scheduler.
|
|
417
|
+
|
|
418
|
+
`BoundedContextBuilder.withDeliveryStrategy(strategy)` snapshots a validated
|
|
419
|
+
immutable strategy for its Entity Inbox; the default is one shard. For example,
|
|
420
|
+
use the public builder chain:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
import { BoundedContext, UniformAcrossAllShards } from "@spine-event-engine/server";
|
|
424
|
+
|
|
425
|
+
const context = BoundedContext.singleTenant("Tasks")
|
|
426
|
+
.withDeliveryStrategy(UniformAcrossAllShards.forNumber(3))
|
|
427
|
+
.build();
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Aggregate commands and Process Manager commands/events derive their target shard
|
|
431
|
+
internally and persist their envelope in the target Entity Inbox before any
|
|
432
|
+
handler runs. Delivery is never a post-request callback: local and remote
|
|
433
|
+
handler runs. Local intake can directly drain the persisted Inbox in the
|
|
434
|
+
current request path. Attached `ServerEnvironment` ports acknowledge admission
|
|
435
|
+
and delivery workers replay it through the same path. Projection rows remain
|
|
436
|
+
separate.
|
|
437
|
+
|
|
438
|
+
`DeliveryBuilder` constructs a controlled `Delivery`; `DeliverySupervisor`
|
|
439
|
+
receives `{ source, delivery, onMessage }`, manages bounded shard notifications
|
|
440
|
+
from that structural source, and must start after endpoints are ready and close
|
|
441
|
+
before source client/storage. `DeliverySource` is not configured on
|
|
442
|
+
`DeliveryBuilder`. The supervisor does not promise
|
|
443
|
+
durable supervisor state, topology failover, exactly-once effects, or automatic
|
|
444
|
+
retry of unknown remote mutations.
|
|
445
|
+
|
|
446
|
+
Each drain operation is bounded to one page. That bound limits a single
|
|
447
|
+
operation, not the total pending work: an active lease owner can take another
|
|
448
|
+
page while its policy retains the shard. The 30-second Inbox deduplication
|
|
449
|
+
window controls duplicate admission only; it is not a replay-retention period.
|
|
450
|
+
Persisted accepted rows follow their delivery lifecycle and may be replayed
|
|
451
|
+
according to that lifecycle after the deduplication window has elapsed.
|
|
452
|
+
|
|
453
|
+
`DeliveryMonitor` is an instantiable, customizable policy seam exposing
|
|
454
|
+
asynchronous continuation, start/completion, failed-reception, pickup-failure,
|
|
455
|
+
and already-picked hooks.
|
|
456
|
+
`FailedReception` supplies only `markDelivered()` and one immediate
|
|
457
|
+
`repeatDispatching()` action; the framework adds no attempt history, timer,
|
|
458
|
+
backoff, quarantine, dead-letter, receipt, marker, or scheduler policy. A failed
|
|
459
|
+
durable acknowledgement keeps that row pending, blocks later rows for its
|
|
460
|
+
target during the run, and does not prevent independent targets from running.
|
|
461
|
+
|
|
462
|
+
`Environment` resolves the Node `local` or `production` profile once from
|
|
463
|
+
`NODE_ENV`. `ServerEnvironment` resolves configured facilities once for that
|
|
464
|
+
profile and exposes its `storageFactory`, optional `delivery`, optional
|
|
465
|
+
`tracerFactory`, `nodeId`, and `close()` lifecycle. Applications do
|
|
466
|
+
not manage internal server attachments through this public API. Neither API
|
|
467
|
+
authenticates requests or supplies a production scheduler, remote topology,
|
|
468
|
+
storage adapter, or deployment policy.
|
|
469
|
+
|
|
470
|
+
`ServerEnvironmentDelivery` extends the existing closeable facility shape with
|
|
471
|
+
`open()` plus generic `inbox` and `workRegistry` ports. After readiness, the
|
|
472
|
+
environment supplies those ports to both existing delivery paths: direct finite
|
|
473
|
+
`Delivery` construction and the supervisor's `DeliveryBuilder`. The environment
|
|
474
|
+
invokes `open()` once before attachment admission and coalesces concurrent
|
|
475
|
+
callers; rejection admits no attachment and a later attempt retries open. A
|
|
476
|
+
close-only local delivery remains source-compatible. After attachments retire,
|
|
477
|
+
environment close runs delivery, tracer, then storage and preserves retry
|
|
478
|
+
checkpoints for failed phases.
|
|
479
|
+
|
|
480
|
+
`ServerEnvironmentDelivery.source` is optional. When present, its Admin source
|
|
481
|
+
is used by the environment supervisor for remote snapshots and
|
|
482
|
+
shard-update hints; when absent, the existing local source remains the fallback.
|
|
483
|
+
Applications configure and close only the delivery facility through the
|
|
484
|
+
environment: attachment supervisors and their source reads belong to that facility.
|
|
485
|
+
|
|
486
|
+
# Dynamic unary discovery
|
|
487
|
+
|
|
488
|
+
`BrowserServerOptions.discovery` may supply changing complete application-node snapshots alongside fixed `backend` configuration. Both unary routing and native subscription streams use the same current membership. Empty membership retains durable definitions and later nodes reactivate them; a new backend-dependent subscription is unavailable until a node exists.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Command } from "@spine-event-engine/proto";
|
|
2
|
+
import type { CommandDispatcher } from "./command-dispatcher.js";
|
|
3
|
+
interface CommandBusAccess {
|
|
4
|
+
postInternal(commandBus: CommandBus, command: Command): Promise<void>;
|
|
5
|
+
beginClose(commandBus: CommandBus): void;
|
|
6
|
+
drain(commandBus: CommandBus): Promise<void>;
|
|
7
|
+
finishClose(commandBus: CommandBus): Promise<void>;
|
|
8
|
+
acceptedWorkCount(commandBus: CommandBus): number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Small single-process unicast command bus.
|
|
12
|
+
*
|
|
13
|
+
* Commands are accepted asynchronously through `post()` and routed by enclosed
|
|
14
|
+
* message type URL to exactly one registered dispatcher.
|
|
15
|
+
*/
|
|
16
|
+
export declare class CommandBus {
|
|
17
|
+
#private;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a bus and registers its initial dispatchers.
|
|
20
|
+
*
|
|
21
|
+
* @param dispatchers the dispatchers to register.
|
|
22
|
+
*/
|
|
23
|
+
constructor(dispatchers?: Iterable<CommandDispatcher>);
|
|
24
|
+
/**
|
|
25
|
+
* Registers a dispatcher.
|
|
26
|
+
*
|
|
27
|
+
* @param dispatcher the dispatcher to register.
|
|
28
|
+
* @returns the registered dispatcher.
|
|
29
|
+
*/
|
|
30
|
+
register<Dispatcher extends CommandDispatcher>(dispatcher: Dispatcher): Dispatcher;
|
|
31
|
+
/**
|
|
32
|
+
* Lists command type URLs accepted by registered dispatchers.
|
|
33
|
+
*
|
|
34
|
+
* @returns the accepted command type URLs.
|
|
35
|
+
*/
|
|
36
|
+
acceptedCommandTypes(): readonly string[];
|
|
37
|
+
/**
|
|
38
|
+
* Posts a command for asynchronous dispatch.
|
|
39
|
+
*
|
|
40
|
+
* @param command the command envelope to post.
|
|
41
|
+
* @returns A promise that settles after queued command dispatch completes and may reject.
|
|
42
|
+
*/
|
|
43
|
+
post(command: Command): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Stops accepting new command work and waits for accepted work to settle.
|
|
46
|
+
*
|
|
47
|
+
* Close is idempotent and returns the same close outcome on repeated calls.
|
|
48
|
+
* Runtime close failures reject the returned promise.
|
|
49
|
+
* @returns A promise that settles after the command bus closes.
|
|
50
|
+
*
|
|
51
|
+
*/
|
|
52
|
+
close(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Provides framework-owned command posting and coordinated close access.
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export declare const commandBusAccess: CommandBusAccess;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=command-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-bus.d.ts","sourceRoot":"","sources":["../../src/bus/command-bus.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAUxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAQjE,UAAU,gBAAgB;IACxB,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,WAAW,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC;CACnD;AAID;;;;;GAKG;AACH,qBAAa,UAAU;;IAQrB;;;;OAIG;gBACS,WAAW,GAAE,QAAQ,CAAC,iBAAiB,CAAM;IAezD;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,SAAS,iBAAiB,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU;IAKlF;;;;OAIG;IACH,oBAAoB,IAAI,SAAS,MAAM,EAAE;IAIzC;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrC;;;;;;;OAOG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA6EvB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAkD7B,CAAC"}
|