mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 16:39:21 +01:00
Merge pull request #1028 from tgstation/979-TryFixPostgres
Try to fix postgres
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the average <see cref="TimeSpan"/> of the 10 previous deployments or <see langword="null"/> if there are none.</returns>
|
||||
async Task<TimeSpan?> 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)
|
||||
|
||||
@@ -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<RevisionInformation> 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);
|
||||
|
||||
|
||||
@@ -213,10 +213,14 @@ namespace Tgstation.Server.Host.Components
|
||||
var tasks = new List<Task>();
|
||||
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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<IActionResult> 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<Api.Models.ChatBot>), 200)]
|
||||
public async Task<IActionResult> 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<IActionResult> 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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -61,7 +61,12 @@ namespace Tgstation.Server.Host.Controllers
|
||||
public async Task<IActionResult> 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<IActionResult> 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<EntityId>), 200)]
|
||||
public async Task<IActionResult> 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);
|
||||
|
||||
|
||||
@@ -196,12 +196,12 @@ namespace Tgstation.Server.Host.Controllers
|
||||
using (systemIdentity)
|
||||
{
|
||||
// Get the user from the database
|
||||
IQueryable<User> query;
|
||||
IQueryable<User> 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,
|
||||
|
||||
@@ -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<IActionResult> 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<Models.Instance> InstanceQuery() => DatabaseContext.Instances.Where(x => x.Id == model.Id);
|
||||
IQueryable<Models.Instance> 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<Models.Instance> 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);
|
||||
|
||||
@@ -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<Api.Models.InstanceUser>), 200)]
|
||||
public async Task<IActionResult> 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<IActionResult> 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<IActionResult> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,13 @@ namespace Tgstation.Server.Host.Controllers
|
||||
[ProducesResponseType(typeof(IEnumerable<Api.Models.Job>), 200)]
|
||||
public async Task<IActionResult> 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<IActionResult> 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<IActionResult> 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)
|
||||
|
||||
@@ -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<IActionResult> 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<IActionResult> 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ForEachAsync(Action<TModel> action, CancellationToken cancellationToken) => dbSet
|
||||
.AsAsyncEnumerable()
|
||||
.ForEachAsync(action, cancellationToken);
|
||||
public IAsyncEnumerator<TModel> GetAsyncEnumerator(CancellationToken cancellationToken = default) => dbSet.AsAsyncEnumerable().GetAsyncEnumerator();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<TModel> GetEnumerator() => dbSet.AsQueryable().GetEnumerator();
|
||||
@@ -61,9 +58,6 @@ namespace Tgstation.Server.Host.Database
|
||||
/// <inheritdoc />
|
||||
public void RemoveRange(IEnumerable<TModel> models) => dbSet.RemoveRange(models);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<TModel>> ToListAsync(CancellationToken cancellationToken) => dbSet.AsQueryable().ToListAsync(cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator() => dbSet.AsQueryable().GetEnumerator();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of model.</typeparam>
|
||||
public interface IDatabaseCollection<TModel> : IQueryable<TModel>
|
||||
public interface IDatabaseCollection<TModel> : IQueryable<TModel>, IAsyncEnumerable<TModel>
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IEnumerable{T}"/> of <typeparamref name="TModel"/>s prioritizing in the working set.
|
||||
@@ -46,20 +43,5 @@ namespace Tgstation.Server.Host.Database
|
||||
/// </summary>
|
||||
/// <param name="models">An <see cref="IEnumerable{T}"/> of <typeparamref name="TModel"/>s to remove.</param>
|
||||
void RemoveRange(IEnumerable<TModel> models);
|
||||
|
||||
/// <summary>
|
||||
/// Asyncronously run a given <paramref name="action"/> on the <see cref="IDatabaseCollection{TModel}"/>.
|
||||
/// </summary>
|
||||
/// <param name="action">The <see cref="Action{T}"/> to run.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
|
||||
Task ForEachAsync(Action<TModel> action, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all the <typeparamref name="TModel"/>s in the table.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="List{T}"/> of all <typeparamref name="TModel"/> in the table.</returns>
|
||||
Task<List<TModel>> ToListAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<TaskCanceledException>(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false);
|
||||
}
|
||||
using var cts = new CancellationTokenSource();
|
||||
cts.Cancel();
|
||||
await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user