Files

5.5 KiB

Context

NenjimHub already constructs the runtime graph, starts explicitly enabled NenjimProcess objects, and records each component ID only after start() returns successfully. Its immutable getStartedProcessIds() snapshot is the authoritative successful-start history. The old Process Manager is a dormant JavaFX window with three hardcoded labels and no Hub dependency.

The existing JavaFxRuntime owns JavaFX toolkit initialization and schedules work with Platform.runLater. Nenjim has no general stop lifecycle, so this change must not add a Process Manager-specific public stop operation.

Goals / Non-Goals

Goals:

  • Make the Process Manager a normally registered and started Hub process.
  • Display exactly the ordered component-ID values reported by its owning Hub.
  • Poll outside the JavaFX application thread immediately and every three seconds.
  • Replace the complete JavaFX list on the JavaFX application thread after every successful poll.
  • Keep polling after ordinary failures and terminate cleanly on interruption.
  • Allow the JVM to terminate despite the polling worker.

Non-Goals:

  • Lifecycle events, subscriptions, push delivery, controls, configurable autorun, health or liveness monitoring, supervision, history, timestamps, display aliases, icons, colours, persistence, Contexts, classloading, Journal or Registry changes, or a general stop lifecycle.
  • General unit-test infrastructure or NenjimTestTool functionality.

Decisions

The Process Manager is an ordinary specialized process

NenjimProcessManager extends the canonical NenjimProcess and adds no methods. NenjimProcessManagerImpl requires and retains a non-null NenjimHub, which is the only source of displayed runtime status. Its startup has a one-attempt guard so one Process Manager instance cannot create multiple polling loops.

Hub composition and startup use the existing path

During application composition, NenjimHubImpl constructs the Process Manager with this and registers it as nenjim.process-manager.default. After all currently enabled business processes have started, the Hub resolves and starts the Process Manager through the same startProcess helper. The helper records its ID only after start() returns, with no Process Manager-specific status rule.

The first poll can race with the Hub's post-start recording and therefore need not contain the Process Manager's own ID. Repeated complete snapshots make the ID appear naturally on a later successful poll.

One daemon worker performs complete-snapshot polling

start() first asks the shared JavaFX runtime to show the existing window and then starts one named daemon thread. The worker polls before its first wait and sleeps three seconds between attempts. Daemon status prevents this temporary observer from keeping the JVM alive in the absence of a common stop lifecycle.

Each attempt obtains one immutable Hub snapshot and maps every ID to value() before scheduling publication. No local additions/removals are inferred, so Hub ordering and snapshot authority are preserved.

JavaFX publication replaces the entire list

Window construction and list replacement are both scheduled through JavaFxRuntime. The window task is queued before the polling worker starts, and each successful poll schedules setAll for the complete mapped snapshot. The title, dimensions, and multiple-selection behavior remain unchanged.

Failures retain the last successful display

A runtime failure while querying, mapping, or scheduling a polled snapshot is logged and does not enqueue partial data. A JavaFX publication failure is also logged on the JavaFX thread. The worker waits the ordinary interval and retries instead of accelerating or terminating. An interrupted sleep restores the thread's interrupted status and returns from the polling loop.

Synchronous JavaFX runtime initialization, task scheduling, and worker-start failures from start() remain ordinary process-start failures and propagate through the Hub's existing fail-fast path.

Polling is intentionally replaceable infrastructure

Polling is the delivered observation mechanism, not part of the Process Manager's public API. A later change can replace it with Hub events without changing the Process Manager's responsibility or list presentation model; no event type or subscription behavior is specified here.

Risks / Trade-offs

  • [The immediate poll may precede the Hub recording the Process Manager] → The next normal poll obtains the later authoritative snapshot and displays the manager's ID.
  • [A closed window does not stop the worker] → No component-specific stop lifecycle is added; the daemon remains harmless to JVM termination and keeps the view current if the JavaFX window remains present.
  • [Polling has bounded staleness] → Three seconds is explicitly required for this first vertical slice and keeps event design out of scope.
  • [JavaFX tasks are asynchronous] → The shared runtime preserves JavaFX thread confinement, while synchronous startup failures still follow Hub fail-fast behavior.

Migration Plan

  1. Specialize the Process Manager contract and inject its owning Hub.
  2. Replace hardcoded rows with daemon-backed ordered snapshot polling and JavaFX-thread publication.
  3. Register the Process Manager during Hub composition and start it last via the common lifecycle helper.
  4. Strictly validate this active OpenSpec change and build the repository, leaving synchronization and archival until review acceptance.