diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj
index b87cec0b6..f46c407f6 100644
--- a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs.Hangfire/LINGYUN.Abp.BackgroundJobs.Hangfire.csproj
@@ -3,6 +3,14 @@
netstandard2.0
+ true
+ 2.9.0
+ LINGYUN
+
+
+
+
+ D:\LocalNuget
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj
new file mode 100644
index 000000000..420f871a3
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN.Abp.BackgroundJobs.csproj
@@ -0,0 +1,19 @@
+
+
+
+ netstandard2.0
+
+ true
+ 2.9.0
+ LINGYUN
+
+
+
+ D:\LocalNuget
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs
new file mode 100644
index 000000000..369ccaf12
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobArgs.cs
@@ -0,0 +1,43 @@
+namespace LINGYUN.Abp.BackgroundJobs
+{
+ public class RetryAsyncBackgroundJobArgs
+ {
+ ///
+ /// 重试次数
+ ///
+ public int RetryCount { get; set; } = 0;
+ ///
+ /// 重试间隔(毫秒)
+ /// 默认 300000ms = 5min
+ ///
+ public double RetryIntervalMillisecond { get; set; } = 300000d;
+ ///
+ /// 最大重试次数
+ /// 默认 20
+ ///
+ public int MaxRetryCount { get; set; } = 20;
+ ///
+ /// 作业参数
+ ///
+ public TArgs JobArgs { get; set; }
+
+ public RetryAsyncBackgroundJobArgs()
+ {
+
+ }
+
+ public RetryAsyncBackgroundJobArgs(TArgs jobArgs)
+ {
+ JobArgs = jobArgs;
+ }
+
+ public RetryAsyncBackgroundJobArgs(TArgs jobArgs, int retryCount = 0, double interval = 300000d, int maxRetryCount = 20)
+ {
+ JobArgs = jobArgs;
+
+ RetryCount = retryCount;
+ RetryIntervalMillisecond = interval;
+ MaxRetryCount = maxRetryCount;
+ }
+ }
+}
diff --git a/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs
new file mode 100644
index 000000000..e309e8bbd
--- /dev/null
+++ b/aspnet-core/modules/common/LINGYUN.Abp.BackgroundJobs/LINGYUN/Abp/BackgroundJobs/RetryAsyncBackgroundJobBase.cs
@@ -0,0 +1,80 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.BackgroundJobs;
+
+namespace LINGYUN.Abp.BackgroundJobs
+{
+ public abstract class RetryAsyncBackgroundJobBase : IAsyncBackgroundJob>
+ {
+ public ILogger> Logger { get; set; }
+
+ protected IBackgroundJobManager BackgroundJobManager { get; }
+
+ protected RetryAsyncBackgroundJobBase(
+ IBackgroundJobManager backgroundJobManager)
+ {
+ BackgroundJobManager = backgroundJobManager;
+
+ Logger = NullLogger>.Instance;
+ }
+
+ public async Task ExecuteAsync(RetryAsyncBackgroundJobArgs args)
+ {
+ if (args.RetryCount > args.MaxRetryCount)
+ {
+ Logger.LogWarning("Job has failed and the maximum number of retries has been reached. The failure callback is about to enter");
+ // 任务执行失败次数已达上限,调用用户定义回调,并不再执行
+ await OnJobExecuteFailedAsync(args.JobArgs);
+ return;
+ }
+ try
+ {
+ // 执行任务
+ await ExecuteAsync(args.JobArgs, args.RetryCount);
+ // 执行完成后回调
+ await OnJobExecuteCompletedAsync(args.JobArgs);
+ }
+ catch(Exception ex)
+ {
+ Logger.LogWarning("Job execution has failed and a retry is imminent");
+ Logger.LogWarning("Job running error:{0}", ex.Message);
+
+ // 每次重试 间隔时间增加1.1倍
+ var retryInterval = args.RetryIntervalMillisecond * 1.1;
+ var retryJobArgs = new RetryAsyncBackgroundJobArgs(args.JobArgs,
+ args.RetryCount + 1, retryInterval, args.MaxRetryCount);
+
+ Logger.LogDebug("Job task is queued for the next execution");
+
+ // 计算优先级
+ BackgroundJobPriority priority = BackgroundJobPriority.Normal;
+
+ if (args.RetryCount <= (args.MaxRetryCount / 2) &&
+ args.RetryCount > (args.MaxRetryCount / 3))
+ {
+ priority = BackgroundJobPriority.BelowNormal;
+ }
+ else if (args.RetryCount > (args.MaxRetryCount / 1.5))
+ {
+ priority = BackgroundJobPriority.Low;
+ }
+ // 延迟入队,等待下一次运行
+ await BackgroundJobManager.EnqueueAsync(retryJobArgs, priority, delay: TimeSpan.FromMilliseconds(retryInterval));
+ }
+ }
+
+ protected abstract Task ExecuteAsync(TArgs args, int retryCount);
+
+ protected virtual Task OnJobExecuteFailedAsync(TArgs args)
+ {
+ return Task.CompletedTask;
+ }
+
+ protected virtual Task OnJobExecuteCompletedAsync(TArgs args)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}