79: Integrate NenjimProcessManager with NenjimHub runtime status

This commit is contained in:
2026-09-02 21:51:05 +02:00
parent 7b1f6d18eb
commit 0cb125ca9d
11 changed files with 552 additions and 21 deletions
@@ -28,6 +28,8 @@ import com.r35157.libs.objcache.impl.ref.ObjectCacheImpl;
import com.r35157.libs.solana.impl.cached.CachedSolanaBlockChain;
import com.r35157.libs.valuetypes.basic.MoneyAmount;
import com.r35157.nenjim.hubd.NenjimHub;
import com.r35157.nenjim.npm.NenjimProcessManager;
import com.r35157.nenjim.npm.impl.ref.NenjimProcessManagerImpl;
import com.r35157.nenjim.process.NenjimProcess;
import com.r35157.nenjim.service.journal.JournalService;
import com.r35157.nenjim.service.journal.JournalServiceManager;
@@ -94,6 +96,7 @@ public final class NenjimHubImpl implements NenjimHub {
startProcess(registryService, EVELYN_SERVICE_TEST_ID);
startProcess(registryService, EVELYN_IOU_BURNER_PROD_ID);
startProcess(registryService, EVELYN_MISSION_CONTROL_ID);
startProcess(registryService, PROCESS_MANAGER_ID);
System.out.println("Done - Now online!");
@@ -278,6 +281,11 @@ public final class NenjimHubImpl implements NenjimHub {
registryServiceManager.registerComponent(
EVELYN_MISSION_CONTROL_ID,
missionControl);
processManager = new NenjimProcessManagerImpl(this);
registryServiceManager.registerComponent(
PROCESS_MANAGER_ID,
processManager);
}
private void startProcess(
@@ -356,6 +364,8 @@ public final class NenjimHubImpl implements NenjimHub {
new NenjimComponentId("evelyn.iou-burner.prod");
private static final NenjimComponentId EVELYN_MISSION_CONTROL_ID =
new NenjimComponentId("evelyn.mission-control.default");
private static final NenjimComponentId PROCESS_MANAGER_ID =
new NenjimComponentId("nenjim.process-manager.default");
private static final ΩRaydiumLiquidityPoolIdΩ EVE_USDT_RAYDIUM_POOL_ID =
"8rN4BTEzbogQosEQYgsEu18XwfKS5Yoxqwit8zEVFwEe";
private final CountDownLatch shutdownLatch = new CountDownLatch(1);
@@ -395,4 +405,5 @@ public final class NenjimHubImpl implements NenjimHub {
// Application components
private EvelynMissionControl missionControl;
private NenjimProcessManager processManager;
}
@@ -1,5 +1,7 @@
package com.r35157.nenjim.npm;
public interface NenjimProcessManager {
void start();
import com.r35157.nenjim.process.NenjimProcess;
/** Hub-managed process that presents the runtime's started-process snapshot. */
public interface NenjimProcessManager extends NenjimProcess {
}
@@ -1,31 +1,99 @@
package com.r35157.nenjim.npm.impl.ref;
import com.r35157.libs.javafx.JavaFxRuntime;
import com.r35157.nenjim.hubd.NenjimHub;
import com.r35157.nenjim.npm.NenjimProcessManager;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.stage.Stage;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
public final class NenjimProcessManagerImpl implements NenjimProcessManager {
public NenjimProcessManagerImpl(@NotNull NenjimHub nenjimHub) {
this.nenjimHub = Objects.requireNonNull(nenjimHub, "nenjimHub");
}
@Override
public void start() {
if (!startAttempted.compareAndSet(false, true)) {
throw new IllegalStateException(
"Nenjim Process Manager start has already been attempted");
}
JavaFxRuntime.runLater(this::showWindow);
Thread pollingWorker = new Thread(
this::pollStartedProcesses,
"nenjim-process-manager-poller");
pollingWorker.setDaemon(true);
pollingWorker.start();
}
private void showWindow() {
var processes = new ListView<String>();
processes.getItems().addAll(
"Nenjim Composer",
"Nenjim Process Manager (this)",
"Evelyn Mission Control"
);
processes.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
processList = new ListView<>();
processList.getSelectionModel().setSelectionMode(
SelectionMode.MULTIPLE);
var window = new Stage();
window.setTitle("Nenjim Process Manager");
window.setScene(new Scene(processes, 500, 400));
window.setScene(new Scene(processList, 500, 400));
window.show();
}
private void pollStartedProcesses() {
while (!Thread.currentThread().isInterrupted()) {
publishLatestSnapshot();
try {
Thread.sleep(POLL_INTERVAL);
} catch (InterruptedException interrupted) {
Thread.currentThread().interrupt();
log.info("Nenjim Process Manager polling was interrupted");
return;
}
}
}
private void publishLatestSnapshot() {
try {
List<String> processIds = nenjimHub.getStartedProcessIds()
.stream()
.map(componentId -> componentId.value())
.toList();
JavaFxRuntime.runLater(
() -> replaceDisplayedSnapshot(processIds));
} catch (RuntimeException failure) {
log.error(
"Failed to poll Nenjim Hub started-process snapshot; "
+ "the last displayed snapshot is retained",
failure);
}
}
private void replaceDisplayedSnapshot(List<String> processIds) {
try {
processList.getItems().setAll(processIds);
} catch (RuntimeException failure) {
log.error(
"Failed to display the latest Nenjim Hub "
+ "started-process snapshot",
failure);
}
}
private static final Logger log = LoggerFactory.getLogger(
NenjimProcessManagerImpl.class);
private static final Duration POLL_INTERVAL = Duration.ofSeconds(3);
private final NenjimHub nenjimHub;
private final AtomicBoolean startAttempted = new AtomicBoolean();
private ListView<String> processList;
}