From cad7ddc10f58e667e81dfc47139716ee8a8b7720 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sat, 15 Sep 2018 14:03:44 -0400 Subject: [PATCH] Merge DreamMakerController and Instance auto update compile functions. Instance auto update now properly specifies it as a job --- .../Components/IInstance.cs | 11 ++ .../Components/Instance.cs | 130 ++++++++++++------ .../Controllers/DreamMakerController.cs | 68 +-------- 3 files changed, 99 insertions(+), 110 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/IInstance.cs b/src/Tgstation.Server.Host/Components/IInstance.cs index 8e5b2edf80..cf2c527a8a 100644 --- a/src/Tgstation.Server.Host/Components/IInstance.cs +++ b/src/Tgstation.Server.Host/Components/IInstance.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Hosting; using System; +using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Host.Components.Byond; using Tgstation.Server.Host.Components.Chat; @@ -75,5 +76,15 @@ namespace Tgstation.Server.Host.Components /// The new auto update inteval /// A representing the running operation Task SetAutoUpdateInterval(uint newInterval); + + /// + /// Run the compile job and insert it into the database. Meant to be called by a + /// + /// The running + /// The for the operation + /// The to report compilation progress + /// The for the operation + /// A representing the running operation + Task CompileProcess(Job job, IServiceProvider serviceProvider, Action progressReporter, 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 46b5dc3541..1e99e0b49a 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -1,9 +1,11 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Tgstation.Server.Api.Rights; using Tgstation.Server.Host.Components.Byond; using Tgstation.Server.Host.Components.Chat; using Tgstation.Server.Host.Components.Compiler; @@ -114,6 +116,59 @@ namespace Tgstation.Server.Host.Components RepositoryManager.Dispose(); } + /// + public async Task CompileProcess(Job job, IServiceProvider serviceProvider, Action progressReporter, CancellationToken cancellationToken) + { + var databaseContext = serviceProvider.GetRequiredService(); + + var ddSettingsTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == metadata.Id).Select(x => new DreamDaemonSettings + { + StartupTimeout = x.StartupTimeout, + SecurityLevel = x.SecurityLevel + }).FirstOrDefaultAsync(cancellationToken); + + var dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(cancellationToken).ConfigureAwait(false); + if (dreamMakerSettings == default) + throw new JobException("Missing DreamMakerSettings in DB!"); + var ddSettings = await ddSettingsTask.ConfigureAwait(false); + if (ddSettings == default) + throw new JobException("Missing DreamDaemonSettings in DB!"); + + CompileJob compileJob; + RevisionInformation revInfo; + using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false)) + { + if (repo == null) + throw new JobException("Missing Repository!"); + + var repoSha = repo.Head; + revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).FirstOrDefaultAsync().ConfigureAwait(false); + + if (revInfo == default) + { + revInfo = new RevisionInformation + { + CommitSha = repoSha, + OriginCommitSha = repoSha, + Instance = new Models.Instance + { + Id = metadata.Id + } + }; + logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, repoSha); + databaseContext.Instances.Attach(revInfo.Instance); + } + + compileJob = await DreamMaker.Compile(revInfo, dreamMakerSettings, ddSettings.SecurityLevel.Value, ddSettings.StartupTimeout.Value, repo, cancellationToken).ConfigureAwait(false); + } + + compileJob.Job = job; + + databaseContext.CompileJobs.Add(compileJob); //will be saved by job context + + job.PostComplete = ct => CompileJobConsumer.LoadCompileJob(compileJob, ct); + } + /// /// Pull the repository and compile for every set of given /// @@ -129,33 +184,32 @@ namespace Tgstation.Server.Host.Components try { - CompileJob job = null; + Job job = null; + Models.User user = null; //need this the whole time + var noRepo = false; await databaseContextFactory.UseContext(async (db) => { - //start up queries we'll need in the future - var instanceQuery = db.Instances.Where(x => x.Id == metadata.Id); - var ddSettingsTask = instanceQuery.Select(x => x.DreamDaemonSettings).Select(x => new DreamDaemonSettings - { - StartupTimeout = x.StartupTimeout, - SecurityLevel = x.SecurityLevel - }).FirstAsync(cancellationToken); - var dmSettingsTask = instanceQuery.Select(x => x.DreamMakerSettings).FirstAsync(cancellationToken); - var repositorySettingsTask = instanceQuery.Select(x => x.RepositorySettings).FirstAsync(cancellationToken); + var userTask = db.Users.FirstAsync(cancellationToken); + + var repositorySettingsTask = db.RepositorySettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(cancellationToken); using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false)) { if (repo == null) + { + //no repo, no auto updates + noRepo = true; return; + } - //start the rev info query - var startSha = repo.Head; - var revInfoTask = instanceQuery.SelectMany(x => x.RevisionInformations).Where(x => x.CommitSha == startSha).FirstOrDefaultAsync(cancellationToken); - - //need repo setting to fetch var repositorySettings = await repositorySettingsTask.ConfigureAwait(false); + + //the main point of auto update is to pull the remote await repo.FetchOrigin(repositorySettings.AccessUser, repositorySettings.AccessToken, null, cancellationToken).ConfigureAwait(false); + var startSha = repo.Head; + //take appropriate auto update actions bool shouldSyncTracked; if (repositorySettings.AutoUpdatesKeepTestMerges.Value) @@ -174,38 +228,28 @@ namespace Tgstation.Server.Host.Components //synch if necessary if (repositorySettings.AutoUpdatesSynchronize.Value && startSha != repo.Head) await repo.Sychronize(repositorySettings.AccessUser, repositorySettings.AccessToken, shouldSyncTracked, cancellationToken).ConfigureAwait(false); - - //finish other queries - var dmSettings = await dmSettingsTask.ConfigureAwait(false); - var ddSettings = await ddSettingsTask.ConfigureAwait(false); - var revInfo = await revInfoTask.ConfigureAwait(false); - - //null rev info handling - if (revInfo == default) - { - var currentSha = repo.Head; - revInfo = new RevisionInformation - { - CommitSha = currentSha, - OriginCommitSha = currentSha, - Instance = new Models.Instance - { - Id = metadata.Id - } - }; - logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, currentSha); - db.Instances.Attach(revInfo.Instance); - } - - //finally start compile - job = await DreamMaker.Compile(revInfo, dmSettings, ddSettings.SecurityLevel.Value, ddSettings.StartupTimeout.Value, repo, cancellationToken).ConfigureAwait(false); } - db.CompileJobs.Add(job); - await db.Save(cancellationToken).ConfigureAwait(false); + user = await userTask.ConfigureAwait(false); + + //finally set up the job + job = new Job + { + StartedBy = user, + Instance = new Models.Instance + { + Id = metadata.Id + }, + Description = "Scheduled code deployment", + CancelRightsType = RightsType.DreamMaker, + CancelRight = (ulong)DreamMakerRights.CancelCompile + }; + + await jobManager.RegisterOperation(job, CompileProcess, cancellationToken).ConfigureAwait(false); }).ConfigureAwait(false); - await CompileJobConsumer.LoadCompileJob(job, cancellationToken).ConfigureAwait(false); + if(!noRepo) + await jobManager.WaitForJobCompletion(job, user, cancellationToken, default).ConfigureAwait(false); } catch (OperationCanceledException) { diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs index 746f04157b..3c12cdc2bf 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Linq; @@ -10,7 +9,6 @@ using System.Threading.Tasks; using Tgstation.Server.Api; using Tgstation.Server.Api.Rights; using Tgstation.Server.Host.Components; -using Tgstation.Server.Host.Components.Repository; using Tgstation.Server.Host.Core; using Tgstation.Server.Host.Models; using Tgstation.Server.Host.Security; @@ -97,7 +95,7 @@ namespace Tgstation.Server.Host.Controllers CancelRight = (ulong)DreamMakerRights.CancelCompile, Instance = Instance }; - await jobManager.RegisterOperation(job, (paramJob, serviceProvider, progressReporter, ct) => RunCompile(paramJob, serviceProvider, Instance, ct), cancellationToken).ConfigureAwait(false); + await jobManager.RegisterOperation(job, instanceManager.GetInstance(Instance).CompileProcess, cancellationToken).ConfigureAwait(false); return Accepted(job.ToApi()); } @@ -129,69 +127,5 @@ namespace Tgstation.Server.Host.Controllers await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); return await Read(cancellationToken).ConfigureAwait(false); } - - /// - /// Run the compile job and insert it into the database - /// - /// The running - /// The for the operation - /// The for the operation - /// The for the operation - /// A representing the running operation - async Task RunCompile(Job job, IServiceProvider serviceProvider, Models.Instance instanceModel, CancellationToken cancellationToken) - { - var instanceManager = serviceProvider.GetRequiredService(); - var databaseContext = serviceProvider.GetRequiredService(); - - var ddSettingsTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == instanceModel.Id).Select(x => new DreamDaemonSettings - { - StartupTimeout = x.StartupTimeout, - SecurityLevel = x.SecurityLevel - }).FirstOrDefaultAsync(cancellationToken); - - - var dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == instanceModel.Id).FirstAsync(cancellationToken).ConfigureAwait(false); - if (dreamMakerSettings == default) - throw new JobException("Missing DreamMakerSettings in DB!"); - var ddSettings = await ddSettingsTask.ConfigureAwait(false); - if (ddSettings == default) - throw new JobException("Missing DreamDaemonSettings in DB!"); - - var instance = instanceManager.GetInstance(instanceModel); - - CompileJob compileJob; - RevisionInformation revInfo; - using (var repo = await instance.RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false)) - { - if (repo == null) - throw new JobException("Missing Repository!"); - - var repoSha = repo.Head; - revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).FirstOrDefaultAsync().ConfigureAwait(false); - - if (revInfo == default) - { - revInfo = new RevisionInformation - { - CommitSha = repoSha, - OriginCommitSha = repoSha, - Instance = new Models.Instance - { - Id = Instance.Id - } - }; - Logger.LogWarning(Repository.OriginTrackingErrorTemplate, repoSha); - databaseContext.Instances.Attach(revInfo.Instance); - } - - compileJob = await instance.DreamMaker.Compile(revInfo, dreamMakerSettings, ddSettings.SecurityLevel.Value, ddSettings.StartupTimeout.Value, repo, cancellationToken).ConfigureAwait(false); - } - - compileJob.Job = job; - - databaseContext.CompileJobs.Add(compileJob); //will be saved by job context - - job.PostComplete = ct => instance.CompileJobConsumer.LoadCompileJob(compileJob, ct); - } } }