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);
}
///