Adds the PosixWatchdog

- Test BasicWatchdog in Sqlite travis job
- Rename UseBasicWatchdogOnWindows to UseBasicWatchdog
- Inline one use of DatabaseContextExtensions in DmbFactory
- Rename WindowsSwappableDmbProvider to SwappableDmbProvider
- Fix DreamDaemonController returning the wrong ActiveCompileJob
- Re-enable disabled watchdog tests
This commit is contained in:
Jordan Brown
2020-07-05 12:00:55 -04:00
parent 027392609a
commit 1ba914afee
15 changed files with 274 additions and 90 deletions
+2 -1
View File
@@ -38,9 +38,10 @@ jobs:
- DockerBuild=false
- DMAPI=false
- CONFIG=Release
- General__UseBasicWatchdog=true
- TGS4_TEST_DATABASE_TYPE=Sqlite
- TGS4_TEST_CONNECTION_STRING="Data Source=TravisTestDB.sqlite3;Mode=ReadWriteCreate"
name: "Sqlite Integration Test"
name: "Sqlite & BasicWatchdog Integration Test"
language: csharp
mono: none
dotnet: 3.1
@@ -7,7 +7,6 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.Extensions;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Models;
@@ -173,7 +172,11 @@ namespace Tgstation.Server.Host.Components.Deployment
await databaseContextFactory.UseContext(async (db) =>
{
cj = await db
.MostRecentCompletedCompileJobOrDefault(instance, cancellationToken)
.CompileJobs
.AsQueryable()
.Where(x => x.Job.Instance.Id == instance.Id)
.OrderByDescending(x => x.Job.StoppedAt)
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(false);
})
.ConfigureAwait(false);
@@ -322,7 +325,7 @@ namespace Tgstation.Server.Host.Components.Deployment
.ToList();
}).ConfigureAwait(false);
jobUidsToNotErase.Add(WindowsSwappableDmbProvider.LiveGameDirectory);
jobUidsToNotErase.Add(SwappableDmbProvider.LiveGameDirectory);
logger.LogTrace("We will not clean the following directories: {0}", String.Join(", ", jobUidsToNotErase));
@@ -7,9 +7,9 @@ using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Components.Deployment
{
/// <summary>
/// A windows <see cref="IDmbProvider"/> that uses symlinks.
/// A <see cref="IDmbProvider"/> that uses symlinks.
/// </summary>
sealed class WindowsSwappableDmbProvider : IDmbProvider
sealed class SwappableDmbProvider : IDmbProvider
{
/// <summary>
/// The directory where the <see cref="baseProvider"/> is symlinked to.
@@ -41,12 +41,12 @@ namespace Tgstation.Server.Host.Components.Deployment
readonly ISymlinkFactory symlinkFactory;
/// <summary>
/// Initializes a new instance of the <see cref="WindowsSwappableDmbProvider"/> <see langword="class"/>.
/// Initializes a new instance of the <see cref="SwappableDmbProvider"/> <see langword="class"/>.
/// </summary>
/// <param name="baseProvider">The value of <see cref="baseProvider"/>.</param>
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="symlinkFactory"/>.</param>
public WindowsSwappableDmbProvider(IDmbProvider baseProvider, IIOManager ioManager, ISymlinkFactory symlinkFactory)
public SwappableDmbProvider(IDmbProvider baseProvider, IIOManager ioManager, ISymlinkFactory symlinkFactory)
{
this.baseProvider = baseProvider ?? throw new ArgumentNullException(nameof(baseProvider));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
@@ -60,7 +60,7 @@ namespace Tgstation.Server.Host.Components.Deployment
public void KeepAlive() => baseProvider.KeepAlive();
/// <summary>
/// Make the <see cref="WindowsSwappableDmbProvider"/> active by replacing the live link with our <see cref="CompileJob"/>.
/// Make the <see cref="SwappableDmbProvider"/> active by replacing the live link with our <see cref="CompileJob"/>.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
@@ -174,7 +174,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
protected sealed override ISessionController GetActiveController() => Server;
/// <inheritdoc />
protected sealed override async Task InitControllers(
protected override async Task InitControllers(
Task chatTask,
ReattachInformation reattachInfo,
CancellationToken cancellationToken)
@@ -0,0 +1,121 @@
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Deployment;
using Tgstation.Server.Host.Components.Events;
using Tgstation.Server.Host.Components.Session;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Jobs;
namespace Tgstation.Server.Host.Components.Watchdog
{
/// <summary>
/// A variant of the <see cref="WindowsWatchdog"/> that works on POSIX systems.
/// </summary>
sealed class PosixWatchdog : WindowsWatchdog
{
/// <summary>
/// If the swappable game directory is currently a rename of the compile job.
/// </summary>
bool directoryHardLinked;
/// <summary>
/// Initializes a new instance of the <see cref="PosixWatchdog"/> <see langword="class"/>.
/// </summary>
/// <param name="chat">The <see cref="IChatManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="sessionControllerFactory">The <see cref="ISessionControllerFactory"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="dmbFactory">The <see cref="IDmbFactory"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="reattachInfoHandler">The <see cref="IReattachInfoHandler"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="databaseContextFactory">The <see cref="IDatabaseContextFactory"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="jobManager">The <see cref="IJobManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="serverControl">The <see cref="IServerControl"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gameIOManager">The <see cref="IIOManager"/> pointing to the game directory for the <see cref="WindowsWatchdog"/>..</param>
/// <param name="symlinkFactory">The <see cref="ISymlinkFactory"/> for the <see cref="WindowsWatchdog"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="initialLaunchParameters">The <see cref="DreamDaemonLaunchParameters"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="instance">The <see cref="Api.Models.Instance"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="autoStart">The autostart value for the <see cref="WatchdogBase"/>.</param>
public PosixWatchdog(
IChatManager chat,
ISessionControllerFactory sessionControllerFactory,
IDmbFactory dmbFactory,
IReattachInfoHandler reattachInfoHandler,
IDatabaseContextFactory databaseContextFactory,
IJobManager jobManager,
IServerControl serverControl,
IAsyncDelayer asyncDelayer,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IIOManager gameIOManager,
ISymlinkFactory symlinkFactory,
ILogger<PosixWatchdog> logger,
DreamDaemonLaunchParameters initialLaunchParameters,
Api.Models.Instance instance,
bool autoStart)
: base(
chat,
sessionControllerFactory,
dmbFactory,
reattachInfoHandler,
databaseContextFactory,
jobManager,
serverControl,
asyncDelayer,
diagnosticsIOManager,
eventConsumer,
gameIOManager,
symlinkFactory,
logger,
initialLaunchParameters,
instance,
autoStart)
{ }
/// <inheritdoc />
protected override async Task InitialLink(SwappableDmbProvider swappableDmbProvider, CancellationToken cancellationToken)
{
// Instead of symlinking to begin with we actually rename the directory
Logger.LogTrace("Hard linking compile job...");
await GameIOManager.MoveDirectory(
swappableDmbProvider.CompileJob.DirectoryName.ToString(),
swappableDmbProvider.Directory,
cancellationToken)
.ConfigureAwait(false);
directoryHardLinked = true;
}
/// <inheritdoc />
protected override async Task InitControllers(Task chatTask, ReattachInformation reattachInfo, CancellationToken cancellationToken)
{
try
{
await base.InitControllers(chatTask, reattachInfo, cancellationToken).ConfigureAwait(false);
}
finally
{
// Then we move it back and apply the symlink
if (directoryHardLinked)
{
Logger.LogTrace("Unhardlinking compile job...");
Server?.Suspend();
await GameIOManager.MoveDirectory(
ActiveSwappable.Directory,
ActiveSwappable.CompileJob.DirectoryName.ToString(),
default)
.ConfigureAwait(false);
directoryHardLinked = false;
}
}
await ActiveSwappable.MakeActive(cancellationToken).ConfigureAwait(false);
Server.Resume();
}
}
}
@@ -0,0 +1,78 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Deployment;
using Tgstation.Server.Host.Components.Events;
using Tgstation.Server.Host.Components.Session;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Jobs;
namespace Tgstation.Server.Host.Components.Watchdog
{
/// <summary>
/// <see cref="IWatchdogFactory"/> for creating <see cref="PosixWatchdog"/>s.
/// </summary>
sealed class PosixWatchdogFactory : WindowsWatchdogFactory
{
/// <summary>
/// Initializes a new instance of the <see cref="PosixWatchdogFactory"/> <see langword="class"/>.
/// </summary>
/// <param name="serverControl">The <see cref="IServerControl"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="databaseContextFactory">The <see cref="IDatabaseContextFactory"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="jobManager">The <see cref="IJobManager"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="symlinkFactory">The <see cref="ISymlinkFactory"/> for the <see cref="WindowsWatchdogFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> for <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
public PosixWatchdogFactory(
IServerControl serverControl,
ILoggerFactory loggerFactory,
IDatabaseContextFactory databaseContextFactory,
IJobManager jobManager,
IAsyncDelayer asyncDelayer,
ISymlinkFactory symlinkFactory,
IOptions<GeneralConfiguration> generalConfigurationOptions)
: base(
serverControl,
loggerFactory,
databaseContextFactory,
jobManager,
asyncDelayer,
symlinkFactory,
generalConfigurationOptions)
{ }
/// <inheritdoc />
public override IWatchdog CreateWatchdog(
IChatManager chat,
IDmbFactory dmbFactory,
IReattachInfoHandler reattachInfoHandler,
ISessionControllerFactory sessionControllerFactory,
IIOManager gameIOManager,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
Api.Models.Instance instance,
DreamDaemonSettings settings)
=> new PosixWatchdog(
chat,
sessionControllerFactory,
dmbFactory,
reattachInfoHandler,
DatabaseContextFactory,
JobManager,
ServerControl,
AsyncDelayer,
diagnosticsIOManager,
eventConsumer,
gameIOManager,
SymlinkFactory,
LoggerFactory.CreateLogger<PosixWatchdog>(),
settings,
instance,
settings.AutoStart.Value);
}
}
@@ -236,6 +236,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
restartRegistration.Dispose();
throw;
}
Logger.LogTrace("Created watchdog");
}
/// <inheritdoc />
@@ -15,14 +15,19 @@ using Tgstation.Server.Host.Jobs;
namespace Tgstation.Server.Host.Components.Watchdog
{
/// <summary>
/// A version of the <see cref="BasicWatchdog"/> that, instead of killing servers for updates, uses the wonders of symlinks to swap out changes without killing DreamDaemon.
/// A <see cref="IWatchdog"/> that, instead of killing servers for updates, uses the wonders of symlinks to swap out changes without killing DreamDaemon.
/// </summary>
sealed class WindowsWatchdog : BasicWatchdog
class WindowsWatchdog : BasicWatchdog
{
/// <summary>
/// The <see cref="SwappableDmbProvider"/> for <see cref="WatchdogBase.LastLaunchParameters"/>.
/// </summary>
protected SwappableDmbProvider ActiveSwappable { get; private set; }
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="WindowsWatchdog"/> pointing to the Game directory.
/// </summary>
readonly IIOManager gameIOManager;
protected IIOManager GameIOManager { get; }
/// <summary>
/// The <see cref="ISymlinkFactory"/> for the <see cref="WindowsWatchdog"/>.
@@ -30,14 +35,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
readonly ISymlinkFactory symlinkFactory;
/// <summary>
/// The <see cref="WindowsSwappableDmbProvider"/> for <see cref="WatchdogBase.LastLaunchParameters"/>.
/// The active <see cref="SwappableDmbProvider"/> for <see cref="WatchdogBase.ActiveLaunchParameters"/>.
/// </summary>
WindowsSwappableDmbProvider activeSwappable;
/// <summary>
/// The active <see cref="WindowsSwappableDmbProvider"/> for <see cref="WatchdogBase.ActiveLaunchParameters"/>.
/// </summary>
WindowsSwappableDmbProvider pendingSwappable;
SwappableDmbProvider pendingSwappable;
/// <summary>
/// The <see cref="IDmbProvider"/> the <see cref="WindowsWatchdog"/> was started with.
@@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gameIOManager">The value of <see cref="gameIOManager"/>.</param>
/// <param name="gameIOManager">The value of <see cref="GameIOManager"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="symlinkFactory"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="initialLaunchParameters">The <see cref="DreamDaemonLaunchParameters"/> for the <see cref="WatchdogBase"/>.</param>
@@ -97,7 +97,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
{
try
{
this.gameIOManager = gameIOManager ?? throw new ArgumentNullException(nameof(gameIOManager));
GameIOManager = gameIOManager ?? throw new ArgumentNullException(nameof(gameIOManager));
this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
}
catch
@@ -113,7 +113,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
base.DisposeAndNullControllersImpl();
// If we reach this point, we can guarantee PrepServerForLaunch will be called before starting again.
activeSwappable = null;
ActiveSwappable = null;
pendingSwappable?.Dispose();
pendingSwappable = null;
@@ -128,7 +128,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
{
Logger.LogTrace("Replacing activeSwappable with pendingSwappable...");
Server.ReplaceDmbProvider(pendingSwappable);
activeSwappable = pendingSwappable;
ActiveSwappable = pendingSwappable;
pendingSwappable = null;
}
else
@@ -154,11 +154,11 @@ namespace Tgstation.Server.Host.Components.Watchdog
return;
}
WindowsSwappableDmbProvider windowsProvider = null;
SwappableDmbProvider windowsProvider = null;
bool suspended = false;
try
{
windowsProvider = new WindowsSwappableDmbProvider(compileJobProvider, gameIOManager, symlinkFactory);
windowsProvider = new SwappableDmbProvider(compileJobProvider, GameIOManager, symlinkFactory);
Logger.LogDebug("Swapping to compile job {0}...", windowsProvider.CompileJob.Id);
try
@@ -190,9 +190,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
/// <inheritdoc />
protected override async Task<IDmbProvider> PrepServerForLaunch(IDmbProvider dmbToUse, CancellationToken cancellationToken)
protected sealed override async Task<IDmbProvider> PrepServerForLaunch(IDmbProvider dmbToUse, CancellationToken cancellationToken)
{
if(activeSwappable != null)
if(ActiveSwappable != null)
throw new InvalidOperationException("Expected activeSwappable to be null!");
if(startupDmbProvider != null)
throw new InvalidOperationException("Expected startupDmbProvider to be null!");
@@ -202,21 +202,30 @@ namespace Tgstation.Server.Host.Components.Watchdog
// Add another lock to the startup DMB because it'll be used throughout the lifetime of the watchdog
startupDmbProvider = await DmbFactory.FromCompileJob(dmbToUse.CompileJob, cancellationToken).ConfigureAwait(false);
activeSwappable = pendingSwappable ?? new WindowsSwappableDmbProvider(dmbToUse, gameIOManager, symlinkFactory);
ActiveSwappable = pendingSwappable ?? new SwappableDmbProvider(dmbToUse, GameIOManager, symlinkFactory);
pendingSwappable = null;
try
{
await activeSwappable.MakeActive(cancellationToken).ConfigureAwait(false);
await InitialLink(ActiveSwappable, cancellationToken).ConfigureAwait(false);
}
catch
{
// We won't worry about disposing activeSwappable here as we can't dispose dmbToUse here.
activeSwappable = null;
ActiveSwappable = null;
throw;
}
return activeSwappable;
return ActiveSwappable;
}
/// <summary>
/// Create the initial link to the live game directory.
/// </summary>
/// <param name="swappableDmbProvider">The <see cref="SwappableDmbProvider"/> in use.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
protected virtual Task InitialLink(SwappableDmbProvider swappableDmbProvider, CancellationToken cancellationToken)
=> swappableDmbProvider.MakeActive(cancellationToken);
}
}
@@ -17,12 +17,12 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <summary>
/// <see cref="IWatchdogFactory"/> for creating <see cref="WindowsWatchdog"/>s.
/// </summary>
sealed class WindowsWatchdogFactory : WatchdogFactory
class WindowsWatchdogFactory : WatchdogFactory
{
/// <summary>
/// The <see cref="ISymlinkFactory"/> for the <see cref="WindowsWatchdogFactory"/>.
/// </summary>
readonly ISymlinkFactory symlinkFactory;
protected ISymlinkFactory SymlinkFactory { get; }
/// <summary>
/// Initializes a new instance of the <see cref="WindowsWatchdogFactory"/> <see langword="class"/>.
@@ -32,7 +32,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="databaseContextFactory">The <see cref="IDatabaseContextFactory"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="jobManager">The <see cref="IJobManager"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogFactory"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="symlinkFactory"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="SymlinkFactory"/>.</param>
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> for <see cref="GeneralConfiguration"/> for the <see cref="WatchdogFactory"/>.</param>
public WindowsWatchdogFactory(
IServerControl serverControl,
@@ -50,7 +50,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
asyncDelayer,
generalConfigurationOptions)
{
this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
SymlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
}
/// <inheritdoc />
@@ -76,7 +76,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
diagnosticsIOManager,
eventConsumer,
gameIOManager,
symlinkFactory,
SymlinkFactory,
LoggerFactory.CreateLogger<WindowsWatchdog>(),
settings,
instance,
@@ -83,9 +83,9 @@ namespace Tgstation.Server.Host.Configuration
public uint RestartTimeout { get; set; } = DefaultRestartTimeout;
/// <summary>
/// If the <see cref="Components.Watchdog.WindowsWatchdog"/> should not be used if it is available.
/// If the <see cref="Components.Watchdog.BasicWatchdog"/> should be preferred.
/// </summary>
public bool UseBasicWatchdogOnWindows { get; set; }
public bool UseBasicWatchdog { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="GeneralConfiguration"/> <see langword="class"/>.
@@ -142,7 +142,7 @@ namespace Tgstation.Server.Host.Controllers
if (revision)
{
var latestCompileJob = instance.LatestCompileJob();
result.ActiveCompileJob = ((instance.Watchdog.Status == WatchdogStatus.Offline
result.ActiveCompileJob = ((instance.Watchdog.Status != WatchdogStatus.Offline
? dd.ActiveCompileJob
: latestCompileJob) ?? latestCompileJob)
?.ToApi();
+17 -6
View File
@@ -251,11 +251,7 @@ namespace Tgstation.Server.Host.Core
// configure platform specific services
if (postSetupServices.PlatformIdentifier.IsWindows)
{
if (postSetupServices.GeneralConfiguration.UseBasicWatchdogOnWindows)
services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
else
services.AddSingleton<IWatchdogFactory, WindowsWatchdogFactory>();
AddWatchdog<WindowsWatchdogFactory>(services, postSetupServices);
services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
@@ -268,7 +264,7 @@ namespace Tgstation.Server.Host.Core
}
else
{
services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
AddWatchdog<PosixWatchdogFactory>(services, postSetupServices);
services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
services.AddSingleton<IByondInstaller, PosixByondInstaller>();
@@ -303,6 +299,21 @@ namespace Tgstation.Server.Host.Core
services.AddSingleton<IInstanceManager>(x => x.GetRequiredService<InstanceManager>());
}
/// <summary>
/// Adds the <see cref="IWatchdogFactory"/> implementation.
/// </summary>
/// <typeparam name="TSystemWatchdogFactory">The <see cref="WatchdogFactory"/> child <see langword="class"/> for the current system.</typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to configure.</param>
/// <param name="postSetupServices">The <see cref="IPostSetupServices"/> to use.</param>
static void AddWatchdog<TSystemWatchdogFactory>(IServiceCollection services, IPostSetupServices postSetupServices)
where TSystemWatchdogFactory : class, IWatchdogFactory
{
if (postSetupServices.GeneralConfiguration.UseBasicWatchdog)
services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
else
services.AddSingleton<IWatchdogFactory, TSystemWatchdogFactory>();
}
/// <inheritdoc />
protected override void ConfigureHostedService(IServiceCollection services)
=> services.AddSingleton<IHostedService>(x => x.GetRequiredService<InstanceManager>());
@@ -1,39 +0,0 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Extensions
{
/// <summary>
/// Extensions for the <see cref="IDatabaseContext"/> <see langword="class"/>.
/// </summary>
static class DatabaseContextExtensions
{
/// <summary>
/// Get the most recent <see cref="CompileJob"/> for a given <paramref name="instance"/> from a given <paramref name="databaseContext"/>.
/// </summary>
/// <param name="databaseContext">The <see cref="IDatabaseContext"/>.</param>
/// <param name="instance">The <see cref="Instance"/> to search for <see cref="CompileJob"/>s.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the most recent <see cref="CompileJob"/> associated with the given <paramref name="instance"/> from the <paramref name="databaseContext"/>.</returns>
public static Task<CompileJob> MostRecentCompletedCompileJobOrDefault(
this IDatabaseContext databaseContext,
Api.Models.Instance instance,
CancellationToken cancellationToken)
{
if (databaseContext == null)
throw new ArgumentNullException(nameof(databaseContext));
return databaseContext
.CompileJobs
.AsQueryable()
.Where(x => x.Job.Instance.Id == instance.Id)
.OrderByDescending(x => x.Job.StoppedAt)
.FirstOrDefaultAsync(cancellationToken);
}
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
"ByondTopicTimeout": 5000,
"RestartTimeout": 60000,
"ApiPort": 5000,
"UseBasicWatchdogOnWindows": false,
"UseBasicWatchdog": false,
"UserLimit": 100,
"InstanceLimit": 10,
"ValidInstancePaths": null
@@ -59,10 +59,8 @@ namespace Tgstation.Server.Tests.Instance
Version = ByondTest.TestVersion
}, cancellationToken);
// await RunLongRunningTestThenUpdate(cancellationToken);
// await RunLongRunningTestThenUpdateWithByondVersionSwitch(cancellationToken);
// Remove this deploy when the above tests are reenabled
await DeployTestDme("LongRunning/long_running_test", DreamDaemonSecurity.Trusted, cancellationToken);
await RunLongRunningTestThenUpdate(cancellationToken);
await RunLongRunningTestThenUpdateWithByondVersionSwitch(cancellationToken);
await RunHeartbeatTest(cancellationToken);