|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
using System;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
using Volo.Abp.BackgroundWorkers;
|
|
|
|
@ -11,26 +12,26 @@ namespace Volo.Abp.BackgroundJobs
|
|
|
|
|
public class BackgroundJobWorker : PeriodicBackgroundWorkerBase, IBackgroundJobWorker, ISingletonDependency
|
|
|
|
|
{
|
|
|
|
|
protected IBackgroundJobExecuter JobExecuter { get; }
|
|
|
|
|
protected IBackgroundJobStore Store { get; }
|
|
|
|
|
protected BackgroundJobOptions JobOptions { get; }
|
|
|
|
|
protected BackgroundJobWorkerOptions WorkerOptions { get; }
|
|
|
|
|
protected IClock Clock { get; }
|
|
|
|
|
protected IBackgroundJobSerializer Serializer { get; }
|
|
|
|
|
protected IServiceScopeFactory ServiceScopeFactory { get; }
|
|
|
|
|
|
|
|
|
|
public BackgroundJobWorker(
|
|
|
|
|
IBackgroundJobStore store,
|
|
|
|
|
AbpTimer timer,
|
|
|
|
|
IBackgroundJobExecuter jobExecuter,
|
|
|
|
|
IBackgroundJobSerializer serializer,
|
|
|
|
|
IOptions<BackgroundJobOptions> jobOptions,
|
|
|
|
|
IOptions<BackgroundJobWorkerOptions> workerOptions,
|
|
|
|
|
IClock clock)
|
|
|
|
|
IClock clock,
|
|
|
|
|
IServiceScopeFactory serviceScopeFactory)
|
|
|
|
|
: base(timer)
|
|
|
|
|
{
|
|
|
|
|
JobExecuter = jobExecuter;
|
|
|
|
|
Serializer = serializer;
|
|
|
|
|
Clock = clock;
|
|
|
|
|
Store = store;
|
|
|
|
|
ServiceScopeFactory = serviceScopeFactory;
|
|
|
|
|
WorkerOptions = workerOptions.Value;
|
|
|
|
|
JobOptions = jobOptions.Value;
|
|
|
|
|
Timer.Period = WorkerOptions.JobPollPeriod;
|
|
|
|
@ -38,53 +39,60 @@ namespace Volo.Abp.BackgroundJobs
|
|
|
|
|
|
|
|
|
|
protected override void DoWork()
|
|
|
|
|
{
|
|
|
|
|
var waitingJobs = AsyncHelper.RunSync(() => Store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount));
|
|
|
|
|
|
|
|
|
|
foreach (var jobInfo in waitingJobs)
|
|
|
|
|
using (var scope = ServiceScopeFactory.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
jobInfo.TryCount++;
|
|
|
|
|
jobInfo.LastTryTime = Clock.Now;
|
|
|
|
|
var store = scope.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
|
|
|
|
|
|
|
|
|
|
var waitingJobs = AsyncHelper.RunSync(
|
|
|
|
|
() => store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
foreach (var jobInfo in waitingJobs)
|
|
|
|
|
{
|
|
|
|
|
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
|
|
|
|
|
var jobArgs = Serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
|
|
|
|
|
var context = new JobExecutionContext(jobConfiguration.JobType, jobArgs);
|
|
|
|
|
jobInfo.TryCount++;
|
|
|
|
|
jobInfo.LastTryTime = Clock.Now;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
JobExecuter.Execute(context);
|
|
|
|
|
AsyncHelper.RunSync(() => Store.DeleteAsync(jobInfo.Id));
|
|
|
|
|
}
|
|
|
|
|
catch (BackgroundJobExecutionException)
|
|
|
|
|
{
|
|
|
|
|
var nextTryTime = CalculateNextTryTime(jobInfo);
|
|
|
|
|
if (nextTryTime.HasValue)
|
|
|
|
|
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
|
|
|
|
|
var jobArgs = Serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
|
|
|
|
|
var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType, jobArgs);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
jobInfo.NextTryTime = nextTryTime.Value;
|
|
|
|
|
JobExecuter.Execute(context);
|
|
|
|
|
AsyncHelper.RunSync(() => store.DeleteAsync(jobInfo.Id));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
catch (BackgroundJobExecutionException)
|
|
|
|
|
{
|
|
|
|
|
jobInfo.IsAbandoned = true;
|
|
|
|
|
}
|
|
|
|
|
var nextTryTime = CalculateNextTryTime(jobInfo);
|
|
|
|
|
if (nextTryTime.HasValue)
|
|
|
|
|
{
|
|
|
|
|
jobInfo.NextTryTime = nextTryTime.Value;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
jobInfo.IsAbandoned = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TryUpdate(jobInfo);
|
|
|
|
|
TryUpdate(store, jobInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogException(ex);
|
|
|
|
|
jobInfo.IsAbandoned = true;
|
|
|
|
|
TryUpdate(store, jobInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logger.LogException(ex);
|
|
|
|
|
jobInfo.IsAbandoned = true;
|
|
|
|
|
TryUpdate(jobInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void TryUpdate(BackgroundJobInfo jobInfo)
|
|
|
|
|
protected virtual void TryUpdate(IBackgroundJobStore store, BackgroundJobInfo jobInfo)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Store.UpdateAsync(jobInfo);
|
|
|
|
|
store.UpdateAsync(jobInfo);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception updateEx)
|
|
|
|
|
{
|
|
|
|
|