Table of Contents

Class DaemonOrchestrator

Namespace
AppHealthMonitor
Assembly
AppHealthMonitor.dll

Orchestrates the lifecycle of application health monitors. Owns daemon-wide state (cancellation, start signal, active monitors) and pre-validates configurations at construction time.

public sealed class DaemonOrchestrator : IAsyncDisposable
Inheritance
DaemonOrchestrator
Implements
Inherited Members

Constructors

DaemonOrchestrator(IReadOnlyList<AppConfig>, bool)

Initializes a new instance of the DaemonOrchestrator class. Applies defaults, validates, detects duplicate names, creates health checkers, and logs configuration for each app in a single pass.

public DaemonOrchestrator(IReadOnlyList<AppConfig> appConfigs, bool headless)

Parameters

appConfigs IReadOnlyList<AppConfig>

The raw application configurations from settings.

headless bool

Whether all monitored applications should be launched in headless mode.

Exceptions

InvalidOperationException

Thrown when no application configurations are provided, a configuration entry is invalid, or duplicate application names are detected.

Properties

DaemonShutdownToken

Gets the cancellation token that is signalled when the daemon is shutting down. Used by CommandHandler for cancellable I/O operations.

public CancellationToken DaemonShutdownToken { get; }

Property Value

CancellationToken

Headless

Gets whether all monitored applications should be launched in headless mode. Used by CommandHandler to suppress the interactive console prompt.

public bool Headless { get; }

Property Value

bool

HeadlessCycleCompleted

Gets whether the daemon shut down automatically after a headless monitoring cycle completed. When true, all monitors exhausted their restart attempts or failed initial launch, and the daemon should exit with a non-zero exit code to prevent systemd restart loops. Backed by an int field for thread-safe reads via Volatile.

public bool HeadlessCycleCompleted { get; }

Property Value

bool

IsDaemonShutdownRequested

Gets whether the daemon has been signalled to shut down.

public bool IsDaemonShutdownRequested { get; }

Property Value

bool

Methods

CancelCurrentMonitoring()

Thread-safe cancellation of the current monitoring cycle. Uses Read(ref readonly bool) for lock-free access. Safely handles the case where the CTS was disposed by the monitoring cycle's finally block.

public void CancelCurrentMonitoring()

DisposeAsync()

Disposes of orchestrator resources, cleaning up any remaining active monitors, health checkers, and CTS instances.

public ValueTask DisposeAsync()

Returns

ValueTask

A ValueTask representing the asynchronous dispose operation.

ForceKillAllAsync()

Cancels monitoring and force-kills all active monitored processes. Captures the cycle completion source before cancellation to prevent the race where the cycle's finally block nulls it before callers can await it. Returns only after all processes have been terminated. Thread-safe: takes a snapshot of active monitors under lock before killing.

public Task<Task?> ForceKillAllAsync()

Returns

Task<Task>

The captured cycle completion task (if a cycle was active), or null.

GetActiveMonitorStatuses()

Returns a thread-safe snapshot of active monitor statuses for diagnostics. Takes a snapshot of the monitors list under lock, then queries status outside the lock to avoid holding the lock during process I/O (e.g., /proc reads on Linux).

public IReadOnlyList<HealthMonitorStatus> GetActiveMonitorStatuses()

Returns

IReadOnlyList<HealthMonitorStatus>

A read-only list of HealthMonitorStatus snapshots.

IsMonitoringActive()

Checks whether monitoring is currently active and not cancelled. Uses Read(ref readonly bool) for lock-free thread safety on the CTS reference.

public bool IsMonitoringActive()

Returns

bool

True if monitoring is active and not cancelled; otherwise, false.

RunAsync()

Runs the main orchestration loop. Waits for start signals, launches monitors, and handles stop/shutdown. Returns when the daemon token is cancelled. In headless mode, automatically initiates daemon shutdown after the monitoring cycle completes, since no interactive console is available to issue further commands.

public Task RunAsync()

Returns

Task

A task representing the asynchronous orchestration operation.

Shutdown()

Signals the daemon to shut down by cancelling monitoring and the daemon-wide token. CancelCurrentMonitoring() is called defensively before AppHealthMonitor.DaemonOrchestrator.daemonCts. The linked CTS in RunAsync() ensures propagation either way.

public void Shutdown()

TrySignalStart()

Attempts to release the start signal semaphore to trigger a new monitoring cycle. Safely handles the case where the semaphore is already at its maximum count.

public bool TrySignalStart()

Returns

bool

True if the signal was released; false if it was already signalled.

WaitForCycleCompletionAsync(Task?)

Waits for monitoring cycle cleanup to finish with a bounded timeout.

public Task WaitForCycleCompletionAsync(Task? cycleCompletion)

Parameters

cycleCompletion Task

The cycle completion task captured from ForceKillAllAsync().

Returns

Task

A task representing the wait operation.