From dee9471e021494f1aa3d03fae2977ecf83e62c98 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Fri, 3 Aug 2018 22:56:55 -0400 Subject: [PATCH] Stuff and such --- .../Internal/DreamDaemonLaunchParameters.cs | 2 +- .../Components/Chat/Chat.cs | 14 +++++++- .../Components/Compiler/DreamMaker.cs | 7 ++-- .../Components/Compiler/IDreamMaker.cs | 4 +-- .../Components/Instance.cs | 2 +- .../Components/InstanceFactory.cs | 2 +- .../Controllers/DreamMakerController.cs | 36 +++++++++++++------ src/Tgstation.Server.Host/Core/Application.cs | 1 + src/Tgstation.Server.Host/Core/JobManager.cs | 5 +-- .../IO/DefaultIOManager.cs | 2 +- 10 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs b/src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs index f52315595f..093277987d 100644 --- a/src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs +++ b/src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs @@ -42,6 +42,6 @@ namespace Tgstation.Server.Api.Models.Internal /// [Permissions(ReadRight = DreamDaemonRights.ReadMetadata, WriteRight = DreamDaemonRights.SetStartupTimeout)] [Required] - public int? StartupTimeout { get; set; } + public uint? StartupTimeout { get; set; } } } \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/Chat/Chat.cs b/src/Tgstation.Server.Host/Components/Chat/Chat.cs index c8e3b77ae7..72f8c2cd78 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Chat.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Chat.cs @@ -519,6 +519,18 @@ namespace Tgstation.Server.Host.Components.Chat } /// - public Task DeleteConnection(long connectionId, CancellationToken cancellationToken) => RemoveProvider(connectionId, true, cancellationToken); + public async Task DeleteConnection(long connectionId, CancellationToken cancellationToken) + { + var provider = await RemoveProvider(connectionId, true, cancellationToken).ConfigureAwait(false); + if (provider != null) + try + { + await provider.Disconnect(cancellationToken).ConfigureAwait(false); + } + finally + { + provider.Dispose(); + } + } } } diff --git a/src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs index ba9d935d71..33beec3f99 100644 --- a/src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; @@ -105,7 +104,7 @@ namespace Tgstation.Server.Host.Components.Compiler /// The current /// The for the operation /// A resulting in if the DMAPI was successfully validated, otherwise - async Task VerifyApi(int timeout, Models.CompileJob job, IByondExecutableLock byondLock, CancellationToken cancellationToken) + async Task VerifyApi(uint timeout, Models.CompileJob job, IByondExecutableLock byondLock, CancellationToken cancellationToken) { var launchParameters = new DreamDaemonLaunchParameters { @@ -226,7 +225,7 @@ namespace Tgstation.Server.Host.Components.Compiler } /// - public async Task Compile(string projectName, int apiValidateTimeout, IRepository repository, CancellationToken cancellationToken) + public async Task Compile(string projectName, uint apiValidateTimeout, IRepository repository, CancellationToken cancellationToken) { logger.LogTrace("Begin Compile"); await eventConsumer.HandleEvent(EventType.CompileStart, new List{ repository.Origin }, cancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs b/src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs index 900a3e648e..da6878c667 100644 --- a/src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs @@ -18,11 +18,11 @@ namespace Tgstation.Server.Host.Components.Compiler /// /// Starts a compile /// - /// The name of the .dme to compile without the extension + /// The optional name of the .dme to compile without the extension if not pre /// The time in seconds to wait while validating the API /// The to copy from /// The for the operation /// A resulting in the partially populated for the operation. In particular, note the field will only have it's field populated - Task Compile(string projectName, int apiValidateTimeout, IRepository repository, CancellationToken cancellationToken); + Task Compile(string projectName, uint apiValidateTimeout, IRepository repository, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index cb16e111f4..fcd335a27a 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Components RepositorySettings repositorySettings = null; string projectName = null; - int timeout = 0; + uint timeout = 0; var dbTask = databaseContextFactory.UseContext(async (db) => { var instanceQuery = db.Instances.Where(x => x.Id == metadata.Id); diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index c200766fc8..87f26407be 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -152,7 +152,7 @@ namespace Tgstation.Server.Host.Components commandFactory.SetWatchdog(watchdog); try { - var dreamMaker = new DreamMaker(byond, ioManager, configuration, sessionControllerFactory, dmbFactory, application, eventConsumer, loggerFactory.CreateLogger()); + var dreamMaker = new DreamMaker(byond, gameIoManager, configuration, sessionControllerFactory, dmbFactory, application, eventConsumer, loggerFactory.CreateLogger()); return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, loggerFactory.CreateLogger()); } diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs index 75801aac2d..460a6c598c 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs @@ -48,11 +48,11 @@ namespace Tgstation.Server.Host.Controllers public override async Task Read(CancellationToken cancellationToken) { var instance = instanceManager.GetInstance(Instance); - var projectNameTask = DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).Select(x => x.ProjectName).FirstAsync(cancellationToken); - var job = await DatabaseContext.CompileJobs.OrderByDescending(x => x.Job.StartedAt).Include(x => x.Job).FirstAsync(cancellationToken).ConfigureAwait(false); + var projectNameTask = DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).Select(x => x.ProjectName).FirstOrDefaultAsync(cancellationToken); + var job = await DatabaseContext.CompileJobs.OrderByDescending(x => x.Job.StartedAt).Include(x => x.Job).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); return Json(new Api.Models.DreamMaker { - LastJob = job.ToApi(), + LastJob = job?.ToApi(), ProjectName = await projectNameTask.ConfigureAwait(false), Status = instance.DreamMaker.Status }); @@ -71,7 +71,7 @@ namespace Tgstation.Server.Host.Controllers Instance = Instance }; await jobManager.RegisterOperation(job, (paramJob, serviceProvider, progressReporter, ct) => RunCompile(paramJob, serviceProvider, Instance, ct), cancellationToken).ConfigureAwait(false); - return Json(job); + return Json(job.ToApi()); } /// @@ -85,7 +85,7 @@ namespace Tgstation.Server.Host.Controllers DatabaseContext.DreamMakerSettings.Attach(hostModel); hostModel.ProjectName = model.ProjectName; await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); - return Ok(); + return await Read(cancellationToken).ConfigureAwait(false); } /// @@ -96,19 +96,19 @@ namespace Tgstation.Server.Host.Controllers /// The for the operation /// The for the operation /// A representing the running operation - static async Task RunCompile(Job job, IServiceProvider serviceProvider, Models.Instance instanceModel, CancellationToken cancellationToken) + async Task RunCompile(Job job, IServiceProvider serviceProvider, Models.Instance instanceModel, CancellationToken cancellationToken) { var instanceManager = serviceProvider.GetRequiredService(); var databaseContext = serviceProvider.GetRequiredService(); - var timeoutTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == instanceModel.Id).Select(x => x.StartupTimeout).FirstAsync(cancellationToken); - var projectName = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == instanceModel.Id).Select(x => x.ProjectName).FirstAsync(cancellationToken).ConfigureAwait(false); + var timeoutTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == instanceModel.Id).Select(x => x.StartupTimeout).FirstOrDefaultAsync(cancellationToken); + var projectName = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == instanceModel.Id).Select(x => x.ProjectName).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); var timeout = await timeoutTask.ConfigureAwait(false); var instance = instanceManager.GetInstance(instanceModel); CompileJob compileJob; - Task revInfoTask; + string repoSha = null; using (var repo = await instance.RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false)) { if (repo == null) @@ -116,12 +116,26 @@ namespace Tgstation.Server.Host.Controllers job.ExceptionDetails = "Missing repository!"; return; } - revInfoTask = databaseContext.RevisionInformations.Where(x => x.CommitSha == repo.Head).Select(x => new RevisionInformation { Id = x.Id }).FirstAsync(); + repoSha = repo.Head; compileJob = await instance.DreamMaker.Compile(projectName, timeout.Value, repo, cancellationToken).ConfigureAwait(false); } compileJob.Job = job; - compileJob.RevisionInformation = await revInfoTask.ConfigureAwait(false); + compileJob.RevisionInformation = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha).Select(x => new RevisionInformation { Id = x.Id }).FirstOrDefaultAsync().ConfigureAwait(false); + + if (compileJob.RevisionInformation == default) + { + compileJob.RevisionInformation = new RevisionInformation + { + CommitSha = repoSha, + OriginCommitSha = repoSha, + Instance = new Models.Instance + { + Id = Instance.Id + } + }; + DatabaseContext.Instances.Attach(compileJob.RevisionInformation.Instance); + } databaseContext.CompileJobs.Add(compileJob); //default ct because we don't want to give up after getting this far diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index 0b97551b2a..168e747e3f 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -150,6 +150,7 @@ namespace Tgstation.Server.Host.Core options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.CheckAdditionalContent = true; options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error; + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); var databaseConfiguration = databaseConfigurationSection.Get(); diff --git a/src/Tgstation.Server.Host/Core/JobManager.cs b/src/Tgstation.Server.Host/Core/JobManager.cs index c059cdb7ed..b05e90757c 100644 --- a/src/Tgstation.Server.Host/Core/JobManager.cs +++ b/src/Tgstation.Server.Host/Core/JobManager.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; @@ -148,7 +149,7 @@ namespace Tgstation.Server.Host.Core var databaseContext = scope.ServiceProvider.GetRequiredService(); //mark all jobs as cancelled - var enumerator = await databaseContext.Jobs.Where(y => !y.Cancelled.Value && !y.StoppedAt.HasValue).Select(y => y.Id).ToAsyncEnumerable().ToList(cancellationToken).ConfigureAwait(false); + var enumerator = await databaseContext.Jobs.Where(y => !y.Cancelled.Value && !y.StoppedAt.HasValue).Select(y => y.Id).ToListAsync(cancellationToken).ConfigureAwait(false); foreach(var I in enumerator) { var job = new Job { Id = I }; diff --git a/src/Tgstation.Server.Host/IO/DefaultIOManager.cs b/src/Tgstation.Server.Host/IO/DefaultIOManager.cs index c4b235b3d7..65ae98fd1f 100644 --- a/src/Tgstation.Server.Host/IO/DefaultIOManager.cs +++ b/src/Tgstation.Server.Host/IO/DefaultIOManager.cs @@ -133,7 +133,7 @@ namespace Tgstation.Server.Host.IO throw new ArgumentNullException(nameof(dest)); using (var srcStream = new FileStream(ResolvePath(src), FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize, true)) using (var destStream = new FileStream(ResolvePath(dest), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize, true)) - await srcStream.CopyToAsync(destStream, DefaultBufferSize, cancellationToken).ConfigureAwait(false); + await srcStream.CopyToAsync(destStream, 81920, cancellationToken).ConfigureAwait(false); } ///