diff --git a/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs b/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs index 15e992da83..5e63fa62a3 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs @@ -76,14 +76,21 @@ namespace Tgstation.Server.Host.Components.Chat.Commands head = repo.Head; } - await databaseContextFactory.UseContext(async db => results = await db.RevisionInformations.Where(x => x.Instance.Id == instance.Id && x.CommitSha == head) - .SelectMany(x => x.ActiveTestMerges) - .Select(x => x.TestMerge) - .Select(x => new Models.TestMerge - { - Number = x.Number, - PullRequestRevision = x.PullRequestRevision - }).ToListAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); + await databaseContextFactory.UseContext( + async db => results = await db + .RevisionInformations + .AsQueryable() + .Where(x => x.Instance.Id == instance.Id && x.CommitSha == head) + .SelectMany(x => x.ActiveTestMerges) + .Select(x => x.TestMerge) + .Select(x => new Models.TestMerge + { + Number = x.Number, + PullRequestRevision = x.PullRequestRevision + }) + .ToListAsync(cancellationToken) + .ConfigureAwait(false)) + .ConfigureAwait(false); } else { diff --git a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs index 281bb892e9..978586af70 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs @@ -197,11 +197,17 @@ namespace Tgstation.Server.Host.Components.Deployment // ensure we have the entire compile job tree logger.LogTrace("Loading compile job {0}...", compileJob.Id); - await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id) - .Include(x => x.Job).ThenInclude(x => x.StartedBy) - .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy) - .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy) - .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query + await databaseContextFactory.UseContext( + async db => compileJob = await db + .CompileJobs + .AsQueryable() + .Where(x => x.Id == compileJob.Id) + .Include(x => x.Job).ThenInclude(x => x.StartedBy) + .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy) + .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy) + .FirstAsync(cancellationToken) + .ConfigureAwait(false)) + .ConfigureAwait(false); // can't wait to see that query if (!compileJob.Job.StoppedAt.HasValue) { @@ -269,8 +275,12 @@ namespace Tgstation.Server.Host.Components.Deployment // find the uids of locked directories await databaseContextFactory.UseContext(async db => { - jobUidsToNotErase = (await db.CompileJobs.Where( - x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)) + jobUidsToNotErase = (await db + .CompileJobs + .AsQueryable() + .Where( + x => x.Job.Instance.Id == instance.Id + && jobIdsToSkip.Contains(x.Id)) .Select(x => x.DirectoryName.Value) .ToListAsync(cancellationToken) .ConfigureAwait(false)) diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index 28cf3d8e0c..e35cfd5b15 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -506,6 +506,7 @@ namespace Tgstation.Server.Host.Components.Deployment ddSettings = await databaseContext .DreamDaemonSettings + .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .Select(x => new Models.DreamDaemonSettings { @@ -516,12 +517,18 @@ namespace Tgstation.Server.Host.Components.Deployment if (ddSettings == default) throw new JobException(ErrorCode.InstanceMissingDreamDaemonSettings); - dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(cancellationToken).ConfigureAwait(false); + dreamMakerSettings = await databaseContext + .DreamMakerSettings + .AsQueryable() + .Where(x => x.InstanceId == metadata.Id) + .FirstAsync(cancellationToken) + .ConfigureAwait(false); if (dreamMakerSettings == default) throw new JobException(ErrorCode.InstanceMissingDreamMakerSettings); repositorySettings = await databaseContext .RepositorySettings + .AsQueryable() .Where(x => x.InstanceId == metadata.Id) .Select(x => new Models.RepositorySettings { @@ -550,6 +557,7 @@ namespace Tgstation.Server.Host.Components.Deployment var repoSha = repo.Head; revInfo = await databaseContext .RevisionInformations + .AsQueryable() .Where(x => x.CommitSha == repoSha && x.Instance.Id == metadata.Id) .Include(x => x.ActiveTestMerges) .ThenInclude(x => x.TestMerge) @@ -686,7 +694,9 @@ namespace Tgstation.Server.Host.Components.Deployment /// A resulting in the average of the 10 previous deployments or if there are none. async Task CalculateExpectedDeploymentTime(IDatabaseContext databaseContext, CancellationToken cancellationToken) { - var previousCompileJobs = await databaseContext.CompileJobs + var previousCompileJobs = await databaseContext + .CompileJobs + .AsQueryable() .Where(x => x.Job.Instance.Id == metadata.Id) .OrderByDescending(x => x.Job.StoppedAt) .Take(10) diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index d1c281352b..2782ee9934 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -162,6 +162,7 @@ namespace Tgstation.Server.Host.Components await databaseContextFactory.UseContext( async (db) => user = await db .Users + .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(Api.Models.User.AdminName)) .FirstAsync(cancellationToken) .ConfigureAwait(false)) @@ -189,7 +190,11 @@ namespace Tgstation.Server.Host.Components await databaseContextFactory.UseContext( async databaseContext => { - var repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(jobCancellationToken); + var repositorySettingsTask = databaseContext + .RepositorySettings + .AsQueryable() + .Where(x => x.InstanceId == metadata.Id) + .FirstAsync(jobCancellationToken); const int NumSteps = 3; var doneSteps = 0; @@ -225,6 +230,7 @@ namespace Tgstation.Server.Host.Components bool hasDbChanges = false; Task LoadRevInfo() => databaseContext.RevisionInformations + .AsQueryable() .Where(x => x.CommitSha == startSha && x.Instance.Id == metadata.Id) .Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge) .FirstOrDefaultAsync(cancellationToken); @@ -294,6 +300,7 @@ namespace Tgstation.Server.Host.Components var currentHead = repo.Head; currentRevInfo = await databaseContext.RevisionInformations + .AsQueryable() .Where(x => x.CommitSha == currentHead && x.Instance.Id == metadata.Id) .FirstOrDefaultAsync(jobCancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs index 3e61925a27..062dca8163 100644 --- a/src/Tgstation.Server.Host/Components/InstanceManager.cs +++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs @@ -213,10 +213,14 @@ namespace Tgstation.Server.Host.Components var tasks = new List(); await databaseContextFactory.UseContext(async db => { - var jobs = db.Jobs.Where(x => x.Instance.Id == metadata.Id).Select(x => new Models.Job - { - Id = x.Id - }).ToAsyncEnumerable(); + var jobs = db + .Jobs + .AsQueryable() + .Where(x => x.Instance.Id == metadata.Id) + .Select(x => new Models.Job + { + Id = x.Id + }); await jobs.ForEachAsync(job => { lock (tasks) @@ -271,7 +275,10 @@ namespace Tgstation.Server.Host.Components var factoryStartup = instanceFactory.StartAsync(cancellationToken); await databaseContext.Initialize(cancellationToken).ConfigureAwait(false); await jobManager.StartAsync(cancellationToken).ConfigureAwait(false); - var dbInstances = databaseContext.Instances.Where(x => x.Online.Value) + var dbInstances = databaseContext + .Instances + .AsQueryable() + .Where(x => x.Online.Value) .Include(x => x.RepositorySettings) .Include(x => x.ChatSettings) .ThenInclude(x => x.Channels) diff --git a/src/Tgstation.Server.Host/Components/Session/ReattachInfoHandler.cs b/src/Tgstation.Server.Host/Components/Session/ReattachInfoHandler.cs index c194aad5b0..001f0a1087 100644 --- a/src/Tgstation.Server.Host/Components/Session/ReattachInfoHandler.cs +++ b/src/Tgstation.Server.Host/Components/Session/ReattachInfoHandler.cs @@ -56,7 +56,11 @@ namespace Tgstation.Server.Host.Components.Session logger.LogDebug("Saving reattach information: {0}...", reattachInformation); - var deleteTask = db.WatchdogReattachInformations.Where(x => x.InstanceId == metadata.Id).DeleteAsync(cancellationToken); + var deleteTask = db + .WatchdogReattachInformations + .AsQueryable() + .Where(x => x.InstanceId == metadata.Id) + .DeleteAsync(cancellationToken); Models.ReattachInformation ConvertReattachInfo(ReattachInformation wdInfo) { @@ -93,7 +97,9 @@ namespace Tgstation.Server.Host.Components.Session Models.DualReattachInformation result = null; await databaseContextFactory.UseContext(async (db) => { - var instance = await db.Instances.Where(x => x.Id == metadata.Id) + var instance = await db.Instances + .AsQueryable() + .Where(x => x.Id == metadata.Id) .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Alpha).ThenInclude(x => x.CompileJob) .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Bravo).ThenInclude(x => x.CompileJob) .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs index 74b3e06371..fb20b8fc48 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/WatchdogBase.cs @@ -857,6 +857,7 @@ namespace Tgstation.Server.Host.Components.Watchdog await databaseContextFactory.UseContext( async db => adminUserId = await db .Users + .AsQueryable() .Where(x => x.CanonicalName == Models.User.CanonicalizeName(Api.Models.User.AdminName)) .Select(x => x.Id) .FirstAsync(cancellationToken) diff --git a/src/Tgstation.Server.Host/Controllers/ChatController.cs b/src/Tgstation.Server.Host/Controllers/ChatController.cs index 321a004b71..153406d210 100644 --- a/src/Tgstation.Server.Host/Controllers/ChatController.cs +++ b/src/Tgstation.Server.Host/Controllers/ChatController.cs @@ -80,6 +80,7 @@ namespace Tgstation.Server.Host.Controllers var countOfExistingBotsInInstance = await DatabaseContext .ChatBots + .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .CountAsync(cancellationToken) .ConfigureAwait(false); @@ -140,7 +141,14 @@ namespace Tgstation.Server.Host.Controllers public async Task Delete(long id, CancellationToken cancellationToken) { var instance = instanceManager.GetInstance(Instance); - await Task.WhenAll(instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext.ChatBots.Where(x => x.Id == id).DeleteAsync(cancellationToken)).ConfigureAwait(false); + await Task.WhenAll( + instance.Chat.DeleteConnection(id, cancellationToken), + DatabaseContext + .ChatBots + .AsQueryable() + .Where(x => x.Id == id) + .DeleteAsync(cancellationToken)) + .ConfigureAwait(false); return Ok(); } @@ -156,7 +164,11 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(typeof(IEnumerable), 200)] public async Task List(CancellationToken cancellationToken) { - var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id).Include(x => x.Channels); + var query = DatabaseContext + .ChatBots + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .Include(x => x.Channels); var results = await query.ToListAsync(cancellationToken).ConfigureAwait(false); @@ -183,7 +195,10 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(410)] public async Task GetId(long id, CancellationToken cancellationToken) { - var query = DatabaseContext.ChatBots.Where(x => x.Id == id).Include(x => x.Channels); + var query = DatabaseContext.ChatBots + .AsQueryable() + .Where(x => x.Id == id) + .Include(x => x.Channels); var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); if (results == default) @@ -221,7 +236,11 @@ namespace Tgstation.Server.Host.Controllers if (earlyOut != null) return earlyOut; - var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels); + var query = DatabaseContext + .ChatBots + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id && x.Id == model.Id) + .Include(x => x.Channels); var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs index bae044577b..f2ed58b9d8 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs @@ -109,7 +109,13 @@ namespace Tgstation.Server.Host.Controllers if (settings == null) { - settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + settings = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .Select(x => x.DreamDaemonSettings) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (settings == default) return StatusCode((int)HttpStatusCode.Gone); } @@ -191,7 +197,13 @@ namespace Tgstation.Server.Host.Controllers return BadRequest(new ErrorMessage(ErrorCode.DreamDaemonDoubleSoft)); // alias for changing DD settings - var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var current = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .Select(x => x.DreamDaemonSettings) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (current == default) return StatusCode((int)HttpStatusCode.Gone); diff --git a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs index 3f011a9cea..bf2354fc98 100644 --- a/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs +++ b/src/Tgstation.Server.Host/Controllers/DreamMakerController.cs @@ -61,7 +61,12 @@ namespace Tgstation.Server.Host.Controllers public async Task Read(CancellationToken cancellationToken) { var instance = instanceManager.GetInstance(Instance); - var dreamMakerSettings = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var dreamMakerSettings = await DatabaseContext + .DreamMakerSettings + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); return Json(dreamMakerSettings.ToApi()); } @@ -79,7 +84,9 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(404)] public async Task GetId(long id, CancellationToken cancellationToken) { - var compileJob = await DatabaseContext.CompileJobs + var compileJob = await DatabaseContext + .CompileJobs + .AsQueryable() .Where(x => x.Id == id && x.Job.Instance.Id == Instance.Id) .Include(x => x.Job).ThenInclude(x => x.StartedBy) .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy) @@ -101,10 +108,17 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(typeof(List), 200)] public async Task List(CancellationToken cancellationToken) { - var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StoppedAt).Select(x => new EntityId - { - Id = x.Id - }).ToListAsync(cancellationToken).ConfigureAwait(false); + var compileJobs = await DatabaseContext + .CompileJobs + .AsQueryable() + .Where(x => x.Job.Instance.Id == Instance.Id) + .OrderByDescending(x => x.Job.StoppedAt) + .Select(x => new EntityId + { + Id = x.Id + }) + .ToListAsync(cancellationToken) + .ConfigureAwait(false); return Json(compileJobs); } @@ -159,7 +173,12 @@ namespace Tgstation.Server.Host.Controllers if (model.ApiValidationPort == 0) throw new InvalidOperationException("ApiValidationPort cannot be 0!"); - var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var hostModel = await DatabaseContext + .DreamMakerSettings + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (hostModel == null) return StatusCode((int)HttpStatusCode.Gone); diff --git a/src/Tgstation.Server.Host/Controllers/HomeController.cs b/src/Tgstation.Server.Host/Controllers/HomeController.cs index eff10e36d1..b10307a232 100644 --- a/src/Tgstation.Server.Host/Controllers/HomeController.cs +++ b/src/Tgstation.Server.Host/Controllers/HomeController.cs @@ -196,12 +196,12 @@ namespace Tgstation.Server.Host.Controllers using (systemIdentity) { // Get the user from the database - IQueryable query; + IQueryable query = DatabaseContext.Users.AsQueryable(); string canonicalName = Models.User.CanonicalizeName(ApiHeaders.Username); if (systemIdentity == null) - query = DatabaseContext.Users.Where(x => x.CanonicalName == canonicalName); + query = query.Where(x => x.CanonicalName == canonicalName); else - query = DatabaseContext.Users.Where(x => x.CanonicalName == canonicalName || x.SystemIdentifier == systemIdentity.Uid); + query = query.Where(x => x.CanonicalName == canonicalName || x.SystemIdentifier == systemIdentity.Uid); var users = await query.Select(x => new User { Id = x.Id, diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs index ed76728410..fe2dbb1233 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs @@ -174,18 +174,25 @@ namespace Tgstation.Server.Host.Controllers var newCancellationToken = cts.Token; try { - await DatabaseContext.Instances.ForEachAsync( - otherInstance => + await DatabaseContext + .Instances + .AsQueryable() + .Select(x => new Models.Instance { - if (++countOfOtherInstances >= generalConfiguration.InstanceLimit) - earlyOut ??= Conflict(new ErrorMessage(ErrorCode.InstanceLimitReached)); - else if (InstanceIsChildOf(otherInstance.Path)) - earlyOut ??= Conflict(new ErrorMessage(ErrorCode.InstanceAtConflictingPath)); + Path = x.Path + }) + .ForEachAsync( + otherInstance => + { + if (++countOfOtherInstances >= generalConfiguration.InstanceLimit) + earlyOut ??= Conflict(new ErrorMessage(ErrorCode.InstanceLimitReached)); + else if (InstanceIsChildOf(otherInstance.Path)) + earlyOut ??= Conflict(new ErrorMessage(ErrorCode.InstanceAtConflictingPath)); - if (earlyOut != null && !newCancellationToken.IsCancellationRequested) - cts.Cancel(); - }, - newCancellationToken) + if (earlyOut != null && !newCancellationToken.IsCancellationRequested) + cts.Cancel(); + }, + newCancellationToken) .ConfigureAwait(false); } catch (OperationCanceledException) @@ -312,7 +319,10 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(410)] public async Task Delete(long id, CancellationToken cancellationToken) { - var originalModel = await DatabaseContext.Instances.Where(x => x.Id == id) + var originalModel = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == id) .Include(x => x.WatchdogReattachInformation) .Include(x => x.WatchdogReattachInformation.Alpha) .Include(x => x.WatchdogReattachInformation.Bravo) @@ -358,7 +368,10 @@ namespace Tgstation.Server.Host.Controllers if (model == null) throw new ArgumentNullException(nameof(model)); - IQueryable InstanceQuery() => DatabaseContext.Instances.Where(x => x.Id == model.Id); + IQueryable InstanceQuery() => DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == model.Id); var moveJob = await InstanceQuery() .SelectMany(x => x.Jobs). @@ -435,6 +448,7 @@ namespace Tgstation.Server.Host.Controllers { var countOfExistingChatBots = await DatabaseContext .ChatBots + .AsQueryable() .Where(x => x.InstanceId == originalModel.Id) .CountAsync(cancellationToken) .ConfigureAwait(false); @@ -582,7 +596,10 @@ namespace Tgstation.Server.Host.Controllers var cantList = !AuthenticationContext.User.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List); IQueryable QueryForUser() { - var query = DatabaseContext.Instances.Where(x => x.Id == id); + var query = DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == id); if (cantList) query = query.Include(x => x.InstanceUsers); diff --git a/src/Tgstation.Server.Host/Controllers/InstanceUserController.cs b/src/Tgstation.Server.Host/Controllers/InstanceUserController.cs index dc335a143d..509b3be88a 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceUserController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceUserController.cs @@ -101,7 +101,14 @@ namespace Tgstation.Server.Host.Controllers if (earlyOut != null) return earlyOut; - var originalUser = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == model.UserId).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var originalUser = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .SelectMany(x => x.InstanceUsers) + .Where(x => x.UserId == model.UserId) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (originalUser == null) return StatusCode((int)HttpStatusCode.Gone); @@ -141,7 +148,13 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(typeof(IEnumerable), 200)] public async Task List(CancellationToken cancellationToken) { - var users = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).ToListAsync(cancellationToken).ConfigureAwait(false); + var users = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .SelectMany(x => x.InstanceUsers) + .ToListAsync(cancellationToken) + .ConfigureAwait(false); return Json(users.Select(x => x.ToApi())); } @@ -160,7 +173,14 @@ namespace Tgstation.Server.Host.Controllers public async Task GetId(long id, CancellationToken cancellationToken) { // this functions as userId - var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var user = await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .SelectMany(x => x.InstanceUsers) + .Where(x => x.UserId == id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (user == default) return StatusCode((int)HttpStatusCode.Gone); return Json(user.ToApi()); @@ -178,7 +198,14 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(204)] public async Task Delete(long id, CancellationToken cancellationToken) { - await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).DeleteAsync(cancellationToken).ConfigureAwait(false); + await DatabaseContext + .Instances + .AsQueryable() + .Where(x => x.Id == Instance.Id) + .SelectMany(x => x.InstanceUsers) + .Where(x => x.UserId == id) + .DeleteAsync(cancellationToken) + .ConfigureAwait(false); return NoContent(); } } diff --git a/src/Tgstation.Server.Host/Controllers/JobController.cs b/src/Tgstation.Server.Host/Controllers/JobController.cs index 4a3485dfd2..483d9ed476 100644 --- a/src/Tgstation.Server.Host/Controllers/JobController.cs +++ b/src/Tgstation.Server.Host/Controllers/JobController.cs @@ -49,7 +49,13 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(typeof(IEnumerable), 200)] public async Task Read(CancellationToken cancellationToken) { - var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false); + var result = await DatabaseContext + .Jobs + .AsQueryable() + .Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue) + .OrderByDescending(x => x.StartedAt) + .ToListAsync(cancellationToken) + .ConfigureAwait(false); return Json(result.Select(x => x.ToApi())); } @@ -65,10 +71,17 @@ namespace Tgstation.Server.Host.Controllers public async Task List(CancellationToken cancellationToken) { // you KNOW this will need pagination eventually right? - var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.EntityId - { - Id = x.Id - }).ToListAsync(cancellationToken).ConfigureAwait(false); + var jobs = await DatabaseContext + .Jobs + .AsQueryable() + .Where(x => x.Instance.Id == Instance.Id) + .OrderByDescending(x => x.StartedAt) + .Select(x => new Api.Models.EntityId + { + Id = x.Id + }) + .ToListAsync(cancellationToken) + .ConfigureAwait(false); return Json(jobs); } @@ -89,7 +102,12 @@ namespace Tgstation.Server.Host.Controllers public async Task Delete(long id, CancellationToken cancellationToken) { // don't care if an instance post or not at this point - var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var job = await DatabaseContext + .Jobs + .AsQueryable() + .Where(x => x.Id == id && x.Instance.Id == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (job == default(Job)) return NotFound(); @@ -119,6 +137,7 @@ namespace Tgstation.Server.Host.Controllers { var job = await DatabaseContext .Jobs + .AsQueryable() .Where(x => x.Id == id && x.Instance.Id == Instance.Id) .Include(x => x.StartedBy) .FirstOrDefaultAsync(cancellationToken) diff --git a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs index de272d9d78..f70bfaa99c 100644 --- a/src/Tgstation.Server.Host/Controllers/RepositoryController.cs +++ b/src/Tgstation.Server.Host/Controllers/RepositoryController.cs @@ -156,7 +156,12 @@ namespace Tgstation.Server.Host.Controllers if (model.AccessUser == null ^ model.AccessToken == null) return BadRequest(ErrorCode.RepoMismatchUserAndAccessToken); - var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var currentModel = await DatabaseContext + .RepositorySettings + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (currentModel == default) return StatusCode((int)HttpStatusCode.Gone); @@ -236,7 +241,12 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(410)] public async Task Delete(CancellationToken cancellationToken) { - var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var currentModel = await DatabaseContext + .RepositorySettings + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (currentModel == default) return StatusCode((int)HttpStatusCode.Gone); @@ -275,7 +285,12 @@ namespace Tgstation.Server.Host.Controllers [ProducesResponseType(410)] public async Task Read(CancellationToken cancellationToken) { - var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); + var currentModel = await DatabaseContext + .RepositorySettings + .AsQueryable() + .Where(x => x.InstanceId == Instance.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); if (currentModel == default) return StatusCode((int)HttpStatusCode.Gone, new ErrorMessage(ErrorCode.RepoMissing)); @@ -346,6 +361,7 @@ namespace Tgstation.Server.Host.Controllers var currentModel = await DatabaseContext .RepositorySettings + .AsQueryable() .Where(x => x.InstanceId == Instance.Id) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); @@ -654,6 +670,7 @@ namespace Tgstation.Server.Host.Controllers await databaseContextFactory.UseContext( async databaseContext => dbPull = await databaseContext.RevisionInformations + .AsQueryable() .Where(x => x.Instance.Id == Instance.Id && x.OriginCommitSha == lastRevisionInfo.OriginCommitSha && x.ActiveTestMerges.Count <= model.NewTestMerges.Count diff --git a/src/Tgstation.Server.Host/Controllers/UserController.cs b/src/Tgstation.Server.Host/Controllers/UserController.cs index 820f043ac3..6f0a1d1c0c 100644 --- a/src/Tgstation.Server.Host/Controllers/UserController.cs +++ b/src/Tgstation.Server.Host/Controllers/UserController.cs @@ -192,7 +192,10 @@ namespace Tgstation.Server.Host.Controllers var originalUser = passwordEditOnly ? AuthenticationContext.User - : await DatabaseContext.Users.Where(x => x.Id == model.Id) + : await DatabaseContext + .Users + .AsQueryable() + .Where(x => x.Id == model.Id) .Include(x => x.CreatedBy) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); @@ -301,6 +304,7 @@ namespace Tgstation.Server.Host.Controllers return Forbid(); var user = await DatabaseContext.Users + .AsQueryable() .Where(x => x.Id == id) .Include(x => x.CreatedBy) .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Database/DatabaseCollection.cs b/src/Tgstation.Server.Host/Database/DatabaseCollection.cs index 16652b38f3..e2ebf973e8 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseCollection.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseCollection.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; -using System.Threading.Tasks; namespace Tgstation.Server.Host.Database { @@ -48,9 +47,7 @@ namespace Tgstation.Server.Host.Database public void Attach(TModel model) => dbSet.Attach(model); /// - public Task ForEachAsync(Action action, CancellationToken cancellationToken) => dbSet - .AsAsyncEnumerable() - .ForEachAsync(action, cancellationToken); + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => dbSet.AsAsyncEnumerable().GetAsyncEnumerator(); /// public IEnumerator GetEnumerator() => dbSet.AsQueryable().GetEnumerator(); @@ -61,9 +58,6 @@ namespace Tgstation.Server.Host.Database /// public void RemoveRange(IEnumerable models) => dbSet.RemoveRange(models); - /// - public Task> ToListAsync(CancellationToken cancellationToken) => dbSet.AsQueryable().ToListAsync(cancellationToken); - /// IEnumerator IEnumerable.GetEnumerator() => dbSet.AsQueryable().GetEnumerator(); } diff --git a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs index ec15fb3e3c..7d13dfc80d 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseSeeder.cs @@ -76,7 +76,11 @@ namespace Tgstation.Server.Host.Database if (platformIdentifier.IsWindows) { // normalize backslashes to forward slashes - var allInstances = await databaseContext.Instances.ToListAsync(cancellationToken).ConfigureAwait(false); + var allInstances = await databaseContext + .Instances + .AsQueryable() + .ToListAsync(cancellationToken) + .ConfigureAwait(false); foreach (var instance in allInstances) instance.Path = instance.Path.Replace('\\', '/'); } @@ -107,6 +111,7 @@ namespace Tgstation.Server.Host.Database { var admin = await databaseContext .Users + .AsQueryable() .Where(x => x.CanonicalName == User.CanonicalizeName(Api.Models.User.AdminName)) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); diff --git a/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs b/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs index 9c3318e35d..a9e1fe0e03 100644 --- a/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs +++ b/src/Tgstation.Server.Host/Database/IDatabaseCollection.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Threading; -using System.Threading.Tasks; namespace Tgstation.Server.Host.Database { @@ -10,7 +7,7 @@ namespace Tgstation.Server.Host.Database /// Represents a database table. /// /// The type of model. - public interface IDatabaseCollection : IQueryable + public interface IDatabaseCollection : IQueryable, IAsyncEnumerable { /// /// An of s prioritizing in the working set. @@ -46,20 +43,5 @@ namespace Tgstation.Server.Host.Database /// /// An of s to remove. void RemoveRange(IEnumerable models); - - /// - /// Asyncronously run a given on the . - /// - /// The to run. - /// The for the operation. - /// A representing the running operation. - Task ForEachAsync(Action action, CancellationToken cancellationToken); - - /// - /// Retrieve all the s in the table. - /// - /// The for the operation. - /// A resulting in a of all in the table. - Task> ToListAsync(CancellationToken cancellationToken); } } diff --git a/src/Tgstation.Server.Host/Database/PostgresSqlDatabaseContext.cs b/src/Tgstation.Server.Host/Database/PostgresSqlDatabaseContext.cs index de020b3653..4042b423ab 100644 --- a/src/Tgstation.Server.Host/Database/PostgresSqlDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/PostgresSqlDatabaseContext.cs @@ -41,7 +41,7 @@ namespace Tgstation.Server.Host.Database throw new NotImplementedException("PostgresSQL implementation is not complete yet!"); if (DatabaseType != DatabaseType.PostgresSql) - throw new InvalidOperationException("Invalid DatabaseType for SqliteDatabaseContext!"); + throw new InvalidOperationException("Invalid DatabaseType for PostgresSqlDatabaseContext!"); } } } diff --git a/src/Tgstation.Server.Host/Extensions/DatabaseContextExtensions.cs b/src/Tgstation.Server.Host/Extensions/DatabaseContextExtensions.cs index 1fdae2abba..2aaf72f6aa 100644 --- a/src/Tgstation.Server.Host/Extensions/DatabaseContextExtensions.cs +++ b/src/Tgstation.Server.Host/Extensions/DatabaseContextExtensions.cs @@ -30,6 +30,7 @@ namespace Tgstation.Server.Host.Extensions return databaseContext .CompileJobs + .AsQueryable() .Where(x => x.Job.Instance.Id == instance.Id) .OrderByDescending(x => x.Job.StoppedAt) .FirstOrDefaultAsync(cancellationToken); diff --git a/src/Tgstation.Server.Host/Jobs/JobManager.cs b/src/Tgstation.Server.Host/Jobs/JobManager.cs index c071c946ed..5f01fcbf5e 100644 --- a/src/Tgstation.Server.Host/Jobs/JobManager.cs +++ b/src/Tgstation.Server.Host/Jobs/JobManager.cs @@ -186,7 +186,13 @@ namespace Tgstation.Server.Host.Jobs await databaseContextFactory.UseContext(async databaseContext => { // mark all jobs as cancelled - var badJobs = await databaseContext.Jobs.Where(y => !y.StoppedAt.HasValue).Select(y => y.Id).ToListAsync(cancellationToken).ConfigureAwait(false); + var badJobs = await databaseContext + .Jobs + .AsQueryable() + .Where(y => !y.StoppedAt.HasValue) + .Select(y => y.Id) + .ToListAsync(cancellationToken) + .ConfigureAwait(false); if (badJobs.Count > 0) { logger.LogTrace("Cleaning {0} unfinished jobs...", badJobs.Count); diff --git a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs index 070642c105..aa019be91f 100644 --- a/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs +++ b/src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs @@ -55,7 +55,10 @@ namespace Tgstation.Server.Host.Security if (CurrentAuthenticationContext != null) throw new InvalidOperationException("Authentication context has already been loaded"); - var user = await databaseContext.Users.Where(x => x.Id == userId) + var user = await databaseContext + .Users + .AsQueryable() + .Where(x => x.Id == userId) .Include(x => x.CreatedBy) .FirstOrDefaultAsync(cancellationToken) .ConfigureAwait(false); @@ -85,6 +88,7 @@ namespace Tgstation.Server.Host.Security if (instanceId.HasValue) { instanceUser = await databaseContext.InstanceUsers + .AsQueryable() .Where(x => x.UserId == userId && x.InstanceId == instanceId && x.Instance.Online.Value) .Include(x => x.Instance) .FirstOrDefaultAsync(cancellationToken) diff --git a/tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs b/tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs index c4927e3dee..8cfb81e0dc 100644 --- a/tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs +++ b/tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs @@ -13,7 +13,7 @@ namespace Tgstation.Server.Host.Core.Tests { var delayer = new AsyncDelayer(); var startDelay = delayer.Delay(TimeSpan.FromSeconds(1), default); - var checkDelay = Task.Delay(TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(10), default); + var checkDelay = Task.Delay(TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(100), default); await startDelay.ConfigureAwait(false); Assert.IsTrue(checkDelay.IsCompleted); } @@ -22,11 +22,9 @@ namespace Tgstation.Server.Host.Core.Tests public async Task TestCancel() { var delayer = new AsyncDelayer(); - using (var cts = new CancellationTokenSource()) - { - cts.Cancel(); - await Assert.ThrowsExceptionAsync(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false); - } + using var cts = new CancellationTokenSource(); + cts.Cancel(); + await Assert.ThrowsExceptionAsync(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false); } } }