DaemonModule
DaemonModule is the per-node sibling of
PlatformModule. It runs
inside the daemon process on every node where the module is installed,
participates in instance-lifecycle hooks, and observes the local node’s
capability registry. Daemon modules have no Mongo storage; their
ModuleContext.findMongoStorage() returns empty.
What you’ll learn
- The four module-lifecycle hooks plus four instance-lifecycle hooks.
- How to mutate a launch spec from
onInstanceStarting. - How daemon modules pair with platform modules in a dual-host module.
API surface
The interface lives at
me.prexorjustin.prexorcloud.api.module.platform.DaemonModule.
Module lifecycle
default void onLoad(ModuleContext context) throws Exceptiondefault void onStart(ModuleContext context) throws Exceptiondefault void onStop(ModuleContext context) throws Exceptiondefault void onUnload(ModuleContext context) throws Exceptiondefault void onUpgrade(ModuleContext context) throws ExceptionIdentical semantics to PlatformModule, but executed inside the daemon
JVM. The daemon receives the module artifact over its gRPC stream
(ModuleInstall); the host classloads it and drives these hooks.
Instance lifecycle
onInstanceStarting
default void onInstanceStarting(InstanceSpec spec) throws ExceptionPre-launch hook for an instance about to start on this node. You may
mutate spec.jvmArgs() or spec.env() to inject flags or environment
variables; mutations are observed by the daemon when it builds the
launch command. Throwing aborts the start with an error report.
onInstanceStarted
default void onInstanceStarted(InstanceHandle handle) throws ExceptionFired after the instance process is spawned and the daemon has a PID.
onInstanceStopping
default void onInstanceStopping(InstanceHandle handle) throws ExceptionFired before the daemon stops the instance process (graceful or forced).
onInstanceStopped
default void onInstanceStopped(InstanceHandle handle, ExitInfo exit) throws ExceptionFired after the instance process has exited (clean or crashed).
ExitInfo carries the exit code, classification, and whether this was
a crash vs. a managed stop.
capabilityHandles
default List<CapabilityHandle<?>> capabilityHandles()Same contract as PlatformModule, but the binding is node-local —
cross-node visibility is out of scope for v1.
Misbehaviour contract
Each instance-lifecycle hook is wrapped by the daemon with a try-catch
- SLF4J
WARN. A misbehaving module cannot wedge the daemon: throwing fromonInstanceStarted/onInstanceStopping/onInstanceStoppedis logged and ignored.onInstanceStartingis the one exception — since it’s a pre-launch gate, throwing there aborts the launch.
Example
A daemon module that injects a -javaagent: flag into every starting
instance:
package com.example.agent;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import me.prexorjustin.prexorcloud.api.module.platform.DaemonModule;import me.prexorjustin.prexorcloud.api.module.platform.InstanceSpec;import me.prexorjustin.prexorcloud.api.module.platform.ModuleContext;
public final class AgentInjectorModule implements DaemonModule {
private static final Logger LOG = LoggerFactory.getLogger(AgentInjectorModule.class);
private String agentPath;
@Override public void onLoad(ModuleContext context) { this.agentPath = context.findRedisStorage() .flatMap(r -> r.get("agent.path")) .orElse("/opt/prexor/agents/observer.jar"); }
@Override public void onInstanceStarting(InstanceSpec spec) { spec.jvmArgs().add("-javaagent:" + agentPath); LOG.info("attached agent to {}", spec.instanceId()); }}Dual-host modules
A module that needs both controller- and daemon-side behaviour
declares hosts: [controller, daemon] in its manifest and ships:
- a
PlatformModuleasbackend.controller.entrypoint - a
DaemonModuleasbackend.daemon.entrypoint
The two halves do not share heap state; they communicate through the controller-bus events forwarded to the daemon (subscribe-registration model — see Layer 7 in the engineering docs).
Next up
- PlatformModule — sibling contract.
- ModuleContext — what’s available inside a daemon-module hook.
- Concepts → Daemon modules