81: Control Nenjim process construction and ordered startup through NenjimHub.conf
This commit is contained in:
@@ -108,7 +108,7 @@ A non-bootstrap application or service that owns a component choice SHALL receiv
|
||||
- **THEN** it receives only `NenjimRegistryService` and cannot self-register
|
||||
|
||||
### Requirement: Main is a thin outer bootstrap
|
||||
`com.r35157.nenjim.hubd.Main` SHALL be a final non-component class. Its `main(String[])` SHALL construct `com.r35157.nenjim.hubd.impl.ref.NenjimHubImpl` through a variable typed as `NenjimHub` and SHALL call `start()` exactly once. The Gradle application entry point SHALL continue to name this class. The bootstrap SHALL not construct the Registry, manager, or business graph.
|
||||
`com.r35157.nenjim.hubd.Main` SHALL be a final non-component class. Its `main(String[])` SHALL construct `com.r35157.nenjim.hubd.impl.ref.NenjimHubImpl` through a variable typed as `NenjimHub` and SHALL call `start()` exactly once. The Gradle application entry point SHALL continue to name this class. The bootstrap SHALL not select a configuration path or construct the Registry, manager, or business graph.
|
||||
|
||||
#### Scenario: Start through the outer bootstrap
|
||||
- **WHEN** the configured Java entry point is invoked
|
||||
@@ -116,11 +116,11 @@ A non-bootstrap application or service that owns a component choice SHALL receiv
|
||||
|
||||
#### Scenario: No duplicate composition path remains
|
||||
- **WHEN** the source tree is inspected after migration
|
||||
- **THEN** the former Registry-manager composition path is absent, `Main` contains no composition path, and `NenjimHubImpl` is the sole owner of the current hardcoded component graph
|
||||
- **THEN** the former Registry-manager and hardcoded autorun paths are absent, `Main` contains no composition path, and `NenjimHubImpl` is the sole owner of configuration-directed composition
|
||||
|
||||
#### Scenario: Bootstrap has no composition responsibility
|
||||
- **WHEN** the outer bootstrap source is inspected
|
||||
- **THEN** composition, process tracking, online announcement, and the blocking wait are absent from `Main` and owned by the Hub implementation
|
||||
- **THEN** configuration parsing, composition, process tracking, online announcement, and the blocking wait are absent from `Main` and owned by the Hub implementation
|
||||
|
||||
### Requirement: Registry terminology and package boundaries are consistent
|
||||
Public component contracts SHALL live in `com.r35157.nenjim.component`; the canonical process contract SHALL live in `com.r35157.nenjim.process`; the global Hub contract SHALL live in `com.r35157.nenjim.hubd`; public Registry service contracts SHALL live in `com.r35157.nenjim.service.registry`; and the component ID SHALL live in its `.valuetypes` package. Registry storage and its package-private administration view SHALL live in `.impl.ref`, where an implementation-only construction boundary MAY also live without exposing administration. Directly affected Ticker price-source API and implementation packages SHALL continue to use `.pricesource`. Public reference-type parameters, return values, and record components added or changed by this capability SHALL declare explicit nullability.
|
||||
@@ -138,11 +138,11 @@ Public component contracts SHALL live in `com.r35157.nenjim.component`; the cano
|
||||
- **THEN** exactly one canonical `com.r35157.nenjim.process.NenjimProcess` contract exists and no `NenjimApplication` type remains
|
||||
|
||||
### Requirement: Deferred runtime features remain absent
|
||||
The Registry SHALL represent one catalogue of already constructed components and SHALL not implement Contexts, artifact-version identity, resolution, classloading, automatic discovery, contributor APIs, public runtime loading or registration, removal, persistence, events, subscribers, user configuration, automatic selection, automatic start-all, ownership tracking, usage counts, permissions, scopes, filtered views, or a common stop lifecycle. Except for the Process Manager's read-only polling of the existing started-process snapshot, the Hub SHALL not add configurable autorun, lifecycle events, subscriptions, process controls, stop, restart, upgrade, health monitoring, recovery, or context-bound dependency access.
|
||||
The Registry SHALL represent one catalogue of already constructed components and SHALL not implement Contexts, artifact-version identity, resolution, classloading, automatic discovery, contributor APIs, public runtime loading or registration, removal, persistence, events, subscribers, automatic start-all, ownership tracking, usage counts, permissions, scopes, filtered views, or a common stop lifecycle. Hub autorun configuration SHALL remain a private startup input that selects only the implementation's known process constructors in explicit manual order. Except for that selection and the Process Manager's read-only polling of the existing started-process snapshot, the Hub SHALL not add lifecycle events, subscriptions, process controls, stop, restart, upgrade, health monitoring, recovery, automatic dependency construction, or context-bound dependency access.
|
||||
|
||||
#### Scenario: Consumer inspects the first Registry API
|
||||
- **WHEN** a consumer examines the public Registry, Registry-manager, process, Hub, and Process Manager contracts
|
||||
- **THEN** only read-only Registry lookup, passive registration, minimal process startup, Hub startup/snapshots, and the Process Manager role are available and no deferred runtime feature is exposed
|
||||
- **THEN** only read-only Registry lookup, passive registration, minimal process startup, Hub startup/snapshots, and the Process Manager role are available and configuration, discovery, resolution, and control remain absent from public APIs
|
||||
|
||||
### Requirement: Components and processes have minimal orthogonal contracts
|
||||
`NenjimComponent` SHALL remain a pure marker with no component-ID or lifecycle property. The one canonical `com.r35157.nenjim.process.NenjimProcess` SHALL extend `NenjimComponent` and SHALL expose only `start() throws Exception` as its common lifecycle operation. Service and application SHALL remain independent domain or orchestration roles: an implementation in either role SHALL additionally implement `NenjimProcess` only when it has a Hub-managed active startup lifecycle. Passive components SHALL not implement `NenjimProcess`, and no `NenjimApplication` compatibility type SHALL remain.
|
||||
@@ -186,63 +186,63 @@ The reference Registry construction boundary SHALL create one Registry object ex
|
||||
- **THEN** no component ID identifies the manager and no lookup returns it as a component or process
|
||||
|
||||
### Requirement: NenjimHub owns composition and runtime startup
|
||||
`NenjimHub` SHALL be the global runtime owner and SHALL expose `start() throws Exception` plus an immutable ordered snapshot of successfully started process IDs. It SHALL be neither a component nor a process and SHALL not register itself. Its only accepted startup attempt SHALL construct the Registry subsystem, start the Registry process first, register it as `nenjim.registry.service`, construct and register the Journal subsystem as `nenjim.journal.service`, start Journal second, and continue to the complete hardcoded business component set from issue #76 only after Journal startup succeeds. During application composition the Hub SHALL construct exactly one `JavaFxRuntimeServiceImpl`, register it as `nenjim.javafx-runtime.service`, inject its service view into Mission Control and Process Manager, construct the Process Manager with itself, and register that manager as `nenjim.process-manager.default`. The Hub SHALL resolve only explicitly enabled IDs through `NenjimProcess`, start the JavaFX runtime service after enabled non-JavaFX business processes and before Mission Control and Process Manager, start Process Manager last, announce the existing online point, and preserve the existing blocking wait. Registration SHALL never imply startup, and the Registry and Journal managers SHALL remain distinct passive, unregistered handles retained privately by the Hub.
|
||||
`NenjimHub` SHALL remain the global runtime owner exposing only `start() throws Exception` plus an immutable ordered snapshot of successfully started process IDs. It SHALL be neither component nor process and SHALL not register itself. Its only accepted startup attempt SHALL validate the complete fixed-path Hub configuration before starting anything, construct and start Registry first, register Registry as `nenjim.registry.service`, record it, construct and register the complete passive graph, then lazily construct, register, start, and record only the remaining configured processes in exact order beginning with Journal. Registry and Journal managers SHALL remain distinct passive, unregistered handles retained privately by the Hub. Registration SHALL never imply startup. The Hub SHALL preserve the online point and blocking wait only after all configured processes succeed, without retry, rollback, dependency inference, or reordering.
|
||||
|
||||
#### Scenario: Registry starts before graph construction
|
||||
- **WHEN** the Hub performs its first startup attempt
|
||||
- **THEN** it starts, registers, and records Registry first before constructing Journal or components in the business graph
|
||||
#### Scenario: Registry starts before passive graph construction
|
||||
- **WHEN** the Hub has validated a complete startup plan and performs its first startup attempt
|
||||
- **THEN** it starts, registers, and records Registry first before constructing the passive component graph or any selected non-Registry process
|
||||
|
||||
#### Scenario: Journal starts before business composition
|
||||
- **WHEN** Registry startup and self-registration have succeeded
|
||||
- **THEN** the Hub registers, starts, and records Journal before constructing components in the business graph
|
||||
#### Scenario: Journal follows passive composition but starts second
|
||||
- **WHEN** Registry bootstrap and passive graph construction have succeeded
|
||||
- **THEN** the Hub constructs, registers, starts, and records Journal before any later configured process, so Journal remains the second successful process
|
||||
|
||||
#### Scenario: Registry is process-discoverable
|
||||
- **WHEN** the Registry registration has completed
|
||||
- **THEN** the same object is retrievable as both `NenjimRegistryService` and `NenjimProcess`
|
||||
|
||||
#### Scenario: Journal is process-discoverable
|
||||
- **WHEN** the Journal registration has completed
|
||||
- **WHEN** the configured Journal construction and registration have completed
|
||||
- **THEN** the same object is retrievable as both `JournalService` and `NenjimProcess` under `nenjim.journal.service`, while its manager is not registered
|
||||
|
||||
#### Scenario: JavaFX runtime is process-discoverable
|
||||
- **WHEN** Hub-owned application composition has completed
|
||||
- **THEN** one object is retrievable as both `JavaFxRuntimeService` and `NenjimProcess` under `nenjim.javafx-runtime.service`
|
||||
#### Scenario: Selected JavaFX runtime is process-discoverable
|
||||
- **WHEN** `nenjim.javafx-runtime.service` is selected and its registration has completed
|
||||
- **THEN** one object is retrievable as both `JavaFxRuntimeService` and `NenjimProcess` under that ID
|
||||
|
||||
#### Scenario: JavaFX applications share the runtime
|
||||
- **WHEN** Hub-owned application composition has completed
|
||||
- **THEN** Mission Control and Process Manager retain the same `JavaFxRuntimeService` instance registered by the Hub
|
||||
#### Scenario: Selected JavaFX applications share the runtime
|
||||
- **WHEN** JavaFX runtime precedes selected Mission Control or Process Manager entries
|
||||
- **THEN** each selected application retains the same already-constructed `JavaFxRuntimeService` instance registered by the Hub
|
||||
|
||||
#### Scenario: Process Manager is process-discoverable
|
||||
- **WHEN** Hub-owned application composition has completed
|
||||
- **THEN** the object constructed with the current Hub and shared JavaFX runtime is retrievable as both `NenjimProcessManager` and `NenjimProcess` under `nenjim.process-manager.default`
|
||||
#### Scenario: Selected Process Manager is process-discoverable
|
||||
- **WHEN** `nenjim.process-manager.default` is selected after JavaFX runtime and its construction and registration complete
|
||||
- **THEN** the object constructed with the current Hub and shared JavaFX runtime is retrievable as both `NenjimProcessManager` and `NenjimProcess`
|
||||
|
||||
#### Scenario: Required hardcoded bindings are registered
|
||||
- **WHEN** Hub composition completes
|
||||
- **THEN** Journal, the JavaFX runtime, the Process Manager, and all component IDs and implementation choices enumerated by issue #76 are present exactly as configured, including intentionally inactive components and excluding both service managers
|
||||
#### Scenario: Required passive bindings are registered
|
||||
- **WHEN** Hub passive composition completes
|
||||
- **THEN** all current passive component IDs and implementation choices from issue #76 are present exactly as configured, while process IDs other than Registry remain absent until selected
|
||||
|
||||
#### Scenario: Explicit startup subset preserves order
|
||||
- **WHEN** Hub startup succeeds through the Process Manager phase
|
||||
- **THEN** successful process order is `nenjim.registry.service`, `nenjim.journal.service`, `assetaz.ticker.default`, `evelyn.service.prod`, `evelyn.service.test`, `evelyn.iou-burner.prod`, `nenjim.javafx-runtime.service`, `evelyn.mission-control.default`, and `nenjim.process-manager.default`
|
||||
#### Scenario: Configured startup subset preserves order
|
||||
- **WHEN** Hub startup completes successfully
|
||||
- **THEN** successful process IDs exactly equal the validated `[AUTO_START]` entries in their declared order
|
||||
|
||||
#### Scenario: Deliberately inactive processes remain inactive
|
||||
- **WHEN** Hub startup reaches its online point
|
||||
- **THEN** `jupiter-perps-alarm.default` and the dormant Composer, Test Tool, Soda Task Manager, and Suwimo Client paths have not been started
|
||||
#### Scenario: Omitted processes do not enter the Registry
|
||||
- **WHEN** a modern process ID is omitted from `[AUTO_START]`
|
||||
- **THEN** that process is neither constructed, registered, started, nor recorded even though its implementation is known to the Hub
|
||||
|
||||
#### Scenario: Journal failure is fail-fast
|
||||
- **WHEN** Journal process startup throws
|
||||
- **THEN** Registry remains the only recorded process, no business component is constructed or started, the exception propagates, and the Hub neither announces online nor enters its final wait
|
||||
- **WHEN** Journal construction, registration, or process startup throws
|
||||
- **THEN** Registry remains the only recorded process, no later configured process is constructed or started, the exception propagates, and the Hub neither announces online nor enters its final wait
|
||||
|
||||
#### Scenario: JavaFX runtime failure is fail-fast
|
||||
- **WHEN** JavaFX runtime service startup throws
|
||||
- **THEN** its ID is not recorded, Mission Control and Process Manager do not start, the exception propagates, and the Hub neither announces online nor enters its final wait
|
||||
- **WHEN** selected JavaFX runtime construction, registration, or startup throws
|
||||
- **THEN** its ID is not recorded, no later configured process is constructed or started, the exception propagates, and the Hub neither announces online nor enters its final wait
|
||||
|
||||
#### Scenario: Hub start is not retried
|
||||
- **WHEN** any first Hub startup attempt has begun and `start()` is requested again
|
||||
- **THEN** the later request fails with `IllegalStateException` whether the first attempt succeeded or failed
|
||||
|
||||
#### Scenario: Startup failure is fail-fast
|
||||
- **WHEN** any process startup throws
|
||||
- **THEN** the exception propagates, no later process starts, the Hub neither announces online nor enters its final wait, and no generic rollback or retry is attempted
|
||||
- **WHEN** any passive composition, selected construction, registration, or process startup operation throws
|
||||
- **THEN** the exception propagates, no later process is constructed or started, the Hub neither announces online nor enters its final wait, and no generic rollback or retry is attempted
|
||||
|
||||
### Requirement: Started-process snapshots are ordered immutable and truthful
|
||||
`NenjimHub.getStartedProcessIds()` SHALL be safe before, during, and after startup and SHALL return an immutable point-in-time snapshot in successful startup order. A process ID SHALL be appended only after that process's `start()` call returns successfully, including `nenjim.javafx-runtime.service` and `nenjim.process-manager.default`. Earlier successful entries SHALL remain visible after a later failure, while a failing process SHALL never be included. The snapshot SHALL make no health or continued-liveness guarantee.
|
||||
|
||||
Reference in New Issue
Block a user