refactor(jobs): modularize background job handlers
Some checks failed
ci / release-gate (push) Has been cancelled
Some checks failed
ci / release-gate (push) Has been cancelled
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Tiku.Application.Assets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Tiku.Application.Jobs;
|
||||
using Tiku.Application.Security;
|
||||
using Tiku.Domain.Common;
|
||||
using Tiku.Domain.Operations;
|
||||
@@ -137,11 +138,18 @@ internal sealed partial class BackgroundJobService
|
||||
|
||||
try
|
||||
{
|
||||
var result = await tenantExecutionScope.ExecuteAsync(
|
||||
var handlerResult = await tenantExecutionScope.ExecuteAsync(
|
||||
new SystemScopeRequest(
|
||||
job.TenantId, SystemScopeCallerType.Worker, workerId,
|
||||
$"Background job {job.JobType}", job.Id.ToString("N")),
|
||||
(provider, token) => ProcessCoreAsync(provider, job, token),
|
||||
async (provider, token) =>
|
||||
{
|
||||
var registry = provider.GetRequiredService<BackgroundJobHandlerRegistry>();
|
||||
var handler = registry.GetRequired(job.JobType);
|
||||
return await handler.HandleAsync(
|
||||
new BackgroundJobExecutionContext(job.Id, job.TenantId, job.JobType, job.Payload),
|
||||
token);
|
||||
},
|
||||
cancellationToken);
|
||||
var cancellationRequested = await dbContext.BackgroundJobs.AsNoTracking()
|
||||
.Where(item => item.Id == job.Id)
|
||||
@@ -150,22 +158,42 @@ internal sealed partial class BackgroundJobService
|
||||
job.Status = cancellationRequested ? BackgroundJobStatus.Cancelled : BackgroundJobStatus.Succeeded;
|
||||
job.CompletedAt = DateTimeOffset.UtcNow;
|
||||
job.LastError = null;
|
||||
job.Result = result;
|
||||
job.Result = handlerResult.Result;
|
||||
job.OutputAssetId = handlerResult.OutputAssetId;
|
||||
}
|
||||
catch (Exception exception) when (exception is not OperationCanceledException)
|
||||
{
|
||||
job.RetryCount++;
|
||||
job.LastError = exception is AssetSecurityScannerException scannerException
|
||||
? $"{scannerException.Code}: {scannerException.Message}"
|
||||
job.LastError = exception is BackgroundJobHandlerException handlerException
|
||||
? $"{handlerException.Code}: {handlerException.Message}"
|
||||
: exception.Message;
|
||||
if (exception is AssetSecurityScannerException assetScanException)
|
||||
await RecordAssetScanRetryAsync(job, assetScanException, cancellationToken);
|
||||
job.Status = job.RetryCount > job.MaxRetries
|
||||
? BackgroundJobStatus.Failed
|
||||
: BackgroundJobStatus.Pending;
|
||||
job.RunAfter = job.Status == BackgroundJobStatus.Pending
|
||||
? DateTimeOffset.UtcNow.AddSeconds(Math.Min(300, 10 * job.RetryCount))
|
||||
: null;
|
||||
try
|
||||
{
|
||||
await tenantExecutionScope.ExecuteAsync(
|
||||
new SystemScopeRequest(
|
||||
job.TenantId, SystemScopeCallerType.Worker, workerId,
|
||||
$"Background job failure compensation {job.JobType}", job.Id.ToString("N")),
|
||||
async (provider, token) =>
|
||||
{
|
||||
var handler = provider.GetRequiredService<BackgroundJobHandlerRegistry>()
|
||||
.GetRequired(job.JobType);
|
||||
await handler.HandleFailureAsync(
|
||||
new BackgroundJobExecutionContext(job.Id, job.TenantId, job.JobType, job.Payload),
|
||||
exception,
|
||||
token);
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception compensationException) when (compensationException is not OperationCanceledException)
|
||||
{
|
||||
job.LastError = $"{job.LastError} Compensation failed: {compensationException.Message}";
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -199,4 +227,4 @@ internal sealed partial class BackgroundJobService
|
||||
.SetProperty(value => value.LockExpiresAt, (DateTimeOffset?)null),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user