34#pragma warning disable CA1506
262 Logger.LogTrace(
"Created watchdog");
268 Logger.LogTrace(
"Disposing...");
311 Text =
"TGS: Server offline!",
319 Text =
"TGS: Bad topic exchange!",
325 Text =
"TGS: Bad topic response!",
373 Logger.LogTrace(
"Begin Restart. Graceful: {gracefulFlag}",
graceful);
387 Logger.LogWarning(
"Unable to send reboot state change event!");
399 var job = Models.Job.Create(
401 ?
JobCode.StartupWatchdogReattach
402 :
JobCode.StartupWatchdogLaunch,
410 if (
core?.Watchdog !=
this)
441 Logger.LogDebug(
"Waiting for server to gracefully shut down.");
445 Logger.LogTrace(
"Graceful shutdown requested but server is already offline.");
454 Logger.LogTrace(
"Not sending detach chat message as status is: {status}",
Status);
475 Logger.LogInformation(
"Attempted broadcast failed, no active server!");
481 Logger.LogInformation(
"Attempted broadcast failed, no DMAPI!");
489 "Attempted broadcast failed, insufficient interop version: {interopVersion}. Requires {minimumRequiredVersion}!",
553 Logger.LogTrace(
"Begin LaunchImplNoLock");
583 Logger.LogTrace(
ex,
"Controller initialization cancelled!");
588 Logger.LogWarning(
e,
"Failed to start watchdog!");
609 Logger.LogTrace(
ex,
"Announcement task canceled!");
613 Logger.LogInformation(
"Controller(s) initialized successfully");
628 Logger.LogTrace(
"StopMonitor");
634 Logger.LogTrace(
"Stopped Monitor");
656 new JobException(
$"{serverName} failed to start: {launchResult}"));
660 new JobException(
$"{serverName} timed out on startup: {ActiveLaunchParameters.StartupTimeout!.Value}s"));
674 const string FailReattachMessage =
"Unable to properly reattach to server! Restarting watchdog...";
694 Logger.LogTrace(
"DisposeAndNullControllers");
729 Logger.LogTrace(
"Same compile job, not sending deployment event");
741 GameIOManager.ResolvePath(newCompileJob.DirectoryName!.Value.ToString()),
752 Logger.LogWarning(
ex,
"Failed to apply remote deployment!");
778 Logger.LogError(
ex,
"Suppressing exception triggered by event!");
789 Logger.LogTrace(
"Monitor restart!");
803 Logger.LogDebug(
"Relaunch successful, resuming monitor...");
817 TimeSpan.FromHours(1).TotalSeconds);
820 $"Failed to restart (Attempt: {retryAttempts}), retrying in {retryDelay}s...");
840 Logger.LogDebug(
"Found new CompileJob without waiting");
852#pragma warning disable CA1502
855 Logger.LogTrace(
"Entered MonitorLifetimes");
944 Logger.LogError(
"Controller was null on monitor wakeup! Attempting restart...");
949 Logger.LogTrace(
"Monitor activated");
1019 "Monitor crashed! Iteration: {iteration}",
1026 $"Monitor crashed, this should NEVER happen! Please report this, full details in logs! {nextActionMessage}. Error: {e.Message}");
1035 Logger.LogDebug(
"Server seems to be okay, not restarting");
1048 Logger.LogDebug(
"Monitor cancelled");
1052 Logger.LogTrace(
"Detaching server...");
1057 Logger.LogError(
"Controller was null on monitor shutdown!");
1065 Logger.LogTrace(
"Monitor exiting...");
1067#pragma warning restore CA1502
1106 Logger.LogTrace(
"Graceful termination requested");
1109 Logger.LogTrace(
"Could not gracefully terminate as there is no active controller!");
1119 Logger.LogTrace(
"Sending health check to active server...");
1132 Logger.LogDebug(
"DEFCON 4: Game server missed first health check!");
1135 const string message2 =
"DEFCON 3: Game server has missed 2 health checks!";
1143 const string logTemplate1 =
"DEFCON 2: Game server has missed 3 health checks! If it does not respond to the next one, the watchdog will {actionToTake}!";
1153 ?
"Shutting down due to graceful termination request"
1155 const string logTemplate2 =
"DEFCON 1: Four health checks have been missed! {actionTaken}...";
1165 Logger.LogDebug(
"DumpOnHealthCheckRestart enabled.");
1172 Logger.LogWarning(
ex,
"Creating dump failed!");
1176 Logger.LogWarning(
ex,
"Creating dump failed!");
1180 Logger.LogTrace(
"DumpOnHealthCheckRestart disabled.");
1204 if (
result?.ChatResponses !=
null)
1210 if (response.ChannelIds == null)
1212 if (!warnedMissingChannelIds)
1214 Logger.LogWarning(
"DMAPI response contains null channelIds!");
1215 warnedMissingChannelIds = true;
1250 if (
session?.Lifetime.IsCompleted !=
false)
1256 diagnosticsIOManager.ConcatPath(
1258 $"DreamDaemon-{DateTimeOffset.UtcNow.ToFileStamp()}"));
1263 dumpFileName =
$"{dumpFileNameTemplate} ({++iteration}){dumpFileExtension}";
1268 if (
session.Lifetime.IsCompleted)
1271 Logger.LogInformation(
"Dumping session to {dumpFileName}...",
dumpFileName);
EngineType? Engine
The EngineType.
virtual ? long Id
The ID of the entity.
Metadata about a server instance.
Represents a deployment run.
Launch settings for DreamDaemon.
uint? HealthCheckSeconds
The number of seconds between each watchdog health check. 0 disables.
bool? DumpOnHealthCheckRestart
If a process core dump should be created prior to restarting the watchdog due to health check failure...
Extension methods for the ValueTask and ValueTask<TResult> classes.
static async ValueTask WhenAll(IEnumerable< ValueTask > tasks)
Fully await a given list of tasks .
Represents a tgs_chat_user datum.
bool DmbAvailable
If LockNextDmb will succeed.
Task OnNewerDmb
Get a Task that completes when the result of a call to LockNextDmb will be different than the previou...
async ValueTask< CompileJob?> LatestCompileJob()
Gets the latest CompileJob.A ValueTask<TResult> resulting in the latest CompileJob or null if none ar...
const string DifferentCoreExceptionMessage
Message for the InvalidOperationException if ever a job starts on a different IInstanceCore than the ...
Represents a message to send to a chat provider.
string? Text
The message string.
Represents a chat command to be handled by DD.
Data structure for TopicCommandType.EventNotification requests.
Parameters for a topic request.
static TopicParameters CreateBroadcastParameters(string broadcastMessage)
Initializes a new instance of the TopicParameters class.
A response to a topic request.
async ValueTask< ReattachInformation?> Load(CancellationToken cancellationToken)
Load a saved ReattachInformation.A ValueTask<TResult> resulting in the stored ReattachInformation if ...
ValueTask Clear(CancellationToken cancellationToken)
Clear any stored ReattachInformation.A ValueTask representing the running operation.
Base class for IWatchdogs.
async ValueTask HandleRestart(Version? updateVersion, bool handlerMayDelayShutdownWithExtremelyLongRunningTasks, CancellationToken cancellationToken)
Handle a restart of the server.A ValueTask representing the running operation.
async ValueTask< bool > Broadcast(string message, CancellationToken cancellationToken)
Send a broadcast message to the DMAPI.A ValueTask<TResult> resulting in true if the broadcast succee...
async ValueTask< MonitorAction > HandleHealthCheck(CancellationToken cancellationToken)
Handles a watchdog health check.
ISessionController? GetActiveController()
Get the active ISessionController.
readonly IJobManager jobManager
The IJobManager for the WatchdogBase.
WatchdogBase(IChatManager chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, ISessionPersistor sessionPersistor, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, IIOManager diagnosticsIOManager, IEventConsumer eventConsumer, IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory, IIOManager gameIOManager, ILogger< WatchdogBase > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance metadata, bool autoStart)
Initializes a new instance of the WatchdogBase class.
ILogger< WatchdogBase > Logger
The ILogger for the WatchdogBase.
bool releaseServers
If the servers should be released instead of shutdown.
async ValueTask ReattachFailure(CancellationToken cancellationToken)
Call from InitController(ValueTask, ReattachInformation, CancellationToken) when a reattach operation...
async ValueTask CreateDumpNoLock(CancellationToken cancellationToken)
Attempt to create a process dump for the game server. Requires a lock on synchronizationSemaphore.
Models.? CompileJob ActiveCompileJob
Retrieves the Models.CompileJob currently running on the server.
DreamDaemonLaunchParameters? LastLaunchParameters
The DreamDaemonLaunchParameters the active server is using.This may not be the exact same as ActiveLa...
DateTimeOffset? LaunchTime
When the current server executions was started.
readonly bool autoStart
If the WatchdogBase should LaunchNoLock(bool, bool, bool, ReattachInformation, CancellationToken) in ...
async ValueTask Terminate(bool graceful, CancellationToken cancellationToken)
Stops the watchdog.A ValueTask representing the running operation.
async ValueTask CheckLaunchResult(ISessionController controller, string serverName, CancellationToken cancellationToken)
Check the LaunchResult of a given controller for errors and throw a JobException if any are detected...
readonly Api.Models.Instance metadata
The Api.Models.Instance for the WatchdogBase.
bool AlphaIsActive
If the alpha server is the active server.
readonly IEventConsumer eventConsumer
The IEventConsumer that is not the WatchdogBase.
bool disposed
If the WatchdogBase has been DisposeAsync'd.
readonly SemaphoreSlim controllerDisposeSemaphore
SemaphoreSlim used for DisposeAndNullControllers.
WatchdogStatus Status
The current WatchdogStatus.
ValueTask< MonitorAction > HandleMonitorWakeup(MonitorActivationReason activationReason, CancellationToken cancellationToken)
Handles the actions to take when the monitor has to "wake up".
CancellationTokenSource? monitorCts
The CancellationTokenSource for the monitor loop.
Task? monitorTask
The Task running the monitor loop.
async ValueTask DisposeAsync()
readonly IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory
The IRemoteDeploymentManagerFactory for the WatchdogBase.
readonly SemaphoreSlim synchronizationSemaphore
The SemaphoreSlim for the WatchdogBase.
async ValueTask Restart(bool graceful, CancellationToken cancellationToken)
Restarts the watchdog.A ValueTask representing the running operation.
long? MemoryUsage
Gets the memory usage of the game server in bytes.
readonly IIOManager diagnosticsIOManager
The IIOManager pointing to the Diagnostics directory.
async ValueTask< MessageContent > HandleChatCommand(string commandName, string arguments, ChatUser sender, CancellationToken cancellationToken)
Handle a chat command.A ValueTask<TResult> resulting in the MessageContent text to send back.
ValueTask InitController(ValueTask eventTask, ReattachInformation? reattachInfo, CancellationToken cancellationToken)
Starts all ISessionControllers.
async ValueTask CreateDump(CancellationToken cancellationToken)
Attempt to create a process dump for DreamDaemon.A ValueTask representing the running operation.
IIOManager GameIOManager
The IIOManager for the WatchdogBase pointing to the Game directory.
DreamDaemonLaunchParameters ActiveLaunchParameters
The DreamDaemonLaunchParameters to be applied.
uint? ClientCount
Last known client count queried from the DMAPI. Requires health checks to be enabled to populate.
async ValueTask BeforeApplyDmb(Models.CompileJob newCompileJob, CancellationToken cancellationToken)
To be called before a given newCompileJob goes live.
async ValueTask< bool > StopMonitor()
Stops MonitorLifetimes(CancellationToken). Doesn't kill the servers.
async ValueTask MonitorRestart(CancellationToken cancellationToken)
Attempt to restart the monitor from scratch.
async ValueTask Launch(CancellationToken cancellationToken)
Start the IWatchdog.A ValueTask representing the running operation.
async Task InitialCheckDmbUpdated(CompileJob currentCompileJob)
Check for a new IDmbProvider.
async ValueTask LaunchNoLock(bool startMonitor, bool announce, bool announceFailure, ReattachInformation? reattachInfo, CancellationToken cancellationToken)
Launches the watchdog.
async ValueTask DisposeAndNullControllers(CancellationToken cancellationToken)
Wrapper for DisposeAndNullControllersImpl under a locked context.
ValueTask DisposeAndNullControllersImpl()
Call IDisposable.Dispose and null the fields for all ISessionControllers.
async ValueTask TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
Implementation of Terminate(bool, CancellationToken). Does not lock synchronizationSemaphore.
async ValueTask< bool > ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
Changes the ActiveLaunchParameters. If currently running, may trigger a graceful restart....
void HandleChatResponses(TopicResponse? result)
Handle any TopicResponse.ChatResponses in a given topic result .
virtual async ValueTask ResetRebootState(CancellationToken cancellationToken)
Cancels pending graceful actions.A ValueTask representing the running operation.
async Task MonitorLifetimes(CancellationToken cancellationToken)
The main loop of the watchdog. Ayschronously waits for events to occur and then responds to them.
long? SessionId
An incrementing ID for representing current server execution.
async Task StartAsync(CancellationToken cancellationToken)
ValueTask InstanceRenamed(string newInstanceName, CancellationToken cancellationToken)
Called when the owning Instance is renamed.A ValueTask representing the running operation.
int healthChecksMissed
The number of hearbeats missed.
IChatManager Chat
The IChatManager for the WatchdogBase.
async Task StopAsync(CancellationToken cancellationToken)
readonly IRestartRegistration restartRegistration
The IRestartRegistration for the WatchdogBase.
async ValueTask HandleEventImpl(EventType eventType, IEnumerable< string > parameters, bool relayToSession, CancellationToken cancellationToken)
Handle a given eventType without re-throwing errors.
WatchdogStatus status
Backing field for Status.
volatile TaskCompletionSource activeParametersUpdated
TaskCompletionSource that completes when ActiveLaunchParameters are changed and we are running.
Operation exceptions thrown from the context of a Models.Job.
async ValueTask Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan .A ValueTask representing the running operation.
Async lock context helper.
static async ValueTask< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken, ILogger? logger=null)
Asyncronously locks a semaphore .
Helpers for manipulating the Serilog.Context.LogContext.
const string WatchdogMonitorIterationContextProperty
The Serilog.Context.LogContext property name for the ID of the watchdog monitor iteration currently b...
For managing connected chat services.
void QueueWatchdogMessage(string message)
Queue a chat message to configured watchdog channels.
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use.
ValueTask UpdateTrackingContexts(CancellationToken cancellationToken)
Force an update with the active channels on all active IChatTrackingContexts.
void QueueMessage(MessageContent message, IEnumerable< ulong > channelIds)
Queue a chat message to a given set of channelIds .
Handles Commands.ICommands that map to those defined in a IChatTrackingContext.
Factory for IDmbProviders.
Factory for creating IRemoteDeploymentManagers.
IRemoteDeploymentManager CreateRemoteDeploymentManager(Api.Models.Instance metadata, RemoteGitProvider remoteGitProvider)
Creates a IRemoteDeploymentManager for a given remoteGitProvider .
Consumes EventTypes and takes the appropriate actions.
ValueTask? HandleCustomEvent(string eventName, IEnumerable< string?> parameters, CancellationToken cancellationToken)
Handles a given custom event.
ValueTask HandleEvent(EventType eventType, IEnumerable< string?> parameters, bool deploymentPipeline, CancellationToken cancellationToken)
Handle a given eventType .
Factory for ISessionControllers.
Handles communication with a DreamDaemon IProcess.
Models.CompileJob CompileJob
Gets the CompileJob associated with the ISessionController.
ReattachInformation ReattachInformation
Gets the Session.ReattachInformation associated with the ISessionController.
EngineVersion EngineVersion
Gets the Api.Models.EngineVersion associated with the ISessionController.
Handles saving and loading ReattachInformation.
Runs and monitors the twin server controllers.
Handler for server restarts.
Represents the lifetime of a IRestartHandler registration.
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart.
Interface for using filesystems.
Manages the runtime of Jobs.
ValueTask RegisterOperation(Job job, JobEntrypoint operation, CancellationToken cancellationToken)
Registers a given Job and begins running it.
long? MemoryUsage
Gets the process' memory usage in bytes.
DateTimeOffset? LaunchTime
When the process was started.
For waiting asynchronously.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
JobCode
The different types of Response.JobResponse.
WatchdogStatus
The current status of the watchdog.
@ List
User may list files if the Models.Instance allows it.
DreamDaemonRights
Rights for managing DreamDaemon.
EventType
Types of events. Mirror in tgs.dm. Prefer last listed name for script.
RebootState
Represents the action to take when /world/Reboot() is called.
MonitorAction
The action for the monitor loop to take when control is returned to it.
MonitorActivationReason
Reasons for the monitor to wake up.