diff --git a/README.md b/README.md index 91f5ec9a98..8cf7ac1589 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ docker run \ --restart=always \ # Recommended for maximum uptime --network="host" \ # Not recommended, eases networking setup if your sql server is on the same machine --name="tgs" \ # Name for the container - --cap-add=sys_nice \ # Recommended, allows tgs to schedule DreamDaemon as a higher priority process + --cap-add=sys_nice \ # Recommended, allows TGS to lower the niceness of child processes if it sees fit --init \ #Highly recommended, reaps potential zombie processes -p 5000:5000 \ # Port bridge for accessing TGS, you can change this if you need -p 0.0.0.0:: \ # Port bridge for accessing DreamDaemon @@ -119,6 +119,10 @@ Create an `appsettings.Production.yml` file next to `appsettings.yml`. This will - `General:GitHubAccessToken`: Specify a GitHub personal access token with no scopes here to highly mitigate the possiblity of 429 response codes from GitHub requests +- `Session:HighPriorityLiveDreamDaemon`: Boolean controlling if live DreamDaemon instances get set to above normal priority processes. + +- `Session:LowPriorityDeploymentProcesses `: Boolean controlling if DreamMaker and API validation DreamDaemon instances get set to below normal priority processes. + - `FileLogging:Directory`: Override the default directory where server logs are stored. Default is C:/ProgramData/tgstation-server/logs on Windows, /usr/share/tgstation-server/logs otherwise - `FileLogging:LogLevel`: Can be one of `Trace`, `Debug`, `Information`, `Warning`, `Error`, or `Critical`. Restricts what is put into the log files. Currently `Debug` is reccommended for help with error reporting. diff --git a/build/Version.props b/build/Version.props index 7c296967f1..014fb98062 100644 --- a/build/Version.props +++ b/build/Version.props @@ -4,7 +4,7 @@ 4.15.6 - 4.0.0 + 4.1.0 9.3.0 9.3.1 10.4.1 diff --git a/src/Tgstation.Server.Host/.config/dotnet-tools.json b/src/Tgstation.Server.Host/.config/dotnet-tools.json index 0e67acb789..071984940d 100644 --- a/src/Tgstation.Server.Host/.config/dotnet-tools.json +++ b/src/Tgstation.Server.Host/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-ef": { - "version": "3.1.18", + "version": "3.1.20", "commands": [ "dotnet-ef" ] diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index 790dee9cc9..f0fa62e021 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -16,6 +16,7 @@ using Tgstation.Server.Host.Components.Deployment.Remote; using Tgstation.Server.Host.Components.Events; using Tgstation.Server.Host.Components.Repository; using Tgstation.Server.Host.Components.Session; +using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Database; using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.IO; @@ -93,6 +94,11 @@ namespace Tgstation.Server.Host.Components.Deployment /// readonly ILogger logger; + /// + /// The for . + /// + readonly SessionConfiguration sessionConfiguration; + /// /// The belongs to. /// @@ -147,6 +153,7 @@ namespace Tgstation.Server.Host.Components.Deployment /// The value of . /// The value of . /// The value of . + /// The value of . /// The value of . public DreamMaker( IByondManager byond, @@ -160,6 +167,7 @@ namespace Tgstation.Server.Host.Components.Deployment IRepositoryManager repositoryManager, IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory, ILogger logger, + SessionConfiguration sessionConfiguration, Api.Models.Instance metadata) { this.byond = byond ?? throw new ArgumentNullException(nameof(byond)); @@ -173,6 +181,7 @@ namespace Tgstation.Server.Host.Components.Deployment this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager)); this.remoteDeploymentManagerFactory = remoteDeploymentManagerFactory ?? throw new ArgumentNullException(nameof(remoteDeploymentManagerFactory)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); + this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); deploymentLock = new object(); @@ -762,6 +771,8 @@ namespace Tgstation.Server.Host.Components.Deployment using (var provider = new TemporaryDmbProvider(ioManager.ResolvePath(job.DirectoryName.ToString()), String.Concat(job.DmeName, DmbExtension), job)) await using (var controller = await sessionControllerFactory.LaunchNew(provider, byondLock, launchParameters, true, cancellationToken).ConfigureAwait(false)) { + controller.AdjustPriority(false); + var launchResult = await controller.LaunchResult.ConfigureAwait(false); if (launchResult.StartupTime.HasValue) @@ -823,6 +834,10 @@ namespace Tgstation.Server.Host.Components.Deployment true, true, true); + + if (sessionConfiguration.LowPriorityDeploymentProcesses) + dm.AdjustPriority(false); + int exitCode; using (cancellationToken.Register(() => dm.Terminate())) exitCode = await dm.Lifetime.ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index 32f05929c7..9bf0652924 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -144,6 +144,12 @@ namespace Tgstation.Server.Host.Components /// readonly GeneralConfiguration generalConfiguration; + /// + /// The for the . + /// + readonly SessionConfiguration sessionConfiguration; + +#pragma warning disable CA1502 // TODO: Decomplexify /// /// Initializes a new instance of the class. /// @@ -170,6 +176,7 @@ namespace Tgstation.Server.Host.Components /// The value of . /// The value of . /// The containing the value of . + /// The containing the value of . public InstanceFactory( IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, @@ -193,7 +200,8 @@ namespace Tgstation.Server.Host.Components IFileTransferTicketProvider fileTransferService, IGitRemoteFeaturesFactory gitRemoteFeaturesFactory, IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory, - IOptions generalConfigurationOptions) + IOptions generalConfigurationOptions, + IOptions sessionConfigurationOptions) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); @@ -218,7 +226,9 @@ namespace Tgstation.Server.Host.Components this.gitRemoteFeaturesFactory = gitRemoteFeaturesFactory ?? throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory)); this.remoteDeploymentManagerFactory = remoteDeploymentManagerFactory ?? throw new ArgumentNullException(nameof(remoteDeploymentManagerFactory)); generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); + sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions)); } +#pragma warning restore CA1502 /// #pragma warning disable CA1506 // TODO: Decomplexify @@ -276,6 +286,7 @@ namespace Tgstation.Server.Host.Components eventConsumer, loggerFactory, loggerFactory.CreateLogger(), + sessionConfiguration, metadata); var dmbFactory = new DmbFactory( @@ -320,6 +331,7 @@ namespace Tgstation.Server.Host.Components repoManager, remoteDeploymentManagerFactory, loggerFactory.CreateLogger(), + sessionConfiguration, metadata); instance = new Instance( diff --git a/src/Tgstation.Server.Host/Components/Session/SessionController.cs b/src/Tgstation.Server.Host/Components/Session/SessionController.cs index 74feee1f9d..91285f0ee8 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionController.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionController.cs @@ -590,7 +590,7 @@ namespace Tgstation.Server.Host.Components.Session } /// - public void SetHighPriority() => process.SetHighPriority(); + public void AdjustPriority(bool higher) => process.AdjustPriority(higher); /// public void Suspend() => process.Suspend(); diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs index 7c5f331a04..9e10b71cb5 100644 --- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs +++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs @@ -17,6 +17,7 @@ using Tgstation.Server.Host.Components.Deployment; using Tgstation.Server.Host.Components.Events; using Tgstation.Server.Host.Components.Interop; using Tgstation.Server.Host.Components.Interop.Bridge; +using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Core; using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.IO; @@ -99,6 +100,11 @@ namespace Tgstation.Server.Host.Components.Session /// readonly ILogger logger; + /// + /// The for the . + /// + readonly SessionConfiguration sessionConfiguration; + /// /// The for the . /// @@ -170,7 +176,8 @@ namespace Tgstation.Server.Host.Components.Session /// The value of . /// The value of . /// The value of . - /// The value of . + /// The value of . + /// The value of . public SessionControllerFactory( IProcessExecutor processExecutor, IByondManager byond, @@ -183,9 +190,10 @@ namespace Tgstation.Server.Host.Components.Session IPlatformIdentifier platformIdentifier, IBridgeRegistrar bridgeRegistrar, IServerPortProvider serverPortProvider, - EventConsumer eventConsumer, + IEventConsumer eventConsumer, ILoggerFactory loggerFactory, ILogger logger, + SessionConfiguration sessionConfiguration, Api.Models.Instance instance) { this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); @@ -193,7 +201,6 @@ namespace Tgstation.Server.Host.Components.Session this.topicClientFactory = topicClientFactory ?? throw new ArgumentNullException(nameof(topicClientFactory)); this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite)); this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); - this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.chat = chat ?? throw new ArgumentNullException(nameof(chat)); this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper)); @@ -203,6 +210,8 @@ namespace Tgstation.Server.Host.Components.Session this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer)); this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); + this.sessionConfiguration = sessionConfiguration ?? throw new ArgumentNullException(nameof(sessionConfiguration)); + this.instance = instance ?? throw new ArgumentNullException(nameof(instance)); } /// @@ -380,6 +389,14 @@ namespace Tgstation.Server.Host.Components.Session false, apiValidate); + if (apiValidate) + { + if (sessionConfiguration.HighPriorityLiveDreamDaemon) + process.AdjustPriority(true); + } + else if (sessionConfiguration.LowPriorityDeploymentProcesses) + process.AdjustPriority(false); + // If this isnt a staging DD (From a Deployment), fire off an event if (!apiValidate) await eventConsumer.HandleEvent( diff --git a/src/Tgstation.Server.Host/Components/Watchdog/BasicWatchdog.cs b/src/Tgstation.Server.Host/Components/Watchdog/BasicWatchdog.cs index f62bc2d2c8..903b063d05 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/BasicWatchdog.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/BasicWatchdog.cs @@ -247,8 +247,7 @@ namespace Tgstation.Server.Host.Components.Watchdog return; } - Server.SetHighPriority(); - + // Server.AdjustPriority(true); if (!reattachInProgress) await SessionPersistor.Save(Server.ReattachInformation, cancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Configuration/SessionConfiguration.cs b/src/Tgstation.Server.Host/Configuration/SessionConfiguration.cs new file mode 100644 index 0000000000..86641b8944 --- /dev/null +++ b/src/Tgstation.Server.Host/Configuration/SessionConfiguration.cs @@ -0,0 +1,28 @@ +namespace Tgstation.Server.Host.Configuration +{ + /// + /// Configuration options for the game sessions. + /// + sealed class SessionConfiguration + { + /// + /// The key for the the resides in. + /// + public const string Section = "Session"; + + /// + /// The default value for . + /// + private const bool DefaultHighPriorityLiveDreamDaemon = true; + + /// + /// If the public DreamDaemon instances are set to be above normal priority processes. + /// + public bool HighPriorityLiveDreamDaemon { get; set; } = DefaultHighPriorityLiveDreamDaemon; + + /// + /// If the deployment DreamMaker and DreamDaemon instances are set to be below normal priority processes. + /// + public bool LowPriorityDeploymentProcesses { get; set; } + } +} diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index f79766ff24..30764018f4 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -120,6 +120,7 @@ namespace Tgstation.Server.Host.Core services.UseStandardConfig(Configuration); services.UseStandardConfig(Configuration); services.UseStandardConfig(Configuration); + services.UseStandardConfig(Configuration); // enable options which give us config reloading services.AddOptions(); diff --git a/src/Tgstation.Server.Host/System/IProcessBase.cs b/src/Tgstation.Server.Host/System/IProcessBase.cs index a38df065d3..612c86447b 100644 --- a/src/Tgstation.Server.Host/System/IProcessBase.cs +++ b/src/Tgstation.Server.Host/System/IProcessBase.cs @@ -14,9 +14,10 @@ namespace Tgstation.Server.Host.System Task Lifetime { get; } /// - /// Set's the owned to . + /// Set's the owned to a non-normal value. /// - void SetHighPriority(); + /// If will be set to otherwise, will be set to . + void AdjustPriority(bool higher); /// /// Suspends the process. diff --git a/src/Tgstation.Server.Host/System/Process.cs b/src/Tgstation.Server.Host/System/Process.cs index 2ff8ccf1b4..e2820b5484 100644 --- a/src/Tgstation.Server.Host/System/Process.cs +++ b/src/Tgstation.Server.Host/System/Process.cs @@ -184,16 +184,17 @@ namespace Tgstation.Server.Host.System } /// - public void SetHighPriority() + public void AdjustPriority(bool higher) { + var targetPriority = higher ? ProcessPriorityClass.AboveNormal : ProcessPriorityClass.BelowNormal; try { - handle.PriorityClass = ProcessPriorityClass.AboveNormal; - logger.LogTrace("Set PID {0} to above normal priority", Id); + handle.PriorityClass = targetPriority; + logger.LogTrace("Set PID {pid} to {targetPriority} priority", Id, targetPriority); } - catch (Exception e) + catch (Exception ex) { - logger.LogWarning(e, "Unable to raise process priority for PID {0}!", Id); + logger.LogWarning(ex, "Unable to set priority for PID {id} to {targetPriority}!", Id, targetPriority); } } diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj index 4262179a12..458c311de2 100644 --- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj +++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj @@ -69,25 +69,25 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + - - + + @@ -97,13 +97,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - + - + diff --git a/src/Tgstation.Server.Host/appsettings.yml b/src/Tgstation.Server.Host/appsettings.yml index 61040477a7..ebab1c2470 100644 --- a/src/Tgstation.Server.Host/appsettings.yml +++ b/src/Tgstation.Server.Host/appsettings.yml @@ -11,6 +11,9 @@ General: InstanceLimit: 10 ValidInstancePaths: HostApiDocumentation: false +Session: + HighPriorityLiveDreamDaemon: false + LowPriorityDeploymentProcesses: true FileLogging: Directory: Disable: false