Browse Source

feat(tasks): add multiple job event handlers

pull/477/head
cKey 4 years ago
parent
commit
366aa2411c
  1. 2
      aspnet-core/Directory.Build.props
  2. 14
      aspnet-core/LINGYUN.MicroService.TaskManagement.sln
  3. 10
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
  4. 10
      aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml
  5. 28
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksAbstractionsModule.cs
  6. 10
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksOptions.cs
  7. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobCompletedNotifierProvider.cs
  8. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobExceptionNotifier.cs
  9. 11
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobExecutedNotifier.cs
  10. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobFailedNotifierProvider.cs
  11. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobSuccessNotifierProvider.cs
  12. 21
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobEventData.cs
  13. 16
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobExceptionNotificationContext.cs
  14. 67
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobExecutedNotifier.cs
  15. 2
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobInfo.cs
  16. 14
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/NullJobExceptionNotifier.cs
  17. 45
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobFailedNotifierProvider.cs
  18. 30
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/AbpBackgroundTasksJobsModule.cs
  19. 6
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/BackgroundTasksConsts.cs
  20. 2
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/HttpRequestJobBase.cs
  21. 8
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/ServiceInvocationJob.cs
  22. 6
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobConcurrentAdapter.cs
  23. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs
  24. 13
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs
  25. 78
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobScheduler.cs
  26. 20
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/Quartz/IJobExecutionContextExtensions.cs
  27. 16
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN.Abp.BackgroundTasks.TaskManagement.csproj
  28. 11
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN/Abp/BackgroundTasks/TaskManagement/AbpBackgroundTasksTaskManagementModule.cs
  29. 44
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN/Abp/BackgroundTasks/TaskManagement/TaskManagementJobPublisher.cs
  30. 8
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs
  31. 10
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/BackgroundJobManager.cs
  32. 10
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/BackgroundWorkerManager.cs
  33. 9
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/IJobPublisher.cs
  34. 21
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/IJobScheduler.cs
  35. 27
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundKeepAliveJob.cs
  36. 4
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundPollingJob.cs
  37. 48
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs
  38. 19
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs
  39. 32
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobNotifierEvent.cs
  40. 12
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs
  41. 14
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/NullJobPublisher.cs
  42. 60
      aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/NullJobScheduler.cs
  43. 2
      aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoCreateOrUpdateDto.cs
  44. 2
      aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs
  45. 19
      aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi.Client/LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj
  46. 17
      aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi.Client/LINGYUN/Abp/TaskManagement/TaskManagementHttpApiClientModule.cs
  47. 2
      aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Properties/launchSettings.json
  48. 1
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj
  49. 31
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.Configure.cs
  50. 2
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs
  51. 7
      aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.Configure.cs
  52. 2
      aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs

2
aspnet-core/Directory.Build.props

@ -4,7 +4,7 @@
<LINGYUNAbpPackageVersion>5.1.1</LINGYUNAbpPackageVersion> <LINGYUNAbpPackageVersion>5.1.1</LINGYUNAbpPackageVersion>
<DaprPackageVersion>1.5.0</DaprPackageVersion> <DaprPackageVersion>1.5.0</DaprPackageVersion>
<DistributedLockRedisPackageVersion>1.0.1</DistributedLockRedisPackageVersion> <DistributedLockRedisPackageVersion>1.0.1</DistributedLockRedisPackageVersion>
<DotNetCoreCAPPackageVersion>5.2.0</DotNetCoreCAPPackageVersion> <DotNetCoreCAPPackageVersion>6.0.0</DotNetCoreCAPPackageVersion>
<AliyunSDKPackageVersion>1.5.10</AliyunSDKPackageVersion> <AliyunSDKPackageVersion>1.5.10</AliyunSDKPackageVersion>
<AliyunOSSSDKPackageVersion>2.13.0</AliyunOSSSDKPackageVersion> <AliyunOSSSDKPackageVersion>2.13.0</AliyunOSSSDKPackageVersion>
<TencentCloudSDKPackageVersion>3.0.434</TencentCloudSDKPackageVersion> <TencentCloudSDKPackageVersion>3.0.434</TencentCloudSDKPackageVersion>

14
aspnet-core/LINGYUN.MicroService.TaskManagement.sln

@ -40,6 +40,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.ExceptionHandling", "modules\task-management\LINGYUN.Abp.BackgroundTasks.ExceptionHandling\LINGYUN.Abp.BackgroundTasks.ExceptionHandling.csproj", "{8507BBFA-FE56-4426-BBFA-C92906CB8407}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.ExceptionHandling", "modules\task-management\LINGYUN.Abp.BackgroundTasks.ExceptionHandling\LINGYUN.Abp.BackgroundTasks.ExceptionHandling.csproj", "{8507BBFA-FE56-4426-BBFA-C92906CB8407}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TaskManagement.HttpApi.Client", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi.Client\LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj", "{56C759D1-6FE6-4111-A2DB-CD65DCE82061}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.TaskManagement", "modules\task-management\LINGYUN.Abp.BackgroundTasks.TaskManagement\LINGYUN.Abp.BackgroundTasks.TaskManagement.csproj", "{7937785C-0D28-46B3-A7E7-0B592821A1F2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -94,6 +98,14 @@ Global
{8507BBFA-FE56-4426-BBFA-C92906CB8407}.Debug|Any CPU.Build.0 = Debug|Any CPU {8507BBFA-FE56-4426-BBFA-C92906CB8407}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8507BBFA-FE56-4426-BBFA-C92906CB8407}.Release|Any CPU.ActiveCfg = Release|Any CPU {8507BBFA-FE56-4426-BBFA-C92906CB8407}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8507BBFA-FE56-4426-BBFA-C92906CB8407}.Release|Any CPU.Build.0 = Release|Any CPU {8507BBFA-FE56-4426-BBFA-C92906CB8407}.Release|Any CPU.Build.0 = Release|Any CPU
{56C759D1-6FE6-4111-A2DB-CD65DCE82061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{56C759D1-6FE6-4111-A2DB-CD65DCE82061}.Debug|Any CPU.Build.0 = Debug|Any CPU
{56C759D1-6FE6-4111-A2DB-CD65DCE82061}.Release|Any CPU.ActiveCfg = Release|Any CPU
{56C759D1-6FE6-4111-A2DB-CD65DCE82061}.Release|Any CPU.Build.0 = Release|Any CPU
{7937785C-0D28-46B3-A7E7-0B592821A1F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7937785C-0D28-46B3-A7E7-0B592821A1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7937785C-0D28-46B3-A7E7-0B592821A1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7937785C-0D28-46B3-A7E7-0B592821A1F2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -111,6 +123,8 @@ Global
{4A049C32-55F2-4A5F-954A-C8A977C2D87F} = {C38EB7EF-BAE9-4129-862A-71C652B81775} {4A049C32-55F2-4A5F-954A-C8A977C2D87F} = {C38EB7EF-BAE9-4129-862A-71C652B81775}
{4C59F590-AA6C-4C46-8060-DA65D8305980} = {C38EB7EF-BAE9-4129-862A-71C652B81775} {4C59F590-AA6C-4C46-8060-DA65D8305980} = {C38EB7EF-BAE9-4129-862A-71C652B81775}
{8507BBFA-FE56-4426-BBFA-C92906CB8407} = {C38EB7EF-BAE9-4129-862A-71C652B81775} {8507BBFA-FE56-4426-BBFA-C92906CB8407} = {C38EB7EF-BAE9-4129-862A-71C652B81775}
{56C759D1-6FE6-4111-A2DB-CD65DCE82061} = {C38EB7EF-BAE9-4129-862A-71C652B81775}
{7937785C-0D28-46B3-A7E7-0B592821A1F2} = {385578CC-C0F1-4377-A7A2-682B8F416234}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E1FD1F4C-D344-408B-97CF-B6F1F6D7D293} SolutionGuid = {E1FD1F4C-D344-408B-97CF-B6F1F6D7D293}

10
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml

@ -147,6 +147,16 @@
<param name="cancellationToken"></param> <param name="cancellationToken"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetCapProvidedParameter(DotNetCore.CAP.Internal.ParameterDescriptor,DotNetCore.CAP.Messages.Message,System.Threading.CancellationToken)">
<summary>
</summary>
<param name="parameterDescriptor"></param>
<param name="message"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:System.ArgumentException"></exception>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)"> <member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)">
<summary> <summary>
获取事件处理类实例 获取事件处理类实例

10
aspnet-core/modules/common/LINGYUN.Abp.EventBus.CAP/modules/common/LINGYUN.Abp.EventBus.CAP/LINGYUN.Abp.EventBus.CAP.xml

@ -147,6 +147,16 @@
<param name="cancellationToken"></param> <param name="cancellationToken"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetCapProvidedParameter(DotNetCore.CAP.Internal.ParameterDescriptor,DotNetCore.CAP.Messages.Message,System.Threading.CancellationToken)">
<summary>
</summary>
<param name="parameterDescriptor"></param>
<param name="message"></param>
<param name="cancellationToken"></param>
<returns></returns>
<exception cref="T:System.ArgumentException"></exception>
</member>
<member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)"> <member name="M:LINGYUN.Abp.EventBus.CAP.AbpCAPSubscribeInvoker.GetInstance(System.IServiceProvider,DotNetCore.CAP.Internal.ConsumerContext)">
<summary> <summary>
获取事件处理类实例 获取事件处理类实例

28
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksAbstractionsModule.cs

@ -1,33 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity;
using System;
using System.Collections.Generic;
using Volo.Abp.Modularity;
using Volo.Abp.Reflection;
namespace LINGYUN.Abp.BackgroundTasks; namespace LINGYUN.Abp.BackgroundTasks;
public class AbpBackgroundTasksAbstractionsModule : AbpModule public class AbpBackgroundTasksAbstractionsModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddJobMonitors(context.Services);
}
private static void AutoAddJobMonitors(IServiceCollection services)
{
var jobMonitors = new List<Type>();
services.OnRegistred(context =>
{
if (ReflectionHelper.IsAssignableToGenericType(context.ImplementationType, typeof(JobEventBase<>)))
{
jobMonitors.Add(context.ImplementationType);
}
});
services.Configure<AbpBackgroundTasksOptions>(options =>
{
options.JobMonitors.AddIfNotContains(jobMonitors);
});
}
} }

10
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksOptions.cs

@ -21,6 +21,10 @@ public class AbpBackgroundTasksOptions
/// </remarks> /// </remarks>
public IDictionary<string, Type> JobProviders { get; } public IDictionary<string, Type> JobProviders { get; }
/// <summary> /// <summary>
/// 启用清理任务
/// </summary>
public bool JobCleanEnabled { get; set; }
/// <summary>
/// 任务过期时间 /// 任务过期时间
/// 默认: 15 days /// 默认: 15 days
/// </summary> /// </summary>
@ -42,6 +46,10 @@ public class AbpBackgroundTasksOptions
/// </remarks> /// </remarks>
public string JobCleanCronExpression { get; set; } public string JobCleanCronExpression { get; set; }
/// <summary> /// <summary>
/// 启用轮询任务
/// </summary>
public bool JobFetchEnabled { get; set; }
/// <summary>
/// 每次轮询任务批次大小 /// 每次轮询任务批次大小
/// 默认: 1000 /// 默认: 1000
/// </summary> /// </summary>
@ -64,10 +72,12 @@ public class AbpBackgroundTasksOptions
public int JobFetchLockTimeOut { get; set; } public int JobFetchLockTimeOut { get; set; }
public AbpBackgroundTasksOptions() public AbpBackgroundTasksOptions()
{ {
JobFetchEnabled = true;
MaxJobFetchCount = 1000; MaxJobFetchCount = 1000;
JobFetchLockTimeOut = 120; JobFetchLockTimeOut = 120;
JobFetchCronExpression = "0/30 * * * * ? "; JobFetchCronExpression = "0/30 * * * * ? ";
JobCleanEnabled = true;
MaxJobCleanCount = 1000; MaxJobCleanCount = 1000;
JobExpiratime = TimeSpan.FromDays(15d); JobExpiratime = TimeSpan.FromDays(15d);
JobCleanCronExpression = "0 0/10 * * * ? *"; JobCleanCronExpression = "0 0/10 * * * ? *";

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobCompletedNotifierProvider.cs

@ -0,0 +1,9 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobCompletedNotifierProvider
{
Task NotifyComplateAsync([NotNull] JobEventContext context);
}

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobExceptionNotifier.cs

@ -1,9 +0,0 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobExceptionNotifier
{
Task NotifyAsync([NotNull] JobExceptionNotificationContext context);
}

11
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobExecutedNotifier.cs

@ -0,0 +1,11 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobExecutedNotifier
{
Task NotifyErrorAsync([NotNull] JobEventContext context);
Task NotifySuccessAsync([NotNull] JobEventContext context);
Task NotifyComplateAsync([NotNull] JobEventContext context);
}

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobFailedNotifierProvider.cs

@ -0,0 +1,9 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobFailedNotifierProvider
{
Task NotifyErrorAsync([NotNull] JobEventContext context);
}

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/IJobSuccessNotifierProvider.cs

@ -0,0 +1,9 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobSuccessNotifierProvider
{
Task NotifySuccessAsync([NotNull] JobEventContext context);
}

21
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobEventData.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.BackgroundTasks; namespace LINGYUN.Abp.BackgroundTasks;
@ -9,6 +10,10 @@ public class JobEventData
/// </summary> /// </summary>
public Type Type { get; } public Type Type { get; }
/// <summary> /// <summary>
/// 任务参数
/// </summary>
public IReadOnlyDictionary<string, object> Args { get; }
/// <summary>
/// 任务组别 /// 任务组别
/// </summary> /// </summary>
public string Group { get; } public string Group { get; }
@ -49,16 +54,6 @@ public class JobEventData
/// </summary> /// </summary>
public int RepeatCount { get; set; } public int RepeatCount { get; set; }
/// <summary> /// <summary>
/// 失败重试上限
/// 默认:50
/// </summary>
public int TryCount { get; set; }
/// <summary>
/// 最大执行次数
/// 默认:0, 无限制
/// </summary>
public int MaxCount { get; set; }
/// <summary>
/// 运行时间 /// 运行时间
/// </summary> /// </summary>
public DateTime RunTime { get; set; } public DateTime RunTime { get; set; }
@ -70,21 +65,19 @@ public class JobEventData
/// 下次运行时间 /// 下次运行时间
/// </summary> /// </summary>
public DateTime? NextRunTime { get; set; } public DateTime? NextRunTime { get; set; }
/// <summary>
/// 连续失败且不会再次执行
/// </summary>
public bool IsAbandoned { get; set; }
public JobEventData( public JobEventData(
string key, string key,
Type type, Type type,
string group, string group,
string name, string name,
IReadOnlyDictionary<string, object> args,
Exception exception = null) Exception exception = null)
{ {
Key = key; Key = key;
Type = type; Type = type;
Group = group; Group = group;
Name = name; Name = name;
Args = args;
Exception = exception; Exception = exception;
} }
} }

16
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobExceptionNotificationContext.cs

@ -1,16 +0,0 @@
using System;
namespace LINGYUN.Abp.BackgroundTasks;
public class JobExceptionNotificationContext
{
public JobInfo JobInfo { get; }
public Exception Exception { get; }
public JobExceptionNotificationContext(
JobInfo jobInfo,
Exception exception)
{
JobInfo = jobInfo;
Exception = exception;
}
}

67
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobExecutedNotifier.cs

@ -0,0 +1,67 @@
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks;
public class JobExecutedNotifier : IJobExecutedNotifier, ISingletonDependency
{
public ILogger<JobExecutedNotifier> Logger { protected get; set; }
public JobExecutedNotifier()
{
Logger = NullLogger<JobExecutedNotifier>.Instance;
}
public async Task NotifyComplateAsync([NotNull] JobEventContext context)
{
var notifier = context.ServiceProvider.GetService<IJobCompletedNotifierProvider>();
if (notifier != null)
{
try
{
await notifier.NotifyComplateAsync(context);
}
catch (Exception ex)
{
Logger.LogWarning($"An exception thow with job complete notify: {ex.Message}");
}
}
}
public async Task NotifyErrorAsync([NotNull] JobEventContext context)
{
var notifier = context.ServiceProvider.GetService<IJobFailedNotifierProvider>();
if (notifier != null)
{
try
{
await notifier.NotifyErrorAsync(context);
}
catch (Exception ex)
{
Logger.LogWarning($"An exception thow with job error notify: {ex.Message}");
}
}
}
public async Task NotifySuccessAsync([NotNull] JobEventContext context)
{
var notifier = context.ServiceProvider.GetService<IJobSuccessNotifierProvider>();
if (notifier != null)
{
try
{
await notifier.NotifySuccessAsync(context);
}
catch (Exception ex)
{
Logger.LogWarning($"An exception thow with job success notify: {ex.Message}");
}
}
}
}

2
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/JobInfo.cs

@ -128,7 +128,7 @@ public class JobInfo
} }
// 重试 // 重试
if (Status == JobStatus.FailedRetry) if (Status == JobStatus.FailedRetry && MaxTryCount > 0)
{ {
maxCount = MaxTryCount - TryCount; maxCount = MaxTryCount - TryCount;

14
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/NullJobExceptionNotifier.cs

@ -1,14 +0,0 @@
using JetBrains.Annotations;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks;
[Dependency(TryRegister = true)]
public class NullJobExceptionNotifier : IJobExceptionNotifier, ISingletonDependency
{
public Task NotifyAsync([NotNull] JobExceptionNotificationContext context)
{
return Task.CompletedTask;
}
}

45
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobExceptionNotifier.cs → aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.ExceptionHandling/LINGYUN/Abp/BackgroundTasks/ExceptionHandling/JobFailedNotifierProvider.cs

@ -15,19 +15,18 @@ using Volo.Abp.Timing;
namespace LINGYUN.Abp.BackgroundTasks.ExceptionHandling; namespace LINGYUN.Abp.BackgroundTasks.ExceptionHandling;
[Dependency(ReplaceServices = true)] public class JobFailedNotifierProvider : IJobFailedNotifierProvider, ITransientDependency
public class JobExceptionNotifier : IJobExceptionNotifier, ITransientDependency
{ {
public const string Prefix = "exception."; public const string Prefix = "exception.";
public const string JobGroup = "ExceptionNotifier"; public const string JobGroup = "ExceptionNotifier";
public ILogger<JobExceptionNotifier> Logger { protected get; set; } public ILogger<JobFailedNotifierProvider> Logger { protected get; set; }
protected IClock Clock { get; } protected IClock Clock { get; }
protected IEmailSender EmailSender { get; } protected IEmailSender EmailSender { get; }
protected ITemplateRenderer TemplateRenderer { get; } protected ITemplateRenderer TemplateRenderer { get; }
public JobExceptionNotifier( public JobFailedNotifierProvider(
IClock clock, IClock clock,
IEmailSender emailSender, IEmailSender emailSender,
ITemplateRenderer templateRenderer) ITemplateRenderer templateRenderer)
@ -36,26 +35,27 @@ public class JobExceptionNotifier : IJobExceptionNotifier, ITransientDependency
EmailSender = emailSender; EmailSender = emailSender;
TemplateRenderer = templateRenderer; TemplateRenderer = templateRenderer;
Logger = NullLogger<JobExceptionNotifier>.Instance; Logger = NullLogger<JobFailedNotifierProvider>.Instance;
} }
public virtual async Task NotifyAsync([NotNull] JobExceptionNotificationContext context) public virtual async Task NotifyErrorAsync([NotNull] JobEventContext context)
{ {
var eventData = context.EventData;
// 异常所属分组不处理, 防止死循环 // 异常所属分组不处理, 防止死循环
if (string.Equals(context.JobInfo.Group, JobGroup)) if (string.Equals(eventData.Group, JobGroup))
{ {
Logger.LogWarning($"There is a problem executing the job, reason: {context.Exception.Message}"); Logger.LogWarning($"There is a problem executing the job, reason: {eventData.Exception.Message}");
return; return;
} }
var notifyKey = Prefix + SendEmailJob.PropertyTo; var notifyKey = Prefix + SendEmailJob.PropertyTo;
if (context.JobInfo.Args.TryGetValue(notifyKey, out var exceptionTo) && if (eventData.Args.TryGetValue(notifyKey, out var exceptionTo) &&
exceptionTo is string to) exceptionTo is string to)
{ {
var template = context.JobInfo.Args.GetOrDefault(Prefix + SendEmailJob.PropertyTemplate)?.ToString() ?? ""; var template = eventData.Args.GetOrDefault(Prefix + SendEmailJob.PropertyTemplate)?.ToString() ?? "";
var content = context.JobInfo.Args.GetOrDefault(Prefix + SendEmailJob.PropertyBody)?.ToString() ?? ""; var content = eventData.Args.GetOrDefault(Prefix + SendEmailJob.PropertyBody)?.ToString() ?? "";
var subject = context.JobInfo.Args.GetOrDefault(Prefix + SendEmailJob.PropertySubject)?.ToString() ?? "From job execute exception"; var subject = eventData.Args.GetOrDefault(Prefix + SendEmailJob.PropertySubject)?.ToString() ?? "From job execute exception";
var from = context.JobInfo.Args.GetOrDefault(Prefix + SendEmailJob.PropertyFrom)?.ToString() ?? ""; var from = eventData.Args.GetOrDefault(Prefix + SendEmailJob.PropertyFrom)?.ToString() ?? "";
var errorMessage = context.Exception.GetBaseException().Message; var errorMessage = eventData.Exception.GetBaseException().Message;
if (template.IsNullOrWhiteSpace()) if (template.IsNullOrWhiteSpace())
{ {
@ -63,22 +63,22 @@ public class JobExceptionNotifier : IJobExceptionNotifier, ITransientDependency
return; return;
} }
var footer = context.JobInfo.Args.GetOrDefault("footer")?.ToString() ?? $"Copyright to LY Colin © {Clock.Now.Year}"; var footer = eventData.Args.GetOrDefault("footer")?.ToString() ?? $"Copyright to LY Colin © {Clock.Now.Year}";
var model = new var model = new
{ {
Title = subject, Title = subject,
Group = context.JobInfo.Group, Group = eventData.Group,
Name = context.JobInfo.Name, Name = eventData.Name,
Id = context.JobInfo.Id, Id = eventData.Key,
Type = context.JobInfo.Type, Type = eventData.Type,
Triggertime = Clock.Now.ToString("yyyy-MM-dd HH:mm:ss"), Triggertime = Clock.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Message = errorMessage, Message = errorMessage,
Tenantname = context.JobInfo.Args.GetOrDefault(nameof(IMultiTenant.TenantId)), Tenantname = eventData.Args.GetOrDefault(nameof(IMultiTenant.TenantId)),
Footer = footer, Footer = footer,
}; };
var globalContext = new Dictionary<string, object>(); var globalContext = new Dictionary<string, object>();
if (context.JobInfo.Args.TryGetValue(Prefix + SendEmailJob.PropertyContext, out var ctx) && if (eventData.Args.TryGetValue(Prefix + SendEmailJob.PropertyContext, out var ctx) &&
ctx is string ctxStr && !ctxStr.IsNullOrWhiteSpace()) ctx is string ctxStr && !ctxStr.IsNullOrWhiteSpace())
{ {
try try
@ -87,8 +87,9 @@ public class JobExceptionNotifier : IJobExceptionNotifier, ITransientDependency
} }
catch { } catch { }
} }
globalContext.AddIfNotContains(eventData.Args);
var culture = context.JobInfo.Args.GetOrDefault(Prefix + SendEmailJob.PropertyCulture)?.ToString() ?? CultureInfo.CurrentCulture.Name; var culture = eventData.Args.GetOrDefault(Prefix + SendEmailJob.PropertyCulture)?.ToString() ?? CultureInfo.CurrentCulture.Name;
content = await TemplateRenderer.RenderAsync( content = await TemplateRenderer.RenderAsync(
templateName: template, templateName: template,

30
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/AbpBackgroundTasksJobsModule.cs

@ -1,4 +1,6 @@
using LINGYUN.Abp.Dapr.Client; using LINGYUN.Abp.Dapr.Client;
using LINGYUN.Abp.Dapr.Client.DynamicProxying;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Emailing; using Volo.Abp.Emailing;
using Volo.Abp.Http.Client; using Volo.Abp.Http.Client;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -12,6 +14,23 @@ namespace LINGYUN.Abp.BackgroundTasks.Jobs;
[DependsOn(typeof(AbpDaprClientModule))] [DependsOn(typeof(AbpDaprClientModule))]
public class AbpBackgroundTasksJobsModule : AbpModule public class AbpBackgroundTasksJobsModule : AbpModule
{ {
protected const string DontWrapResultField = "_AbpDontWrapResult";
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientBuildActions.Add((remoteService, builder) =>
{
builder.ConfigureHttpClient(client =>
{
// 后台作业一般都是内部调用, 不需要包装结果
client.DefaultRequestHeaders.TryAddWithoutValidation(DontWrapResultField, "true");
});
});
});
}
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<AbpBackgroundTasksOptions>(options => Configure<AbpBackgroundTasksOptions>(options =>
@ -23,5 +42,16 @@ public class AbpBackgroundTasksJobsModule : AbpModule
options.AddProvider<ServiceInvocationJob>(DefaultJobNames.ServiceInvocationJob); options.AddProvider<ServiceInvocationJob>(DefaultJobNames.ServiceInvocationJob);
options.AddProvider<HttpRequestJob>(DefaultJobNames.HttpRequestJob); options.AddProvider<HttpRequestJob>(DefaultJobNames.HttpRequestJob);
}); });
Configure<AbpDaprClientProxyOptions>(options =>
{
options.ProxyRequestActions.Add((remoteService, request) =>
{
// 后台作业一般都是内部调用, 不需要包装结果
request.Headers.TryAddWithoutValidation(DontWrapResultField, "true");
});
});
context.Services.AddHttpClient(BackgroundTasksConsts.DefaultHttpClient);
} }
} }

6
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/BackgroundTasksConsts.cs

@ -0,0 +1,6 @@
namespace LINGYUN.Abp.BackgroundTasks.Jobs;
internal static class BackgroundTasksConsts
{
public const string DefaultHttpClient = "_AbpBackgroundTasks_Client";
}

2
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/HttpRequestJobBase.cs

@ -81,7 +81,7 @@ public abstract class HttpRequestJobBase
var clientFactory = context.GetRequiredService<IHttpClientFactory>(); var clientFactory = context.GetRequiredService<IHttpClientFactory>();
var client = clientName.IsNullOrWhiteSpace() var client = clientName.IsNullOrWhiteSpace()
? clientFactory.CreateClient() ? clientFactory.CreateClient(BackgroundTasksConsts.DefaultHttpClient)
: clientFactory.CreateClient(clientName); : clientFactory.CreateClient(clientName);
var response = await client.SendAsync(request); var response = await client.SendAsync(request);

8
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Jobs/LINGYUN/Abp/BackgroundTasks/Jobs/ServiceInvocationJob.cs

@ -57,13 +57,7 @@ public class ServiceInvocationJob : IJobRunnable
null); null);
} }
Guid? tenantId = null; context.TryGetMultiTenantId(PropertyTenant, out var tenantId);
if (context.TryGetString(PropertyTenant, out var tenant) &&
Guid.TryParse(tenant, out var converTenant))
{
tenantId = converTenant;
}
var currentTenant = context.GetRequiredService<ICurrentTenant>(); var currentTenant = context.GetRequiredService<ICurrentTenant>();
using (currentTenant.Change(tenantId)) using (currentTenant.Change(tenantId))
{ {

6
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobConcurrentAdapter.cs

@ -1,4 +1,4 @@
using System; using Microsoft.Extensions.DependencyInjection;
using Quartz; using Quartz;
namespace LINGYUN.Abp.BackgroundTasks.Quartz; namespace LINGYUN.Abp.BackgroundTasks.Quartz;
@ -7,8 +7,8 @@ namespace LINGYUN.Abp.BackgroundTasks.Quartz;
public class QuartzJobConcurrentAdapter<TJobRunnable> : QuartzJobSimpleAdapter<TJobRunnable> public class QuartzJobConcurrentAdapter<TJobRunnable> : QuartzJobSimpleAdapter<TJobRunnable>
where TJobRunnable : IJobRunnable where TJobRunnable : IJobRunnable
{ {
public QuartzJobConcurrentAdapter(IServiceProvider serviceProvider) public QuartzJobConcurrentAdapter(IServiceScopeFactory serviceScopeFactory)
: base(serviceProvider) : base(serviceScopeFactory)
{ {
} }
} }

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs

@ -37,16 +37,9 @@ public class QuartzJobExecutorProvider : IQuartzJobExecutorProvider, ISingletonD
return null; return null;
} }
var adapterType = typeof(QuartzJobSimpleAdapter<>);
// 注释, 通过触发器监听锁定
//if (job.LockTimeOut > 0)
//{
// adapterType = typeof(QuartzJobConcurrentAdapter<>);
//}
if (!typeof(IJob).IsAssignableFrom(jobType)) if (!typeof(IJob).IsAssignableFrom(jobType))
{ {
var adapterType = typeof(QuartzJobSimpleAdapter<>);
jobType = adapterType.MakeGenericType(jobType); jobType = adapterType.MakeGenericType(jobType);
} }

13
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs

@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using Quartz; using Quartz;
using Quartz.Listener; using Quartz.Listener;
using System; using System;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -67,7 +68,8 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency
jobId, jobId,
context.JobDetail.JobType, context.JobDetail.JobType,
context.JobDetail.Key.Group, context.JobDetail.Key.Group,
context.JobDetail.Key.Name) context.JobDetail.Key.Name,
context.MergedJobDataMap.ToImmutableDictionary())
{ {
Result = context.Result?.ToString() Result = context.Result?.ToString()
}; };
@ -120,6 +122,7 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency
jobType, jobType,
context.JobDetail.Key.Group, context.JobDetail.Key.Group,
context.JobDetail.Key.Name, context.JobDetail.Key.Name,
context.MergedJobDataMap.ToImmutableDictionary(),
jobException) jobException)
{ {
Status = JobStatus.Running Status = JobStatus.Running
@ -140,11 +143,9 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency
{ {
jobEventData.Result = context.Result?.ToString(); jobEventData.Result = context.Result?.ToString();
} }
var tenantIdString = context.GetString(nameof(IMultiTenant.TenantId));
if (Guid.TryParse(tenantIdString, out var tenantId)) context.TryGetMultiTenantId(out var tenantId);
{ jobEventData.TenantId = tenantId;
jobEventData.TenantId = tenantId;
}
var eventContext = new JobEventContext( var eventContext = new JobEventContext(
scope.ServiceProvider, scope.ServiceProvider,

78
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobScheduler.cs

@ -1,12 +1,17 @@
using Quartz; using Quartz;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks.Quartz; namespace LINGYUN.Abp.BackgroundTasks.Quartz;
[Dependency(ReplaceServices = true)] [Dependency(ReplaceServices = true)]
public class QuartzJobScheduler : IJobScheduler, ISingletonDependency [ExposeServices(
typeof(IJobScheduler),
typeof(IJobPublisher),
typeof(QuartzJobScheduler))]
public class QuartzJobScheduler : IJobScheduler, IJobPublisher, ISingletonDependency
{ {
protected IJobStore JobStore { get; } protected IJobStore JobStore { get; }
protected IScheduler Scheduler { get; } protected IScheduler Scheduler { get; }
@ -25,28 +30,33 @@ public class QuartzJobScheduler : IJobScheduler, ISingletonDependency
QuartzJobExecutor = quartzJobExecutor; QuartzJobExecutor = quartzJobExecutor;
} }
public virtual async Task<bool> ExistsAsync(JobInfo job) public virtual async Task<bool> ExistsAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
return await Scheduler.CheckExists(BuildJobKey(job)); return await Scheduler.CheckExists(BuildJobKey(job), cancellationToken);
} }
public virtual async Task PauseAsync(JobInfo job) public virtual async Task PauseAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
var jobKey = BuildJobKey(job); var jobKey = BuildJobKey(job);
if (await Scheduler.CheckExists(jobKey)) if (await Scheduler.CheckExists(jobKey, cancellationToken))
{ {
var triggers = await Scheduler.GetTriggersOfJob(jobKey); var triggers = await Scheduler.GetTriggersOfJob(jobKey, cancellationToken);
foreach (var trigger in triggers) foreach (var trigger in triggers)
{ {
await Scheduler.PauseTrigger(trigger.Key); await Scheduler.PauseTrigger(trigger.Key, cancellationToken);
} }
} }
} }
public virtual async Task<bool> QueueAsync(JobInfo job) public virtual async Task<bool> PublishAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return await QueueAsync(job, cancellationToken);
}
public virtual async Task<bool> QueueAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
var jobKey = BuildJobKey(job); var jobKey = BuildJobKey(job);
if (await Scheduler.CheckExists(jobKey)) if (await Scheduler.CheckExists(jobKey, cancellationToken))
{ {
return false; return false;
} }
@ -63,12 +73,12 @@ public class QuartzJobScheduler : IJobScheduler, ISingletonDependency
return false; return false;
} }
await Scheduler.ScheduleJob(jobDetail, jobTrigger); await Scheduler.ScheduleJob(jobDetail, jobTrigger, cancellationToken);
return await Scheduler.CheckExists(jobTrigger.Key); return await Scheduler.CheckExists(jobTrigger.Key, cancellationToken);
} }
public virtual async Task QueuesAsync(IEnumerable<JobInfo> jobs) public virtual async Task QueuesAsync(IEnumerable<JobInfo> jobs, CancellationToken cancellationToken = default)
{ {
var jobDictionary = new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>(); var jobDictionary = new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>();
foreach (var job in jobs) foreach (var job in jobs)
@ -88,78 +98,78 @@ public class QuartzJobScheduler : IJobScheduler, ISingletonDependency
jobDictionary[jobDetail] = new ITrigger[] { jobTrigger }; jobDictionary[jobDetail] = new ITrigger[] { jobTrigger };
} }
await Scheduler.ScheduleJobs(jobDictionary, true); await Scheduler.ScheduleJobs(jobDictionary, true, cancellationToken);
} }
public virtual async Task<bool> RemoveAsync(JobInfo job) public virtual async Task<bool> RemoveAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
var jobKey = BuildJobKey(job); var jobKey = BuildJobKey(job);
if (!await Scheduler.CheckExists(jobKey)) if (!await Scheduler.CheckExists(jobKey, cancellationToken))
{ {
return false; return false;
} }
var triggers = await Scheduler.GetTriggersOfJob(jobKey); var triggers = await Scheduler.GetTriggersOfJob(jobKey, cancellationToken);
foreach (var trigger in triggers) foreach (var trigger in triggers)
{ {
await Scheduler.PauseTrigger(trigger.Key); await Scheduler.PauseTrigger(trigger.Key, cancellationToken);
} }
await Scheduler.DeleteJob(jobKey); await Scheduler.DeleteJob(jobKey, cancellationToken);
return !await Scheduler.CheckExists(jobKey); return !await Scheduler.CheckExists(jobKey, cancellationToken);
} }
public virtual async Task ResumeAsync(JobInfo job) public virtual async Task ResumeAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
var jobKey = BuildJobKey(job); var jobKey = BuildJobKey(job);
if (await Scheduler.CheckExists(jobKey)) if (await Scheduler.CheckExists(jobKey, cancellationToken))
{ {
var triggers = await Scheduler.GetTriggersOfJob(jobKey); var triggers = await Scheduler.GetTriggersOfJob(jobKey, cancellationToken);
foreach (var trigger in triggers) foreach (var trigger in triggers)
{ {
await Scheduler.ResumeTrigger(trigger.Key); await Scheduler.ResumeTrigger(trigger.Key, cancellationToken);
} }
} }
} }
public virtual async Task<bool> ShutdownAsync() public virtual async Task<bool> ShutdownAsync(CancellationToken cancellationToken = default)
{ {
await StopAsync(); await StopAsync(cancellationToken);
await Scheduler.Shutdown(true); await Scheduler.Shutdown(true, cancellationToken);
return Scheduler.IsShutdown; return Scheduler.IsShutdown;
} }
public virtual async Task<bool> StartAsync() public virtual async Task<bool> StartAsync(CancellationToken cancellationToken = default)
{ {
if (Scheduler.InStandbyMode) if (Scheduler.InStandbyMode)
{ {
await Scheduler.Start(); await Scheduler.Start(cancellationToken);
} }
return Scheduler.InStandbyMode; return Scheduler.InStandbyMode;
} }
public virtual async Task<bool> StopAsync() public virtual async Task<bool> StopAsync(CancellationToken cancellationToken = default)
{ {
if (!Scheduler.InStandbyMode) if (!Scheduler.InStandbyMode)
{ {
//等待任务运行完成 //等待任务运行完成
await Scheduler.Standby(); await Scheduler.Standby(cancellationToken);
} }
return !Scheduler.InStandbyMode; return !Scheduler.InStandbyMode;
} }
public virtual async Task TriggerAsync(JobInfo job) public virtual async Task TriggerAsync(JobInfo job, CancellationToken cancellationToken = default)
{ {
var jobKey = BuildJobKey(job); var jobKey = BuildJobKey(job);
if (!await Scheduler.CheckExists(jobKey)) if (!await Scheduler.CheckExists(jobKey, cancellationToken))
{ {
await QueueAsync(job); await QueueAsync(job, cancellationToken);
} }
else else
{ {
await Scheduler.TriggerJob(jobKey); await Scheduler.TriggerJob(jobKey, cancellationToken);
} }
} }

20
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/Quartz/IJobExecutionContextExtensions.cs

@ -1,4 +1,5 @@
using System; using LINGYUN.Abp.BackgroundTasks;
using System;
namespace Quartz; namespace Quartz;
@ -24,4 +25,21 @@ public static class IJobExecutionContextExtensions
return value; return value;
} }
public static bool TryGetMultiTenantId(this IJobExecutionContext context, out Guid? tenantId)
{
return context.TryGetMultiTenantId(nameof(JobInfo.TenantId), out tenantId);
}
public static bool TryGetMultiTenantId(this IJobExecutionContext context, string multiTenancyKey, out Guid? tenantId)
{
tenantId = null;
var tenantUUIdString = context.GetString(multiTenancyKey);
if (Guid.TryParse(tenantUUIdString, out var tenantUUId))
{
tenantId = tenantUUId;
return true;
}
return false;
}
} }

16
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN.Abp.BackgroundTasks.TaskManagement.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.BackgroundTasks\LINGYUN.Abp.BackgroundTasks.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TaskManagement.HttpApi.Client\LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj" />
</ItemGroup>
</Project>

11
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN/Abp/BackgroundTasks/TaskManagement/AbpBackgroundTasksTaskManagementModule.cs

@ -0,0 +1,11 @@
using LINGYUN.Abp.TaskManagement.HttpApi.Client;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.BackgroundTasks.TaskManagement;
[DependsOn(typeof(AbpBackgroundTasksModule))]
[DependsOn(typeof(TaskManagementHttpApiClientModule))]
public class AbpBackgroundTasksTaskManagementModule : AbpModule
{
}

44
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.TaskManagement/LINGYUN/Abp/BackgroundTasks/TaskManagement/TaskManagementJobPublisher.cs

@ -0,0 +1,44 @@
using LINGYUN.Abp.TaskManagement;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks.TaskManagement;
public class TaskManagementJobPublisher : IJobPublisher, ITransientDependency
{
protected IBackgroundJobInfoAppService BackgroundJobAppService { get; }
public TaskManagementJobPublisher(
IBackgroundJobInfoAppService backgroundJobAppService)
{
BackgroundJobAppService = backgroundJobAppService;
}
public async virtual Task<bool> PublishAsync(JobInfo job, CancellationToken cancellationToken = default)
{
var input = new BackgroundJobInfoCreateDto
{
Cron = job.Cron,
MaxCount = job.MaxCount,
MaxTryCount = job.MaxTryCount,
Args = new ExtraPropertyDictionary(job.Args),
BeginTime = job.BeginTime,
Description = job.Description,
EndTime = job.EndTime,
Group = job.Group,
Interval = job.Interval,
Type = job.Type,
JobType = job.JobType,
LockTimeOut = job.LockTimeOut,
IsEnabled = true,
Name = job.Name,
Priority = job.Priority,
};
await BackgroundJobAppService.CreateAsync(input);
return true;
}
}

8
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs

@ -1,6 +1,7 @@
using LINGYUN.Abp.BackgroundTasks.Internal; using LINGYUN.Abp.BackgroundTasks.Internal;
using LINGYUN.Abp.BackgroundTasks.Localization; using LINGYUN.Abp.BackgroundTasks.Localization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.BackgroundJobs; using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundWorkers; using Volo.Abp.BackgroundWorkers;
@ -39,5 +40,12 @@ public class AbpBackgroundTasksModule : AbpModule
.Add<BackgroundTasksResource>("en") .Add<BackgroundTasksResource>("en")
.AddVirtualJson("/LINGYUN/Abp/BackgroundTasks/Localization/Resources"); .AddVirtualJson("/LINGYUN/Abp/BackgroundTasks/Localization/Resources");
}); });
Configure<AbpBackgroundTasksOptions>(options =>
{
options.JobMonitors.AddIfNotContains(typeof(JobExecutedEvent));
options.JobMonitors.AddIfNotContains(typeof(JobLogEvent));
options.JobMonitors.AddIfNotContains(typeof(JobNotifierEvent));
});
} }
} }

10
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/BackgroundJobManager.cs

@ -16,7 +16,7 @@ public class BackgroundJobManager : IBackgroundJobManager, ITransientDependency
{ {
protected IClock Clock { get; } protected IClock Clock { get; }
protected IJobStore JobStore { get; } protected IJobStore JobStore { get; }
protected IJobScheduler JobScheduler { get; } protected IJobPublisher JobPublisher { get; }
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IGuidGenerator GuidGenerator { get; } protected IGuidGenerator GuidGenerator { get; }
protected IJsonSerializer JsonSerializer { get; } protected IJsonSerializer JsonSerializer { get; }
@ -24,7 +24,7 @@ public class BackgroundJobManager : IBackgroundJobManager, ITransientDependency
public BackgroundJobManager( public BackgroundJobManager(
IClock clock, IClock clock,
IJobStore jobStore, IJobStore jobStore,
IJobScheduler jobScheduler, IJobPublisher jobPublisher,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
@ -32,7 +32,7 @@ public class BackgroundJobManager : IBackgroundJobManager, ITransientDependency
{ {
Clock = clock; Clock = clock;
JobStore = jobStore; JobStore = jobStore;
JobScheduler = jobScheduler; JobPublisher = jobPublisher;
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
GuidGenerator = guidGenerator; GuidGenerator = guidGenerator;
JsonSerializer = jsonSerializer; JsonSerializer = jsonSerializer;
@ -79,8 +79,8 @@ public class BackgroundJobManager : IBackgroundJobManager, ITransientDependency
// 存储状态 // 存储状态
await JobStore.StoreAsync(jobInfo); await JobStore.StoreAsync(jobInfo);
// 手动入队 // 发布作业
await JobScheduler.QueueAsync(jobInfo); await JobPublisher.PublishAsync(jobInfo);
return jobInfo.Id; return jobInfo.Id;
} }

10
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/BackgroundWorkerManager.cs

@ -11,14 +11,14 @@ namespace LINGYUN.Abp.BackgroundTasks;
public class BackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDependency public class BackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDependency
{ {
protected IJobStore JobStore { get; } protected IJobStore JobStore { get; }
protected IJobScheduler JobScheduler { get; } protected IJobPublisher JobPublisher { get; }
public BackgroundWorkerManager( public BackgroundWorkerManager(
IJobStore jobStore, IJobStore jobStore,
IJobScheduler jobScheduler) IJobPublisher jobPublisher)
{ {
JobStore = jobStore; JobStore = jobStore;
JobScheduler = jobScheduler; JobPublisher = jobPublisher;
} }
public async Task AddAsync(IBackgroundWorker worker) public async Task AddAsync(IBackgroundWorker worker)
@ -37,8 +37,8 @@ public class BackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDepen
// 存储状态 // 存储状态
await JobStore.StoreAsync(jobInfo); await JobStore.StoreAsync(jobInfo);
// 手动入队 // 发布作业
await JobScheduler.QueueAsync(jobInfo); await JobPublisher.PublishAsync(jobInfo);
} }
public Task StartAsync(CancellationToken cancellationToken = default) public Task StartAsync(CancellationToken cancellationToken = default)

9
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/IJobPublisher.cs

@ -0,0 +1,9 @@
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.BackgroundTasks;
public interface IJobPublisher
{
Task<bool> PublishAsync(JobInfo job, CancellationToken cancellationToken = default);
}

21
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/IJobScheduler.cs

@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
namespace LINGYUN.Abp.BackgroundTasks; namespace LINGYUN.Abp.BackgroundTasks;
/// <summary> /// <summary>
@ -12,61 +13,61 @@ public interface IJobScheduler
/// </summary> /// </summary>
/// <param name="job"></param> /// <param name="job"></param>
/// <returns></returns> /// <returns></returns>
Task<bool> QueueAsync(JobInfo job); Task<bool> QueueAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 任务入队 /// 任务入队
/// </summary> /// </summary>
/// <param name="jobs"></param> /// <param name="jobs"></param>
/// <returns></returns> /// <returns></returns>
Task QueuesAsync(IEnumerable<JobInfo> jobs); Task QueuesAsync(IEnumerable<JobInfo> jobs, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 任务是否存在 /// 任务是否存在
/// </summary> /// </summary>
/// <param name="group"></param> /// <param name="group"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
Task<bool> ExistsAsync(JobInfo job); Task<bool> ExistsAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 触发任务 /// 触发任务
/// </summary> /// </summary>
/// <param name="group"></param> /// <param name="group"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
Task TriggerAsync(JobInfo job); Task TriggerAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 暂停任务 /// 暂停任务
/// </summary> /// </summary>
/// <param name="group"></param> /// <param name="group"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
Task PauseAsync(JobInfo job); Task PauseAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 恢复暂停的任务 /// 恢复暂停的任务
/// </summary> /// </summary>
/// <param name="group"></param> /// <param name="group"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
Task ResumeAsync(JobInfo job); Task ResumeAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 移除任务 /// 移除任务
/// </summary> /// </summary>
/// <param name="group"></param> /// <param name="group"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
Task<bool> RemoveAsync(JobInfo job); Task<bool> RemoveAsync(JobInfo job, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 启动任务协调器 /// 启动任务协调器
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task<bool> StartAsync(); Task<bool> StartAsync(CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 停止任务协调器 /// 停止任务协调器
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task<bool> StopAsync(); Task<bool> StopAsync(CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 释放任务协调器 /// 释放任务协调器
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
Task<bool> ShutdownAsync(); Task<bool> ShutdownAsync(CancellationToken cancellationToken = default);
} }

27
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundKeepAliveJob.cs

@ -1,27 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Auditing;
namespace LINGYUN.Abp.BackgroundTasks.Internal;
[DisableAuditing]
public class BackgroundKeepAliveJob : IJobRunnable
{
public virtual async Task ExecuteAsync(JobRunnableContext context)
{
var store = context.ServiceProvider.GetRequiredService<IJobStore>();
// TODO: 如果积压有大量周期性任务, 可能后面的队列无法被检索到
var periodJobs = await store.GetAllPeriodTasksAsync();
if (!periodJobs.Any())
{
return;
}
var jobScheduler = context.ServiceProvider.GetRequiredService<IJobScheduler>();
await jobScheduler.QueuesAsync(periodJobs);
}
}

4
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundPollingJob.cs

@ -27,11 +27,11 @@ public class BackgroundPollingJob : IJobRunnable
return; return;
} }
var jobScheduler = context.ServiceProvider.GetRequiredService<IJobScheduler>(); var jobPublisher = context.ServiceProvider.GetRequiredService<IJobPublisher>();
foreach (var job in waitingJobs) foreach (var job in waitingJobs)
{ {
await jobScheduler.QueueAsync(job); await jobPublisher.PublishAsync(job);
} }
} }
} }

48
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs

@ -10,65 +10,41 @@ namespace LINGYUN.Abp.BackgroundTasks.Internal;
internal class DefaultBackgroundWorker : BackgroundService internal class DefaultBackgroundWorker : BackgroundService
{ {
private readonly IJobStore _jobStore; private readonly IJobStore _jobStore;
private readonly IJobScheduler _jobScheduler; private readonly IJobPublisher _jobPublisher;
private readonly AbpBackgroundTasksOptions _options; private readonly AbpBackgroundTasksOptions _options;
public DefaultBackgroundWorker( public DefaultBackgroundWorker(
IJobStore jobStore, IJobStore jobStore,
IJobScheduler jobScheduler, IJobPublisher jobPublisher,
IOptions<AbpBackgroundTasksOptions> options) IOptions<AbpBackgroundTasksOptions> options)
{ {
_jobStore = jobStore; _jobStore = jobStore;
_jobScheduler = jobScheduler; _jobPublisher = jobPublisher;
_options = options.Value; _options = options.Value;
} }
protected async override Task ExecuteAsync(CancellationToken stoppingToken) protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{ {
// 仅轮询宿主端
await QueuePollingJob(); await QueuePollingJob();
await QueueCleaningJob(); await QueueCleaningJob();
// 周期性任务改为手动入队
// await QueueKeepAliveJob();
}
private async Task QueueKeepAliveJob()
{
var keepAliveJob = BuildKeepAliveJobInfo();
await _jobScheduler.QueueAsync(keepAliveJob);
} }
private async Task QueuePollingJob() private async Task QueuePollingJob()
{ {
var pollingJob = BuildPollingJobInfo(); if (_options.JobFetchEnabled)
await _jobScheduler.QueueAsync(pollingJob); {
var pollingJob = BuildPollingJobInfo();
await _jobPublisher.PublishAsync(pollingJob);
}
} }
private async Task QueueCleaningJob() private async Task QueueCleaningJob()
{ {
var cleaningJob = BuildCleaningJobInfo(); if (_options.JobCleanEnabled)
await _jobScheduler.QueueAsync(cleaningJob);
}
private JobInfo BuildKeepAliveJobInfo()
{
return new JobInfo
{ {
Id = "KeepAlive", var cleaningJob = BuildCleaningJobInfo();
Name = nameof(BackgroundKeepAliveJob), await _jobPublisher.PublishAsync(cleaningJob);
Group = "KeepAlive", }
Description = "Add periodic tasks",
Args = new Dictionary<string, object>(),
Status = JobStatus.Running,
BeginTime = DateTime.Now,
CreationTime = DateTime.Now,
JobType = JobType.Once,
Priority = JobPriority.High,
MaxCount = 1,
Interval = 30,
Type = typeof(BackgroundKeepAliveJob).AssemblyQualifiedName,
};
} }
private JobInfo BuildPollingJobInfo() private JobInfo BuildPollingJobInfo()

19
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -64,9 +63,6 @@ public class JobExecutedEvent : JobEventBase<JobExecutedEvent>, ITransientDepend
job.NextRunTime = null; job.NextRunTime = null;
await RemoveJobAsync(context, job); await RemoveJobAsync(context, job);
} }
// 每次重试发布异常通知
await NotifierAsync(context, job);
} }
else else
{ {
@ -94,21 +90,6 @@ public class JobExecutedEvent : JobEventBase<JobExecutedEvent>, ITransientDepend
await jobScheduler.RemoveAsync(jobInfo); await jobScheduler.RemoveAsync(jobInfo);
} }
private async Task NotifierAsync(JobEventContext context, JobInfo jobInfo)
{
try
{
var notifier = context.ServiceProvider.GetRequiredService<IJobExceptionNotifier>();
var exceptionContext = new JobExceptionNotificationContext(jobInfo, context.EventData.Exception);
await notifier.NotifyAsync(exceptionContext);
}
catch (Exception ex)
{
Logger.LogWarning($"An exception thow with job exception notify: {ex.Message}");
}
}
private string GetExceptionMessage(Exception exception) private string GetExceptionMessage(Exception exception)
{ {
if (exception.InnerException != null) if (exception.InnerException != null)

32
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobNotifierEvent.cs

@ -0,0 +1,32 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks.Internal;
public class JobNotifierEvent : JobEventBase<JobNotifierEvent>, ITransientDependency
{
protected async override Task OnJobAfterExecutedAsync(JobEventContext context)
{
try
{
var notifier = context.ServiceProvider.GetRequiredService<IJobExecutedNotifier>();
if (context.EventData.Exception != null)
{
await notifier.NotifyErrorAsync(context);
}
else
{
await notifier.NotifySuccessAsync(context);
}
await notifier.NotifyComplateAsync(context);
}
catch (Exception ex)
{
Logger.LogWarning($"An exception thow with job notify: {ex.Message}");
}
}
}

12
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs

@ -6,18 +6,14 @@ using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.BackgroundTasks; namespace LINGYUN.Abp.BackgroundTasks;
public class JobRunnableExecuter : IJobRunnableExecuter, ISingletonDependency public class JobRunnableExecuter : IJobRunnableExecuter, ITransientDependency
{ {
public async virtual Task ExecuteAsync(JobRunnableContext context) public async virtual Task ExecuteAsync(JobRunnableContext context)
{ {
Guid? tenantId = null;
if (context.JobData.TryGetValue(nameof(IMultiTenant.TenantId), out var tenant) &&
Guid.TryParse(tenant?.ToString(), out var tid))
{
tenantId = tid;
}
var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>(); var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
context.TryGetMultiTenantId(out var tenantId);
using (currentTenant.Change(tenantId)) using (currentTenant.Change(tenantId))
{ {
await InternalExecuteAsync(context); await InternalExecuteAsync(context);

14
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/NullJobPublisher.cs

@ -0,0 +1,14 @@
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks;
[Dependency(TryRegister = true)]
public class NullJobPublisher : IJobPublisher, ISingletonDependency
{
public Task<bool> PublishAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
}

60
aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/NullJobScheduler.cs

@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.BackgroundTasks;
[Dependency(TryRegister = true)]
public class NullJobScheduler : IJobScheduler, ISingletonDependency
{
public Task<bool> ExistsAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task PauseAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public Task<bool> QueueAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task QueuesAsync(IEnumerable<JobInfo> jobs, CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public Task<bool> RemoveAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task ResumeAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public Task<bool> ShutdownAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task<bool> StartAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task<bool> StopAsync(CancellationToken cancellationToken = default)
{
return Task.FromResult(false);
}
public Task TriggerAsync(JobInfo job, CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
}

2
aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoCreateOrUpdateDto.cs

@ -10,7 +10,7 @@ public abstract class BackgroundJobInfoCreateOrUpdateDto
/// <summary> /// <summary>
/// 是否启用 /// 是否启用
/// </summary> /// </summary>
public bool IsEnabled { get; set; } public bool IsEnabled { get; set; } = true;
/// <summary> /// <summary>
/// 任务参数 /// 任务参数
/// </summary> /// </summary>

2
aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContext.cs

@ -1,8 +1,10 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.TaskManagement.EntityFrameworkCore; namespace LINGYUN.Abp.TaskManagement.EntityFrameworkCore;
[ConnectionStringName(TaskManagementDbProperties.ConnectionStringName)]
public class TaskManagementDbContext : AbpDbContext<TaskManagementDbContext>, ITaskManagementDbContext public class TaskManagementDbContext : AbpDbContext<TaskManagementDbContext>, ITaskManagementDbContext
{ {
public TaskManagementDbContext( public TaskManagementDbContext(

19
aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi.Client/LINGYUN.Abp.TaskManagement.HttpApi.Client.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Http.Client" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.TaskManagement.Application.Contracts\LINGYUN.Abp.TaskManagement.Application.Contracts.csproj" />
</ItemGroup>
</Project>

17
aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi.Client/LINGYUN/Abp/TaskManagement/TaskManagementHttpApiClientModule.cs

@ -0,0 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.TaskManagement.HttpApi.Client;
[DependsOn(typeof(TaskManagementApplicationContractsModule))]
[DependsOn(typeof(AbpHttpClientModule))]
public class TaskManagementHttpApiClientModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHttpClientProxies(
typeof(TaskManagementApplicationContractsModule).Assembly,
TaskManagementRemoteServiceConsts.RemoteServiceName);
}
}

2
aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Properties/launchSettings.json

@ -14,7 +14,7 @@
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "http://127.0.0.1:30010", "applicationUrl": "http://127.0.0.1:30010",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }

1
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/LY.MicroService.RealtimeMessage.HttpApi.Host.csproj

@ -43,6 +43,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" /> <ProjectReference Include="..\..\modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" /> <ProjectReference Include="..\..\modules\common\LINGYUN.Abp.AspNetCore.HttpOverrides\LINGYUN.Abp.AspNetCore.HttpOverrides.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.BackgroundWorkers.Hangfire\LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj" /> <ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Notifications\LINGYUN.Abp.ExceptionHandling.Notifications.csproj" /> <ProjectReference Include="..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Notifications\LINGYUN.Abp.ExceptionHandling.Notifications.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj" /> <ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj" />

31
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.Configure.cs

@ -11,6 +11,7 @@ using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -31,14 +32,15 @@ using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
using HangfireDashboardOptions = Hangfire.DashboardOptions; using HangfireDashboardOptions = Hangfire.DashboardOptions;
namespace LY.MicroService.RealtimeMessage; namespace LY.MicroService.RealtimeMessage;
public partial class RealtimeMessageHttpApiHostModule public partial class RealtimeMessageHttpApiHostModule
{ {
protected static string[] PrefixTokenQueryStrings = new [] { "/signalr-hubs", "/hangfire" };
private void PreConfigureApp() private void PreConfigureApp()
{ {
AbpSerilogEnrichersConsts.ApplicationName = "MessageService"; AbpSerilogEnrichersConsts.ApplicationName = "MessageService";
@ -292,13 +294,34 @@ public partial class RealtimeMessageHttpApiHostModule
var accessToken = context.Request.Query["access_token"]; var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path; var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/signalr-hubs"))) PrefixTokenQueryStrings.Any(prefix => path.StartsWithSegments(prefix)))
{ {
// Read the token out of the query string // 解决仪表板自定义授权问题
context.Token = accessToken; context.Token = accessToken;
var clock = context.HttpContext.RequestServices.GetRequiredService<IClock>();
var protectedProvider = context.HttpContext.RequestServices.GetRequiredService<IDataProtectionProvider>();
var protector = protectedProvider.CreateProtector("_hangfire_tk");
var tokenCookies = protector.Protect(accessToken);
context.HttpContext.Response.Cookies.Append(
"_hangfire_tk",
tokenCookies,
new CookieOptions
{
Expires = clock.Now.AddMinutes(10)
});
}
if (context.Token.IsNullOrWhiteSpace() &&
context.Request.Cookies.TryGetValue("_hangfire_tk", out var protectedToken))
{
var protectedProvider = context.HttpContext.RequestServices.GetRequiredService<IDataProtectionProvider>();
var protector = protectedProvider.CreateProtector("_hangfire_tk");
context.Token = protector.Unprotect(protectedToken);
} }
return Task.CompletedTask; return Task.CompletedTask;
} },
}; };
}); });

2
aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/RealtimeMessageHttpApiHostModule.cs

@ -2,6 +2,7 @@
using LINGYUN.Abp.AspNetCore.HttpOverrides; using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AuditLogging.Elasticsearch; using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.BackgroundJobs.Hangfire; using LINGYUN.Abp.BackgroundJobs.Hangfire;
using LINGYUN.Abp.BackgroundWorkers.Hangfire;
using LINGYUN.Abp.Data.DbMigrator; using LINGYUN.Abp.Data.DbMigrator;
using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling.Notifications; using LINGYUN.Abp.ExceptionHandling.Notifications;
@ -56,6 +57,7 @@ namespace LY.MicroService.RealtimeMessage
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpHangfireMySqlStorageModule), typeof(AbpHangfireMySqlStorageModule),
typeof(AbpBackgroundJobsHangfireModule), typeof(AbpBackgroundJobsHangfireModule),
typeof(AbpBackgroundWorkersHangfireModule),
typeof(AbpBackgroundWorkersModule), typeof(AbpBackgroundWorkersModule),
typeof(AbpIMSignalRModule), typeof(AbpIMSignalRModule),
typeof(AbpNotificationsSmsModule), typeof(AbpNotificationsSmsModule),

7
aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.Configure.cs

@ -1,4 +1,5 @@
using LINGYUN.Abp.ExceptionHandling; using DotNetCore.CAP;
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId; using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
@ -10,10 +11,10 @@ using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Quartz;
using StackExchange.Redis; using StackExchange.Redis;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Unicode; using System.Text.Unicode;
using Volo.Abp; using Volo.Abp;
@ -26,8 +27,6 @@ using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.Quartz; using Volo.Abp.Quartz;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
using Quartz;
using DotNetCore.CAP;
namespace LY.MicroService.TaskManagement; namespace LY.MicroService.TaskManagement;

2
aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs

@ -94,7 +94,7 @@ public partial class TaskManagementHttpApiHostModule : AbpModule
ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment()); ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment());
// 开发取消权限检查 // 开发取消权限检查
// context.Services.AddAlwaysAllowAuthorization(); context.Services.AddAlwaysAllowAuthorization();
} }
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)

Loading…
Cancel
Save