7using System.Threading.Tasks;
9using Microsoft.Extensions.Logging;
24 readonly ILogger<ServiceLifetime>
logger;
53 public ServiceLifetime(Action stopService, Func<ISignalChecker, IWatchdog> watchdogFactory, ILogger<ServiceLifetime>
logger,
string[] args)
55 ArgumentNullException.ThrowIfNull(stopService);
56 ArgumentNullException.ThrowIfNull(watchdogFactory);
57 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
58 ArgumentNullException.ThrowIfNull(args);
60 logger.LogDebug(
"Starting service lifetime as user: {username}", Environment.UserName);
65 watchdogFactory(
this),
85 public async ValueTask
CheckSignals(Func<
string, (
int, Task)> startChildAndGetPid, CancellationToken cancellationToken)
89 await
using (
commandPipeServer =
new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable))
90 await
using (
readyPipeServer =
new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
92 var (_, lifetimeTask) = startChildAndGetPid($
"--Internal:CommandPipe={commandPipeServer.GetClientHandleAsString()} --Internal:ReadyPipe={readyPipeServer.GetClientHandleAsString()}");
112 foreach (var stringCommand
in commandsToCheck)
115 if (command == commandId)
122 logger.LogWarning(
"Received unknown service command: {command}", command);
133 async Task
RunWatchdog(Action stopService,
IWatchdog watchdog,
string[] args, CancellationToken cancellationToken)
135 var localWatchdogTask = watchdog.
RunAsync(
false, args, cancellationToken);
137 if (!localWatchdogTask.IsCompleted && (await watchdog.
InitialHostVersion) >=
new Version(5, 14, 0))
140 logger.LogInformation(
"Waiting for host to finish starting...");
141 using var streamReader =
new StreamReader(
146 var line = streamReader.ReadLine();
147 logger.LogDebug(
"Pipe read: {line}", line);
153 logger.LogError(
"Watchdog started and ready pipe was not initialized!");
155 await localWatchdogTask;
157 async
void StopServiceAsync()
162 await Task.Run(stopService, cancellationToken);
164 catch (OperationCanceledException ex)
166 logger.LogDebug(ex,
"Stopping service cancelled!");
170 logger.LogError(ex,
"Error stopping service!");
184 if (localPipeServer ==
null)
186 logger.LogWarning(
"Unable to send command \"{command}\" to main server process. Is the service running?", command);
190 logger.LogDebug(
"Send command: {command}", command);
193 var encoding = Encoding.UTF8;
194 using var streamWriter =
new StreamWriter(
200 command => encoding.GetByteCount(
201 command + Environment.NewLine))
204 streamWriter.WriteLine(command);
208 logger.LogError(ex,
"Error attempting to send command \"{command}\"", command);
Values able to be passed via the update file path.
static ? int GetServiceCommandId(string command)
Gets the int value of a given command .
Represents the lifetime of the service.
readonly CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the ServerService.
AnonymousPipeServerStream? readyPipeServer
The AnonymousPipeServerStream for receiving the PipeCommands.CommandStartupComplete.
void HandleCustomCommand(int command)
Handle a custom service command .
readonly ILogger< ServiceLifetime > logger
The ILogger for the ServerService.
async ValueTask DisposeAsync()
ServiceLifetime(Action stopService, Func< ISignalChecker, IWatchdog > watchdogFactory, ILogger< ServiceLifetime > logger, string[] args)
Initializes a new instance of the ServiceLifetime class.
void SendCommandToHostThroughPipe(string command)
Sends a command to the main server process.
async ValueTask CheckSignals(Func< string,(int, Task)> startChildAndGetPid, CancellationToken cancellationToken)
async Task RunWatchdog(Action stopService, IWatchdog watchdog, string[] args, CancellationToken cancellationToken)
Executes the watchdog , stopping the service if it exits.
readonly Task watchdogTask
The Task that represents the running ServerService.
AnonymousPipeServerStream? commandPipeServer
The AnonymousPipeServerStream for sending PipeCommands to the server process.
For relaying signals received to the host process.
ValueTask< bool > RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
Run the IWatchdog.
Task< Version > InitialHostVersion
Gets a Task<TResult> resulting in the current version of the host process. Guaranteed to complete onc...