Cleanup cleanup

This commit is contained in:
Cyberboss
2018-05-04 13:48:42 -04:00
parent b8b652c7a5
commit 40ffe4bf2f
9 changed files with 95 additions and 89 deletions
@@ -4,9 +4,9 @@
public sealed class CompileJob : Internal.CompileJob
{
/// <summary>
/// The <see cref="User"/> that triggered the job
/// The <see cref="Job"/> relating to this job
/// </summary>
public User TriggeredBy { get; set; }
public Job Job { get; set; }
/// <summary>
/// Git revision the compiler ran on. Not modifiable
@@ -13,18 +13,6 @@ namespace Tgstation.Server.Api.Models.Internal
/// </summary>
public long Id { get; set; }
/// <summary>
/// When the compilation started
/// </summary>
[Required]
public DateTimeOffset StartedAt { get; set; }
/// <summary>
/// When the compilation finished
/// </summary>
[Required]
public DateTimeOffset FinishedAt { get; set; }
/// <summary>
/// If the DMAPI version detected is compatible
/// </summary>
@@ -1,4 +1,5 @@
using System;
using Tgstation.Server.Api.Rights;
namespace Tgstation.Server.Api.Models.Internal
{
@@ -43,5 +44,17 @@ namespace Tgstation.Server.Api.Models.Internal
/// </summary>
[Permissions(DenyWrite = true)]
public bool Cancelled { get; set; }
/// <summary>
/// The <see cref="RightsType"/> of <see cref="CancelRight"/> if it can be cancelled
/// </summary>
[Permissions(DenyWrite = true)]
public RightsType? CancelRightsType { get; set; }
/// <summary>
/// The <see cref="Rights"/> required to cancel the <see cref="Job"/>
/// </summary>
[Permissions(DenyWrite = true)]
public int? CancelRight { get; set; }
}
}
+6 -6
View File
@@ -11,16 +11,16 @@
[Permissions(DenyWrite = true)]
public int Progress { get; set; }
/// <summary>
/// If the current user has permission to cancel the job
/// </summary>
[Permissions(DenyWrite = true)]
public bool UserCanCancel { get; set; }
/// <summary>
/// The <see cref="User"/> that started the job
/// </summary>
[Permissions(DenyWrite = true)]
public User StartedBy { get; set; }
/// <summary>
/// The <see cref="User"/> that cancelled the job
/// </summary>
[Permissions(DenyWrite = true)]
public User CancelledBy { get; set; }
}
}
@@ -194,67 +194,59 @@ namespace Tgstation.Server.Host.Components
var job = new Host.Models.CompileJob
{
DirectoryName = Guid.NewGuid(),
StartedAt = DateTimeOffset.Now,
DmeName = dmeName
};
try
await ioManager.CreateDirectory(job.DirectoryName.ToString(), cancellationToken).ConfigureAwait(false);
var dirA = ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName);
var dirB = ioManager.ConcatPath(job.DirectoryName.ToString(), "B");
async Task CleanupFailedCompile()
{
await ioManager.CreateDirectory(job.DirectoryName.ToString(), cancellationToken).ConfigureAwait(false);
var dirA = ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName);
var dirB = ioManager.ConcatPath(job.DirectoryName.ToString(), "B");
async Task CleanupFailedCompile()
{
try
{
await ioManager.DeleteDirectory(job.DirectoryName.ToString(), CancellationToken.None).ConfigureAwait(false);
}
catch { }
};
try
{
//copy the repository
var fullDirA = ioManager.ResolvePath(dirA);
using (repository)
await repository.CopyTo(fullDirA, cancellationToken).ConfigureAwait(false);
await ModifyDme(job, cancellationToken).ConfigureAwait(false);
//run compiler, verify api
var ddVerified = await byond.UseExecutables(async (dreamMakerPath, dreamDaemonPath) =>
{
await RunDreamMaker(dreamMakerPath, job, cancellationToken).ConfigureAwait(false);
return job.ExitCode == 0 && await VerifyApi(dreamDaemonPath, job, cancellationToken).ConfigureAwait(false);
}, true).ConfigureAwait(false);
if (!ddVerified)
//server never validated or compile failed
await CleanupFailedCompile().ConfigureAwait(false);
else
{
job.DMApiValidated = true;
//duplicate the dmb et al
await ioManager.CopyDirectory(dirA, dirB, null, cancellationToken).ConfigureAwait(false);
//symlink in the static data
var symATask = configuration.SymlinkStaticFilesTo(fullDirA, cancellationToken);
await configuration.SymlinkStaticFilesTo(ioManager.ResolvePath(dirB), cancellationToken).ConfigureAwait(false);
await symATask.ConfigureAwait(false);
}
return job;
await ioManager.DeleteDirectory(job.DirectoryName.ToString(), CancellationToken.None).ConfigureAwait(false);
}
catch
{
await CleanupFailedCompile().ConfigureAwait(false);
throw;
}
}
finally
catch { }
};
try
{
job.FinishedAt = DateTimeOffset.Now;
//copy the repository
var fullDirA = ioManager.ResolvePath(dirA);
using (repository)
await repository.CopyTo(fullDirA, cancellationToken).ConfigureAwait(false);
await ModifyDme(job, cancellationToken).ConfigureAwait(false);
//run compiler, verify api
var ddVerified = await byond.UseExecutables(async (dreamMakerPath, dreamDaemonPath) =>
{
await RunDreamMaker(dreamMakerPath, job, cancellationToken).ConfigureAwait(false);
return job.ExitCode == 0 && await VerifyApi(dreamDaemonPath, job, cancellationToken).ConfigureAwait(false);
}, true).ConfigureAwait(false);
if (!ddVerified)
//server never validated or compile failed
await CleanupFailedCompile().ConfigureAwait(false);
else
{
job.DMApiValidated = true;
//duplicate the dmb et al
await ioManager.CopyDirectory(dirA, dirB, null, cancellationToken).ConfigureAwait(false);
//symlink in the static data
var symATask = configuration.SymlinkStaticFilesTo(fullDirA, cancellationToken);
await configuration.SymlinkStaticFilesTo(ioManager.ResolvePath(dirB), cancellationToken).ConfigureAwait(false);
await symATask.ConfigureAwait(false);
}
return job;
}
catch
{
await CleanupFailedCompile().ConfigureAwait(false);
throw;
}
}
}
@@ -40,13 +40,16 @@ namespace Tgstation.Server.Host.Controllers
var job = new Job
{
Description = "Compile active repository code",
StartedBy = AuthenticationContext.User
StartedBy = AuthenticationContext.User,
CancelRightsType = RightsType.DreamMaker,
CancelRight = (int)DreamMakerRights.CancelCompile
};
await jobManager.RegisterOperation(job, (serviceProvider, ct) => RunCompile(serviceProvider, Instance, AuthenticationContext.Clone(), ct), cancellationToken).ConfigureAwait(false);
await jobManager.RegisterOperation(job, (paramJob, serviceProvider, ct) => RunCompile(paramJob, serviceProvider, Instance, ct), cancellationToken).ConfigureAwait(false);
return Json(job);
}
/// <inheritdoc />
[TgsAuthorize(DreamMakerRights.CancelCompile)]
public override async Task<IActionResult> Delete([FromBody] Api.Models.CompileJob model, CancellationToken cancellationToken)
{
//alias for cancelling the latest job
@@ -60,12 +63,12 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// Run the compile job and insert it into the database
/// </summary>
/// <param name="job">The running <see cref="Job"/></param>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> for the operation</param>
/// <param name="instanceModel">The <see cref="Models.Instance"/> for the operation</param>
/// <param name="authenticationContext">The <see cref="IAuthenticationContext"/> for the operation</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns></returns>
static async Task RunCompile(IServiceProvider serviceProvider, Models.Instance instanceModel, IAuthenticationContext authenticationContext, CancellationToken cancellationToken)
/// <returns>A <see cref="Task"/> representing the running operation</returns>
static async Task RunCompile(Job job, IServiceProvider serviceProvider, Models.Instance instanceModel, CancellationToken cancellationToken)
{
var instanceManager = serviceProvider.GetRequiredService<IInstanceManager>();
var databaseContext = serviceProvider.GetRequiredService<IDatabaseContext>();
@@ -82,7 +85,7 @@ namespace Tgstation.Server.Host.Controllers
compileJob = await instance.DreamMaker.Compile(projectName, repo, cancellationToken).ConfigureAwait(false);
}
compileJob.TriggeredBy = authenticationContext.User;
compileJob.Job = job;
compileJob.RevisionInformation = await revInfoTask.ConfigureAwait(false);
databaseContext.CompileJobs.Add(compileJob);
@@ -15,10 +15,10 @@ namespace Tgstation.Server.Host.Core
/// Registers a given <see cref="Job"/> and begins running it
/// </summary>
/// <param name="job">The <see cref="Job"/></param>
/// <param name="operation">The operation to run</param>
/// <param name="operation">The operation to run taking the started <see cref="Job"/>, a <see cref="IServiceProvider"/> and a <see cref="CancellationToken"/></param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task"/> representing a running operation</returns>
Task RegisterOperation(Job job, Func<IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken);
Task RegisterOperation(Job job, Func<Job, IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken);
/// <summary>
/// Wait for a given <paramref name="job"/> to complete
+5 -4
View File
@@ -53,20 +53,21 @@ namespace Tgstation.Server.Host.Core
/// <param name="operation">The operation for the <paramref name="job"/></param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
/// <returns>A <see cref="Task"/> representing the running operation</returns>
async Task RunJob(Job job, Func<IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken)
async Task RunJob(Job job, Func<Job, IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken)
{
using (var scope = serviceProvider.CreateScope())
{
IDatabaseContext databaseContext = null;
try
{
var oldJob = job;
job = new Job { Id = oldJob.Id };
try
{
await operation(scope.ServiceProvider, cancellationToken).ConfigureAwait(false);
await operation(job, scope.ServiceProvider, cancellationToken).ConfigureAwait(false);
}
finally
{
job = new Job { Id = job.Id };
databaseContext = scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
databaseContext.Jobs.Attach(job);
}
@@ -85,7 +86,7 @@ namespace Tgstation.Server.Host.Core
}
/// <inheritdoc />
public async Task RegisterOperation(Job job, Func<IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken)
public async Task RegisterOperation(Job job, Func<Job, IServiceProvider, CancellationToken, Task> operation, CancellationToken cancellationToken)
{
using (var scope = serviceProvider.CreateScope())
{
+12 -3
View File
@@ -1,16 +1,25 @@
namespace Tgstation.Server.Host.Models
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Host.Models
{
/// <inheritdoc />
public sealed class CompileJob : Api.Models.Internal.CompileJob
{
/// <summary>
/// See <see cref="Api.Models.CompileJob.TriggeredBy"/>
/// The <see cref="Api.Models.Internal.Job.Id"/> of <see cref="Job"/>
/// </summary>
public User TriggeredBy { get; set; }
public long JobId { get; set; }
/// <summary>
/// See <see cref="Api.Models.CompileJob.Job"/>
/// </summary>
[Required]
public Job Job { get; set; }
/// <summary>
/// See <see cref="Api.Models.CompileJob.RevisionInformation"/>
/// </summary>
[Required]
public RevisionInformation RevisionInformation { get; set; }
}
}