mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 07:04:57 +01:00
It all comes together
This commit is contained in:
@@ -11,8 +11,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// Create an <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
/// <param name="metadata">The <see cref="Host.Models.Instance"/></param>
|
||||
/// <param name="databaseContextFactory">The <see cref="IDatabaseContextFactory"/> for the operation</param>
|
||||
/// <returns>A new <see cref="IInstance"/></returns>
|
||||
IInstance CreateInstance(Host.Models.Instance metadata, IDatabaseContextFactory databaseContextFactory);
|
||||
IInstance CreateInstance(Host.Models.Instance metadata);
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,9 @@ 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, IDatabaseContext databaseContext, CancellationToken cancellationToken);
|
||||
Task OnlineInstance(Host.Models.Instance metadata, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Offline an <see cref="IInstance"/>
|
||||
@@ -37,10 +36,9 @@ 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, IDatabaseContext databaseContext, string newPath, CancellationToken cancellationToken);
|
||||
Task MoveInstance(Host.Models.Instance metadata, string newPath, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <summary>
|
||||
/// Represents an on-disk git repository
|
||||
/// </summary>
|
||||
interface IRepository : IDisposable
|
||||
public interface IRepository : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// If the <see cref="IRepository"/> was cloned from GitHub.com
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Threading;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
|
||||
@@ -11,14 +11,24 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IDatabaseContextFactory"/> for the <see cref="InstanceFactory"/>
|
||||
/// </summary>
|
||||
readonly IDatabaseContextFactory databaseContextFactory;
|
||||
|
||||
/// <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));
|
||||
/// <param name="databaseContextFactory">The value of <see cref="databaseContextFactory"/></param>
|
||||
public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IInstance CreateInstance(Host.Models.Instance metadata, IDatabaseContextFactory databaseContextFactory)
|
||||
public IInstance CreateInstance(Host.Models.Instance metadata)
|
||||
{
|
||||
//Create the ioManager for the instance
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
@@ -16,18 +15,18 @@ namespace Tgstation.Server.Host.Components
|
||||
sealed class InstanceManager : IInstanceManager, IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IInstanceFactory"/> for the <see cref="IInstanceManager"/>
|
||||
/// The <see cref="IInstanceFactory"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
readonly IInstanceFactory instanceFactory;
|
||||
/// <summary>
|
||||
/// The <see cref="IServiceProvider"/> for the <see cref="IInstanceManager"/>
|
||||
/// </summary>
|
||||
readonly IServiceProvider serviceProvider;
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="IInstanceManager"/>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
/// <summary>
|
||||
/// The <see cref="IDatabaseContextFactory"/> for the <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
readonly IDatabaseContextFactory databaseContextFactory;
|
||||
/// <summary>
|
||||
/// Map of <see cref="Api.Models.Instance.Id"/>s to respective <see cref="IInstance"/>s
|
||||
/// </summary>
|
||||
readonly Dictionary<long, IInstance> instances;
|
||||
@@ -36,13 +35,13 @@ namespace Tgstation.Server.Host.Components
|
||||
/// Construct an <see cref="InstanceManager"/>
|
||||
/// </summary>
|
||||
/// <param name="instanceFactory">The value of <see cref="instanceFactory"/></param>
|
||||
/// <param name="serviceProvider">The value of <paramref name="serviceProvider"/></param>
|
||||
/// <param name="ioManager">The value of <paramref name="ioManager"/></param>
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IServiceProvider serviceProvider, IIOManager ioManager)
|
||||
/// <param name="databaseContextFactory">The value of <paramref name="databaseContextFactory"/></param>
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory)
|
||||
{
|
||||
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
|
||||
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
instances = new Dictionary<long, IInstance>();
|
||||
}
|
||||
|
||||
@@ -60,7 +59,7 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task MoveInstance(Host.Models.Instance instance, IDatabaseContext databaseContext, string newPath, CancellationToken cancellationToken)
|
||||
public async Task MoveInstance(Host.Models.Instance instance, string newPath, CancellationToken cancellationToken)
|
||||
{
|
||||
if (newPath == null)
|
||||
throw new ArgumentNullException(nameof(newPath));
|
||||
@@ -72,14 +71,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, databaseContext, default);
|
||||
instanceOnlineTask = OnlineInstance(instance, default);
|
||||
await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (instance.Online)
|
||||
if (instanceOnlineTask == null)
|
||||
await OnlineInstance(instance, databaseContext, default).ConfigureAwait(false);
|
||||
await OnlineInstance(instance, default).ConfigureAwait(false);
|
||||
else
|
||||
await instanceOnlineTask.ConfigureAwait(false);
|
||||
}
|
||||
@@ -101,11 +100,11 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnlineInstance(Host.Models.Instance metadata, IDatabaseContext databaseContext, CancellationToken cancellationToken)
|
||||
public async Task OnlineInstance(Host.Models.Instance metadata, CancellationToken cancellationToken)
|
||||
{
|
||||
if (metadata == null)
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
var instance = instanceFactory.CreateInstance(metadata, databaseContext);
|
||||
var instance = instanceFactory.CreateInstance(metadata);
|
||||
lock (this)
|
||||
{
|
||||
if (instances.ContainsKey(metadata.Id))
|
||||
@@ -116,18 +115,14 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async databaseContext =>
|
||||
{
|
||||
using(var scope = serviceProvider.CreateScope())
|
||||
{
|
||||
var databaseContext = scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
|
||||
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, databaseContext, cancellationToken)), cancellationToken).ConfigureAwait(false);
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
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 Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// Controller for managing the compiler
|
||||
/// </summary>
|
||||
[Route("/DreamMaker")]
|
||||
public sealed class DreamMakerController : ModelController<Api.Models.CompileJob>
|
||||
public sealed class DreamMakerController : ModelController<Api.Models.DreamMaker>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IJobManager"/> for the <see cref="DreamMakerController"/>
|
||||
@@ -38,7 +38,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamMakerRights.Compile)]
|
||||
public override async Task<IActionResult> Create([FromBody] Api.Models.CompileJob model, CancellationToken cancellationToken)
|
||||
public override async Task<IActionResult> Create([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
|
||||
{
|
||||
var job = new Job
|
||||
{
|
||||
@@ -53,16 +53,30 @@ namespace Tgstation.Server.Host.Controllers
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamMakerRights.CancelCompile)]
|
||||
public override async Task<IActionResult> Delete([FromBody] Api.Models.CompileJob model, CancellationToken cancellationToken)
|
||||
public override async Task<IActionResult> Delete([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
|
||||
{
|
||||
//alias for cancelling the latest job
|
||||
var job = await DatabaseContext.Jobs.OrderByDescending(x => x.StartedAt).Select(x => new Job { Id = x.Id, StoppedAt = x.StoppedAt }).FirstAsync(cancellationToken).ConfigureAwait(false);
|
||||
var job = await DatabaseContext.CompileJobs.OrderByDescending(x => x.Job.StartedAt).Select(x => new Job { Id = x.Job.Id, StoppedAt = x.Job.StoppedAt }).FirstAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (job.StoppedAt != null)
|
||||
return StatusCode(HttpStatusCode.Gone);
|
||||
jobManager.CancelJob(job);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(DreamMakerRights.SetDme)]
|
||||
public override async Task<IActionResult> Update([FromBody] Api.Models.DreamMaker model, CancellationToken cancellationToken)
|
||||
{
|
||||
var hostModel = new DreamMakerSettings
|
||||
{
|
||||
InstanceId = Instance.Id
|
||||
};
|
||||
DatabaseContext.DreamMakerSettings.Attach(hostModel);
|
||||
hostModel.ProjectName = model.ProjectName;
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the compile job and insert it into the database
|
||||
/// </summary>
|
||||
|
||||
@@ -28,6 +28,9 @@ namespace Tgstation.Server.Host.Models
|
||||
/// <inheritdoc />
|
||||
public DbSet<RevisionInformation> RevisionInformations { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DbSet{TEntity}"/> for <see cref="Log"/>s
|
||||
/// </summary>
|
||||
@@ -50,10 +53,6 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
public DbSet<DreamDaemonSettings> DreamDaemonSettings { get; set; }
|
||||
/// <summary>
|
||||
/// The <see cref="Models.DreamMakerSettings"/> in the <see cref="DatabaseContext{TParentContext}"/>
|
||||
/// </summary>
|
||||
public DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
|
||||
/// <summary>
|
||||
/// The <see cref="Job"/>s in the <see cref="DatabaseContext{TParentContext}"/>
|
||||
/// </summary>
|
||||
public DbSet<Job> Jobs { get; set; }
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
DbSet<RevisionInformation> RevisionInformations { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DreamMakerSettings"/> in the <see cref="IDatabaseContext"/>
|
||||
/// </summary>
|
||||
DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="ServerSettings"/> in the <see cref="IDatabaseContext"/>
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user