mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 08:00:19 +01:00
Pull the chains slightly tighter
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -12,7 +11,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <summary>
|
||||
/// Standard <see cref="IDmbFactory"/>
|
||||
/// </summary>
|
||||
sealed class DmbFactory : IDmbFactory, ICompileJobConsumer, IHostedService, IDisposable
|
||||
sealed class DmbFactory : IDmbFactory, ICompileJobConsumer
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IDatabaseContext"/> for the <see cref="DmbFactory"/>
|
||||
@@ -102,7 +101,12 @@ namespace Tgstation.Server.Host.Components
|
||||
else
|
||||
task = newerDmbTcs.Task;
|
||||
|
||||
return await task.ConfigureAwait(false);
|
||||
var result = await task.ConfigureAwait(false);
|
||||
//so there's currently a race condition in DreamMakerController where the setting of CompileJob.RevisionInformation and thus IDmbProvider.RevisionInformation can be delayed to after this if someone tries to start the server instantly after compiling
|
||||
//This is a terrible terrible hack to get around that
|
||||
//I'm sorry future me, I can't think of any other way to fix this other than giving DreamMaker an IDatabaseContext or having the controller load the CompileJob
|
||||
await Task.Delay(new TimeSpan(0, 0, 10), cancellationToken).ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -47,6 +47,10 @@ namespace Tgstation.Server.Host.Components
|
||||
/// The <see cref="IInterop"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
readonly IInterop interop;
|
||||
/// <summary>
|
||||
/// The <see cref="ICompileJobConsumer"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
readonly ICompileJobConsumer compileJobConsumer;
|
||||
|
||||
/// <summary>
|
||||
/// Construct <see cref="DreamMaker"/>
|
||||
@@ -56,13 +60,15 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="dreamDaemonExecutor">The value of <see cref="dreamDaemonExecutor"/></param>
|
||||
/// <param name="byond">The value of <see cref="byond"/></param>
|
||||
/// <param name="interop">The value of <see cref="interop"/></param>
|
||||
public DreamMaker(IIOManager ioManager, IConfiguration configuration, IDreamDaemonExecutor dreamDaemonExecutor, IByond byond, IInterop interop)
|
||||
/// <param name="compileJobConsumer">The value of <see cref="compileJobConsumer"/></param>
|
||||
public DreamMaker(IIOManager ioManager, IConfiguration configuration, IDreamDaemonExecutor dreamDaemonExecutor, IByond byond, IInterop interop, ICompileJobConsumer compileJobConsumer)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
|
||||
this.dreamDaemonExecutor = dreamDaemonExecutor ?? throw new ArgumentNullException(nameof(dreamDaemonExecutor));
|
||||
this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
|
||||
this.interop = interop ?? throw new ArgumentNullException(nameof(interop));
|
||||
this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -248,6 +254,7 @@ namespace Tgstation.Server.Host.Components
|
||||
await configuration.SymlinkStaticFilesTo(ioManager.ResolvePath(dirB), cancellationToken).ConfigureAwait(false);
|
||||
await symATask.ConfigureAwait(false);
|
||||
}
|
||||
compileJobConsumer.LoadCompileJob(job);
|
||||
return job;
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
interface ICompileJobConsumer
|
||||
interface ICompileJobConsumer : IHostedService, IDisposable
|
||||
{
|
||||
void LoadCompileJob(CompileJob job);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace Tgstation.Server.Host.Components
|
||||
/// Create an <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">The <see cref="Host.Models.Instance"/></param>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the operation</param>
|
||||
/// <returns>A new <see cref="IInstance"/></returns>
|
||||
IInstance CreateInstance(Host.Models.Instance metadata);
|
||||
IInstance CreateInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
@@ -19,9 +20,10 @@ namespace Tgstation.Server.Host.Components
|
||||
/// Online an <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">The <see cref="Host.Models.Instance"/> of the desired <see cref="IInstance"/></param>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the operation</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task OnlineInstance(Host.Models.Instance metadata, CancellationToken cancellationToken);
|
||||
Task OnlineInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Offline an <see cref="IInstance"/>
|
||||
@@ -35,9 +37,10 @@ namespace Tgstation.Server.Host.Components
|
||||
/// Move an <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">The <see cref="Host.Models.Instance"/> of the desired <see cref="IInstance"/></param>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the operation</param>
|
||||
/// <param name="newPath">The new path of the <see cref="IInstance"/>. <paramref name="metadata"/> will have this set on <see cref="Api.Models.Instance.Path"/> if the operation completes successfully</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task MoveInstance(Host.Models.Instance metadata, string newPath, CancellationToken cancellationToken);
|
||||
Task MoveInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext, string newPath, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ namespace Tgstation.Server.Host.Components
|
||||
public IChat Chat { get; }
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
|
||||
readonly ICompileJobConsumer compileJobConsumer;
|
||||
|
||||
readonly Api.Models.Instance metadata;
|
||||
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByond byond, IDreamMaker dreamMaker, IDreamDaemon dreamDaemon, IChat chat, IConfiguration configuration)
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByond byond, IDreamMaker dreamMaker, IDreamDaemon dreamDaemon, IChat chat, IConfiguration configuration, ICompileJobConsumer compileJobConsumer)
|
||||
{
|
||||
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
|
||||
RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
|
||||
@@ -29,6 +31,7 @@ namespace Tgstation.Server.Host.Components
|
||||
DreamDaemon = dreamDaemon ?? throw new ArgumentNullException(nameof(dreamDaemon));
|
||||
Chat = chat ?? throw new ArgumentNullException(nameof(chat));
|
||||
Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
|
||||
this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
|
||||
}
|
||||
|
||||
public Api.Models.Instance GetMetadata() => metadata.CloneMetadata();
|
||||
@@ -40,8 +43,8 @@ namespace Tgstation.Server.Host.Components
|
||||
metadata.Name = newName;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.WhenAll(RepositoryManager.StartAsync(cancellationToken), DreamDaemon.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken));
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.WhenAll(RepositoryManager.StartAsync(cancellationToken), DreamDaemon.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken));
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(RepositoryManager.StopAsync(cancellationToken), DreamDaemon.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken));
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(RepositoryManager.StopAsync(cancellationToken), DreamDaemon.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken), compileJobConsumer.StopAsync(cancellationToken));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
using System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class InstanceFactory : IInstanceFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="InstanceFactory"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// Construct an <see cref="InstanceFactory"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
public InstanceFactory(IIOManager ioManager) => this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
|
||||
/// <inheritdoc />
|
||||
public IInstance CreateInstance(Host.Models.Instance metadata)
|
||||
public IInstance CreateInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext)
|
||||
{
|
||||
//Create the ioManager for the instance
|
||||
|
||||
@@ -21,6 +30,11 @@ namespace Tgstation.Server.Host.Components
|
||||
var byondIOManager = new ResolvingIOManager(instanceIoManager, "Byond");
|
||||
var gameIoManager = new ResolvingIOManager(instanceIoManager, "Game");
|
||||
var configurationIoManager = new ResolvingIOManager(instanceIoManager, "Configuration");
|
||||
var codeModificationsIoMananger = new ResolvingIOManager(instanceIoManager, "CodeModifications");
|
||||
|
||||
var dmbFactory = new DmbFactory(databaseContext, gameIoManager);
|
||||
|
||||
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task MoveInstance(Host.Models.Instance instance, string newPath, CancellationToken cancellationToken)
|
||||
public async Task MoveInstance(Host.Models.Instance instance, IDatabaseContext databaseContext, string newPath, CancellationToken cancellationToken)
|
||||
{
|
||||
if (newPath == null)
|
||||
throw new ArgumentNullException(nameof(newPath));
|
||||
@@ -72,14 +72,14 @@ namespace Tgstation.Server.Host.Components
|
||||
var oldPath = instance.Path;
|
||||
await ioManager.CopyDirectory(oldPath, newPath, null, cancellationToken).ConfigureAwait(false);
|
||||
instance.Path = ioManager.ResolvePath(newPath);
|
||||
instanceOnlineTask = OnlineInstance(instance, default);
|
||||
instanceOnlineTask = OnlineInstance(instance, databaseContext, default);
|
||||
await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (instance.Online)
|
||||
if (instanceOnlineTask == null)
|
||||
await OnlineInstance(instance, default).ConfigureAwait(false);
|
||||
await OnlineInstance(instance, databaseContext, default).ConfigureAwait(false);
|
||||
else
|
||||
await instanceOnlineTask.ConfigureAwait(false);
|
||||
}
|
||||
@@ -101,11 +101,11 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnlineInstance(Host.Models.Instance metadata, CancellationToken cancellationToken)
|
||||
public async Task OnlineInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext, CancellationToken cancellationToken)
|
||||
{
|
||||
if (metadata == null)
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
var instance = instanceFactory.CreateInstance(metadata);
|
||||
var instance = instanceFactory.CreateInstance(metadata, databaseContext);
|
||||
lock (this)
|
||||
{
|
||||
if (instances.ContainsKey(metadata.Id))
|
||||
@@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Components
|
||||
await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
|
||||
var dbInstances = databaseContext.Instances.Where(x => x.Online).Include(x => x.RepositorySettings).Include(x => x.ChatSettings).Include(x => x.DreamDaemonSettings).ToAsyncEnumerable();
|
||||
var tasks = new List<Task>();
|
||||
await dbInstances.ForEachAsync(metadata => tasks.Add(OnlineInstance(metadata, cancellationToken)), cancellationToken).ConfigureAwait(false);
|
||||
await dbInstances.ForEachAsync(metadata => tasks.Add(OnlineInstance(metadata, databaseContext, cancellationToken)), cancellationToken).ConfigureAwait(false);
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user