mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-26 14:37:44 +01:00
Merge branch 'dev' into V6
This commit is contained in:
@@ -382,6 +382,17 @@ namespace Tgstation.Server.Host.Components
|
||||
// build current commit data if it's missing
|
||||
await UpdateRevInfo(repo.Head, false, null);
|
||||
|
||||
var preserveTestMerges = repositorySettings.AutoUpdatesKeepTestMerges.Value;
|
||||
var remoteDeploymentManager = remoteDeploymentManagerFactory.CreateRemoteDeploymentManager(
|
||||
metadata,
|
||||
repo.RemoteGitProvider.Value);
|
||||
|
||||
var updatedTestMerges = await remoteDeploymentManager.RemoveMergedTestMerges(
|
||||
repo,
|
||||
repositorySettings,
|
||||
currentRevInfo,
|
||||
cancellationToken);
|
||||
|
||||
var result = await repo.MergeOrigin(
|
||||
NextProgressReporter("Merge Origin"),
|
||||
repositorySettings.CommitterName,
|
||||
@@ -389,21 +400,10 @@ namespace Tgstation.Server.Host.Components
|
||||
true,
|
||||
cancellationToken);
|
||||
|
||||
var preserveTestMerges = repositorySettings.AutoUpdatesKeepTestMerges.Value;
|
||||
var remoteDeploymentManager = remoteDeploymentManagerFactory.CreateRemoteDeploymentManager(
|
||||
metadata,
|
||||
repo.RemoteGitProvider.Value);
|
||||
|
||||
// take appropriate auto update actions
|
||||
var shouldSyncTracked = false;
|
||||
if (result.HasValue)
|
||||
{
|
||||
var updatedTestMerges = await remoteDeploymentManager.RemoveMergedTestMerges(
|
||||
repo,
|
||||
repositorySettings,
|
||||
currentRevInfo,
|
||||
cancellationToken);
|
||||
|
||||
if (updatedTestMerges.Count == 0)
|
||||
{
|
||||
logger.LogTrace("All test merges have been merged on remote");
|
||||
@@ -517,7 +517,12 @@ namespace Tgstation.Server.Host.Components
|
||||
RepositoryAutoUpdateJob,
|
||||
cancellationToken);
|
||||
|
||||
await jobManager.WaitForJobCompletion(repositoryUpdateJob, null, cancellationToken, cancellationToken);
|
||||
var repoUpdateJobResult = await jobManager.WaitForJobCompletion(repositoryUpdateJob, null, cancellationToken, cancellationToken);
|
||||
if (repoUpdateJobResult == false)
|
||||
{
|
||||
logger.LogWarning("Aborting auto-update due to repository update error!");
|
||||
continue;
|
||||
}
|
||||
|
||||
Job compileProcessJob;
|
||||
using (var repo = await RepositoryManager.LoadRepository(cancellationToken))
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Tgstation.Server.Host.Jobs
|
||||
/// <param name="canceller">The <see cref="User"/> to cancel the <paramref name="job"/>. If <see langword="null"/> the TGS user will be used.</param>
|
||||
/// <param name="jobCancellationToken">A <see cref="CancellationToken"/> that will cancel the <paramref name="job"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the <see cref="Job"/>.</returns>
|
||||
ValueTask WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> representing the <see cref="Job"/>. Results in <see langword="true"/> if the <see cref="Job"/> completed without errors, <see langword="false"/> if errors occurred, or <see langword="null"/> if the job isn't registered.</returns>
|
||||
ValueTask<bool?> WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels a give <paramref name="job"/>.
|
||||
|
||||
@@ -30,20 +30,20 @@ namespace Tgstation.Server.Host.Jobs
|
||||
readonly CancellationTokenSource cancellationTokenSource;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Func{T, TResult}"/> taking a <see cref="CancellationToken"/> and returning a <see cref="Task"/> that the <see cref="JobHandler"/> will wrap.
|
||||
/// A <see cref="Func{T, TResult}"/> taking a <see cref="CancellationToken"/> and returning a <see cref="Task{TResult}"/> that the <see cref="JobHandler"/> will wrap.
|
||||
/// </summary>
|
||||
readonly Func<CancellationToken, Task> jobActivator;
|
||||
readonly Func<CancellationToken, Task<bool>> jobActivator;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Task"/> being run.
|
||||
/// </summary>
|
||||
Task task;
|
||||
Task<bool> task;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JobHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="jobActivator">The value of <see cref="jobActivator"/>.</param>
|
||||
public JobHandler(Func<CancellationToken, Task> jobActivator)
|
||||
public JobHandler(Func<CancellationToken, Task<bool>> jobActivator)
|
||||
{
|
||||
this.jobActivator = jobActivator ?? throw new ArgumentNullException(nameof(jobActivator));
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
@@ -56,8 +56,8 @@ namespace Tgstation.Server.Host.Jobs
|
||||
/// Wait for <see cref="task"/> to complete.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
|
||||
public Task Wait(CancellationToken cancellationToken)
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the job. Results in <see langword="true"/> if the job completed without errors, <see langword="false"/> otherwise.</returns>
|
||||
public Task<bool> Wait(CancellationToken cancellationToken)
|
||||
{
|
||||
if (task == null)
|
||||
throw new InvalidOperationException("Job not started!");
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
|
||||
public async ValueTask<bool?> WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(job);
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
lock (synchronizationLock)
|
||||
{
|
||||
if (!jobs.TryGetValue(job.Id.Value, out handler))
|
||||
return;
|
||||
return null;
|
||||
|
||||
noMoreJobsShouldStart = this.noMoreJobsShouldStart;
|
||||
}
|
||||
@@ -270,11 +270,14 @@ namespace Tgstation.Server.Host.Jobs
|
||||
await Extensions.TaskExtensions.InfiniteTask.WaitAsync(cancellationToken);
|
||||
|
||||
ValueTask<Job>? cancelTask = null;
|
||||
bool result;
|
||||
using (jobCancellationToken.Register(() => cancelTask = CancelJob(job, canceller, true, cancellationToken)))
|
||||
await handler.Wait(cancellationToken);
|
||||
result = await handler.Wait(cancellationToken);
|
||||
|
||||
if (cancelTask.HasValue)
|
||||
await cancelTask.Value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -293,12 +296,14 @@ namespace Tgstation.Server.Host.Jobs
|
||||
/// <param name="operation">The <see cref="JobEntrypoint"/> 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, JobEntrypoint operation, CancellationToken cancellationToken)
|
||||
async Task<bool> RunJob(Job job, JobEntrypoint operation, CancellationToken cancellationToken)
|
||||
{
|
||||
using (LogContext.PushProperty(SerilogContextHelper.JobIdContextProperty, job.Id))
|
||||
try
|
||||
{
|
||||
void LogException(Exception ex) => logger.LogDebug(ex, "Job {jobId} exited with error!", job.Id);
|
||||
|
||||
var result = false;
|
||||
try
|
||||
{
|
||||
var oldJob = job;
|
||||
@@ -336,6 +341,7 @@ namespace Tgstation.Server.Host.Jobs
|
||||
cancellationToken);
|
||||
|
||||
logger.LogDebug("Job {jobId} completed!", job.Id);
|
||||
result = true;
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
@@ -370,6 +376,8 @@ namespace Tgstation.Server.Host.Jobs
|
||||
// DCT: Cancellation token is for job, operation should always run
|
||||
await databaseContext.Save(CancellationToken.None);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace Tgstation.Server.Host.Utils.GitHub
|
||||
{
|
||||
GitHubClient client;
|
||||
bool cacheHit;
|
||||
DateTimeOffset? lastUsed;
|
||||
lock (clientCache)
|
||||
{
|
||||
string cacheKey;
|
||||
@@ -105,11 +106,13 @@ namespace Tgstation.Server.Host.Utils.GitHub
|
||||
client.Credentials = new Credentials(accessToken);
|
||||
|
||||
clientCache.Add(cacheKey, (client, now));
|
||||
lastUsed = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogTrace("Cache hit for GitHubClient");
|
||||
client = tuple.Item1;
|
||||
lastUsed = tuple.Item2;
|
||||
tuple.Item2 = now;
|
||||
}
|
||||
|
||||
@@ -144,13 +147,15 @@ namespace Tgstation.Server.Host.Utils.GitHub
|
||||
rateLimitInfo.Reset.ToString("o"));
|
||||
else if (rateLimitInfo.Remaining < 25) // good luck hitting these lines on codecov
|
||||
logger.LogWarning(
|
||||
"Requested GitHub client has only {remainingRequests} requests remaining! Limit resets at {resetTime}",
|
||||
"Requested GitHub client has only {remainingRequests} requests remaining after the usage at {lastUse}! Limit resets at {resetTime}",
|
||||
rateLimitInfo.Remaining,
|
||||
lastUsed,
|
||||
rateLimitInfo.Reset.ToString("o"));
|
||||
else
|
||||
logger.LogDebug(
|
||||
"Requested GitHub client has {remainingRequests} requests remaining. Limit resets at {resetTime}",
|
||||
"Requested GitHub client has {remainingRequests} requests remaining after the usage {lastUse}. Limit resets at {resetTime}",
|
||||
rateLimitInfo.Remaining,
|
||||
lastUsed,
|
||||
rateLimitInfo.Reset.ToString("o"));
|
||||
|
||||
return client;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests
|
||||
.Returns(ValueTask.CompletedTask);
|
||||
mockSetup
|
||||
.Setup(x => x.WaitForJobCompletion(It.IsNotNull<Job>(), It.IsAny<User>(), It.IsAny<CancellationToken>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(ValueTask.CompletedTask);
|
||||
.Returns(ValueTask.FromResult<bool?>(true));
|
||||
mockJobManager = mockSetup.Object;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers.Tests
|
||||
.Returns(ValueTask.CompletedTask);
|
||||
mockSetup
|
||||
.Setup(x => x.WaitForJobCompletion(It.IsNotNull<Job>(), It.IsAny<User>(), It.IsAny<CancellationToken>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(ValueTask.CompletedTask);
|
||||
.Returns(ValueTask.FromResult<bool?>(true));
|
||||
var mockJobManager = mockSetup.Object;
|
||||
await using var provider = new IrcProvider(mockJobManager, new AsyncDelayer(), loggerFactory.CreateLogger<IrcProvider>(), Mock.Of<IAssemblyInformationProvider>(), new ChatBot
|
||||
{
|
||||
|
||||
@@ -11,10 +11,11 @@ namespace Tgstation.Server.Host.Jobs.Tests
|
||||
Task currentWaitTask;
|
||||
bool cancelled;
|
||||
|
||||
async Task TestJob(CancellationToken cancellationToken)
|
||||
async Task<bool> TestJob(CancellationToken cancellationToken)
|
||||
{
|
||||
await currentWaitTask;
|
||||
cancelled = cancellationToken.IsCancellationRequested;
|
||||
return true;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
Reference in New Issue
Block a user