diff --git a/aspnet-core/LINGYUN.MicroService.TaskManagement.sln b/aspnet-core/LINGYUN.MicroService.TaskManagement.sln new file mode 100644 index 000000000..0ae43b0bb --- /dev/null +++ b/aspnet-core/LINGYUN.MicroService.TaskManagement.sln @@ -0,0 +1,104 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{8DA8A2EE-0B26-487E-A6C4-518906E92B1B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C38EB7EF-BAE9-4129-862A-71C652B81775}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{77341F31-F54C-436A-AF8D-F78D91303C45}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.Domain.Shared", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain.Shared\LINGYUN.Abp.TaskManagement.Domain.Shared.csproj", "{691CD138-9FFA-4988-BAC4-A32F0DAE1090}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.Domain", "modules\task-management\LINGYUN.Abp.TaskManagement.Domain\LINGYUN.Abp.TaskManagement.Domain.csproj", "{8873A651-4F83-43B3-A34E-7AAA8A3ED4CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.Application.Contracts", "modules\task-management\LINGYUN.Abp.TaskManagement.Application.Contracts\LINGYUN.Abp.TaskManagement.Application.Contracts.csproj", "{D5EC4CA0-7E16-4D17-B08E-E162EF332C77}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.Application", "modules\task-management\LINGYUN.Abp.TaskManagement.Application\LINGYUN.Abp.TaskManagement.Application.csproj", "{09039DDF-5B0E-4670-8055-CC0BE82D4D2C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.HttpApi", "modules\task-management\LINGYUN.Abp.TaskManagement.HttpApi\LINGYUN.Abp.TaskManagement.HttpApi.csproj", "{283B0039-F67C-41F7-B554-DF5EE9178C4A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TaskManagement.EntityFrameworkCore", "modules\task-management\LINGYUN.Abp.TaskManagement.EntityFrameworkCore\LINGYUN.Abp.TaskManagement.EntityFrameworkCore.csproj", "{B8AB5E9B-9711-470E-8072-7444579EC5F6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C99728F6-FB3C-4D26-8917-1D30725209B9}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "provider", "provider", "{385578CC-C0F1-4377-A7A2-682B8F416234}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks", "modules\task-management\LINGYUN.Abp.BackgroundTasks\LINGYUN.Abp.BackgroundTasks.csproj", "{AC0B4342-9C9B-41E6-9646-E505C763EE77}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.Quartz", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Quartz\LINGYUN.Abp.BackgroundTasks.Quartz.csproj", "{7051C251-11D0-4971-B13E-F6929AE6DE89}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.TaskManagement.HttpApi.Host", "services\LY.MicroService.TaskManagement.HttpApi.Host\LY.MicroService.TaskManagement.HttpApi.Host.csproj", "{E8022994-A19F-4540-B9D1-7EF4AA85D18A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Abstractions", "modules\task-management\LINGYUN.Abp.BackgroundTasks.Abstractions\LINGYUN.Abp.BackgroundTasks.Abstractions.csproj", "{4A049C32-55F2-4A5F-954A-C8A977C2D87F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {691CD138-9FFA-4988-BAC4-A32F0DAE1090}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {691CD138-9FFA-4988-BAC4-A32F0DAE1090}.Debug|Any CPU.Build.0 = Debug|Any CPU + {691CD138-9FFA-4988-BAC4-A32F0DAE1090}.Release|Any CPU.ActiveCfg = Release|Any CPU + {691CD138-9FFA-4988-BAC4-A32F0DAE1090}.Release|Any CPU.Build.0 = Release|Any CPU + {8873A651-4F83-43B3-A34E-7AAA8A3ED4CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8873A651-4F83-43B3-A34E-7AAA8A3ED4CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8873A651-4F83-43B3-A34E-7AAA8A3ED4CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8873A651-4F83-43B3-A34E-7AAA8A3ED4CF}.Release|Any CPU.Build.0 = Release|Any CPU + {D5EC4CA0-7E16-4D17-B08E-E162EF332C77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5EC4CA0-7E16-4D17-B08E-E162EF332C77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5EC4CA0-7E16-4D17-B08E-E162EF332C77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5EC4CA0-7E16-4D17-B08E-E162EF332C77}.Release|Any CPU.Build.0 = Release|Any CPU + {09039DDF-5B0E-4670-8055-CC0BE82D4D2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09039DDF-5B0E-4670-8055-CC0BE82D4D2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09039DDF-5B0E-4670-8055-CC0BE82D4D2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09039DDF-5B0E-4670-8055-CC0BE82D4D2C}.Release|Any CPU.Build.0 = Release|Any CPU + {283B0039-F67C-41F7-B554-DF5EE9178C4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {283B0039-F67C-41F7-B554-DF5EE9178C4A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {283B0039-F67C-41F7-B554-DF5EE9178C4A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {283B0039-F67C-41F7-B554-DF5EE9178C4A}.Release|Any CPU.Build.0 = Release|Any CPU + {B8AB5E9B-9711-470E-8072-7444579EC5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B8AB5E9B-9711-470E-8072-7444579EC5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B8AB5E9B-9711-470E-8072-7444579EC5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B8AB5E9B-9711-470E-8072-7444579EC5F6}.Release|Any CPU.Build.0 = Release|Any CPU + {AC0B4342-9C9B-41E6-9646-E505C763EE77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC0B4342-9C9B-41E6-9646-E505C763EE77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC0B4342-9C9B-41E6-9646-E505C763EE77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC0B4342-9C9B-41E6-9646-E505C763EE77}.Release|Any CPU.Build.0 = Release|Any CPU + {7051C251-11D0-4971-B13E-F6929AE6DE89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7051C251-11D0-4971-B13E-F6929AE6DE89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7051C251-11D0-4971-B13E-F6929AE6DE89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7051C251-11D0-4971-B13E-F6929AE6DE89}.Release|Any CPU.Build.0 = Release|Any CPU + {E8022994-A19F-4540-B9D1-7EF4AA85D18A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8022994-A19F-4540-B9D1-7EF4AA85D18A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8022994-A19F-4540-B9D1-7EF4AA85D18A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8022994-A19F-4540-B9D1-7EF4AA85D18A}.Release|Any CPU.Build.0 = Release|Any CPU + {4A049C32-55F2-4A5F-954A-C8A977C2D87F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4A049C32-55F2-4A5F-954A-C8A977C2D87F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4A049C32-55F2-4A5F-954A-C8A977C2D87F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4A049C32-55F2-4A5F-954A-C8A977C2D87F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {691CD138-9FFA-4988-BAC4-A32F0DAE1090} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {8873A651-4F83-43B3-A34E-7AAA8A3ED4CF} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {D5EC4CA0-7E16-4D17-B08E-E162EF332C77} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {09039DDF-5B0E-4670-8055-CC0BE82D4D2C} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {283B0039-F67C-41F7-B554-DF5EE9178C4A} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {B8AB5E9B-9711-470E-8072-7444579EC5F6} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {AC0B4342-9C9B-41E6-9646-E505C763EE77} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + {7051C251-11D0-4971-B13E-F6929AE6DE89} = {385578CC-C0F1-4377-A7A2-682B8F416234} + {E8022994-A19F-4540-B9D1-7EF4AA85D18A} = {8DA8A2EE-0B26-487E-A6C4-518906E92B1B} + {4A049C32-55F2-4A5F-954A-C8A977C2D87F} = {C38EB7EF-BAE9-4129-862A-71C652B81775} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E1FD1F4C-D344-408B-97CF-B6F1F6D7D293} + EndGlobalSection +EndGlobal diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTaskConcurrentException.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTaskConcurrentException.cs new file mode 100644 index 000000000..a4f65d170 --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Abstractions/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTaskConcurrentException.cs @@ -0,0 +1,45 @@ +using System; +using Volo.Abp; + +namespace LINGYUN.Abp.BackgroundTasks; + +public class AbpBackgroundTaskConcurrentException : AbpException +{ + public Type JobType { get; } + /// + /// Creates a new object. + /// + /// Inner exception + public AbpBackgroundTaskConcurrentException(Type jobType) + : this( + jobType, + $"This job {jobType.Name} cannot be performed because it has been locked by another performer", + null) + { + } + + /// + /// Creates a new object. + /// + /// Execute job type + /// Inner exception + public AbpBackgroundTaskConcurrentException(Type jobType, Exception innerException) + : this( + jobType, + $"This job {jobType.Name} cannot be performed because it has been locked by another performer", + innerException) + { + } + + /// + /// Creates a new object. + /// + /// Execute job type + /// Exception message + /// Inner exception + public AbpBackgroundTaskConcurrentException(Type jobType, string message, Exception innerException) + : base(message, innerException) + { + JobType = jobType; + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobConcurrentAdapter.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobConcurrentAdapter.cs new file mode 100644 index 000000000..1fde4e3c0 --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobConcurrentAdapter.cs @@ -0,0 +1,14 @@ +using System; +using Quartz; + +namespace LINGYUN.Abp.BackgroundTasks.Quartz; + +[DisallowConcurrentExecution] +public class QuartzJobConcurrentAdapter : QuartzJobSimpleAdapter + where TJobRunnable : IJobRunnable +{ + public QuartzJobConcurrentAdapter(IServiceProvider serviceProvider) + : base(serviceProvider) + { + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs index ec3ab3501..45f35155e 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobExecutorProvider.cs @@ -35,6 +35,10 @@ public class QuartzJobExecutorProvider : IQuartzJobExecutorProvider, ISingletonD } var adapterType = typeof(QuartzJobSimpleAdapter<>); + if (job.LockTimeOut > 0) + { + adapterType = typeof(QuartzJobConcurrentAdapter<>); + } if (!typeof(IJob).IsAssignableFrom(jobType)) { @@ -88,6 +92,7 @@ public class QuartzJobExecutorProvider : IQuartzJobExecutorProvider, ISingletonD triggerBuilder .WithIdentity(job.Name, job.Group) .WithDescription(job.Description) + .StartAt(Clock.Now.AddSeconds(job.Interval)) .EndAt(job.EndTime) .ForJob(job.Name, job.Group) .WithPriority((int)job.Priority) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs index 7408ffcf2..b90cb54b6 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks.Quartz/LINGYUN/Abp/BackgroundTasks/Quartz/QuartzJobListener.cs @@ -82,7 +82,6 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency } } - [UnitOfWork] public override async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default) { try @@ -91,9 +90,15 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency var jobId = context.GetString(nameof(JobInfo.Id)); if (Guid.TryParse(jobId, out var jobUUId)) { + var jobType = context.JobDetail.JobType; + if (jobType.IsGenericType) + { + jobType = jobType.GetGenericArguments()[0]; + } + var jobEventData = new JobEventData( jobUUId, - context.JobDetail.JobType, + jobType, context.JobDetail.Key.Group, context.JobDetail.Key.Name, jobException) @@ -112,7 +117,7 @@ public class QuartzJobListener : JobListenerSupport, ISingletonDependency jobEventData.NextRunTime = context.NextFireTimeUtc?.LocalDateTime; if (context.Result != null) { - jobEventData.Result = context.Result.ToString(); + jobEventData.Result = context.Result?.ToString(); } var tenantIdString = context.GetString(nameof(IMultiTenant.TenantId)); if (Guid.TryParse(tenantIdString, out var tenantId)) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN.Abp.BackgroundTasks.csproj b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN.Abp.BackgroundTasks.csproj index 96b629b02..14206d3f2 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN.Abp.BackgroundTasks.csproj +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN.Abp.BackgroundTasks.csproj @@ -11,7 +11,7 @@ - + diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs index 205ccd0e9..2ee46ed95 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/AbpBackgroundTasksModule.cs @@ -12,9 +12,9 @@ using Volo.Abp.Reflection; namespace LINGYUN.Abp.BackgroundTasks; [DependsOn(typeof(AbpAuditingModule))] -[DependsOn(typeof(AbpDistributedLockingModule))] [DependsOn(typeof(AbpBackgroundTasksAbstractionsModule))] [DependsOn(typeof(AbpBackgroundJobsAbstractionsModule))] +[DependsOn(typeof(AbpDistributedLockingAbstractionsModule))] [DependsOn(typeof(AbpGuidsModule))] public class AbpBackgroundTasksModule : AbpModule { diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundCleaningJob.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundCleaningJob.cs index ee767808d..f21537b5d 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundCleaningJob.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/BackgroundCleaningJob.cs @@ -1,9 +1,11 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System.Threading.Tasks; +using Volo.Abp.Auditing; namespace LINGYUN.Abp.BackgroundTasks.Internal; +[DisableAuditing] internal class BackgroundCleaningJob : IJobRunnable { public virtual async Task ExecuteAsync(JobRunnableContext context) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs index e86ae7879..adce084cb 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/DefaultBackgroundWorker.cs @@ -63,6 +63,7 @@ internal class DefaultBackgroundWorker : BackgroundService JobType = JobType.Once, Priority = JobPriority.High, MaxCount = 1, + Interval = 30, Type = typeof(BackgroundKeepAliveJob).AssemblyQualifiedName, }; } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs index 4cbbc0fd9..dd2275dde 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobExecutedEvent.cs @@ -4,7 +4,7 @@ using Volo.Abp.DependencyInjection; namespace LINGYUN.Abp.BackgroundTasks.Internal; -internal class JobExecutedEvent : JobEventBase, ITransientDependency +public class JobExecutedEvent : JobEventBase, ITransientDependency { protected override async Task OnJobAfterExecutedAsync(JobEventContext context) { @@ -15,8 +15,8 @@ internal class JobExecutedEvent : JobEventBase, ITransientDepe { job.TriggerCount += 1; job.NextRunTime = context.EventData.NextRunTime; - job.LastRunTime = context.EventData.LastRunTime; - job.Result = context.EventData.Result; + job.LastRunTime = context.EventData.RunTime; + job.Result = context.EventData.Result ?? "OK"; // 一次性任务执行一次后标记为已完成 if (job.JobType == JobType.Once) @@ -53,7 +53,7 @@ internal class JobExecutedEvent : JobEventBase, ITransientDepe } // 所有任务达到上限则标记已完成 - if (job.MaxCount > 0 && job.TriggerCount > job.MaxCount) + if (job.MaxCount > 0 && job.TriggerCount >= job.MaxCount) { job.Status = JobStatus.Completed; diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobLogEvent.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobLogEvent.cs index 6fb015762..8a239d806 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobLogEvent.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Internal/JobLogEvent.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; namespace LINGYUN.Abp.BackgroundTasks.Internal; @@ -11,7 +12,7 @@ namespace LINGYUN.Abp.BackgroundTasks.Internal; /// /// 任务类型标记了 特性则不会记录日志 /// -internal class JobLogEvent : JobEventBase, ITransientDependency +public class JobLogEvent : JobEventBase, ITransientDependency { protected async override Task OnJobAfterExecutedAsync(JobEventContext context) { diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs index 24ad6721f..042f681fa 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/JobRunnableExecuter.cs @@ -10,7 +10,7 @@ namespace LINGYUN.Abp.BackgroundTasks; public class JobRunnableExecuter : IJobRunnableExecuter, ISingletonDependency { - protected const string LockKeyFormat = "job:{0},key:{1}"; + protected const string LockKeyFormat = "p:{0},job:{1},key:{2}"; public async virtual Task ExecuteAsync(JobRunnableContext context) { @@ -26,12 +26,21 @@ public class JobRunnableExecuter : IJobRunnableExecuter, ISingletonDependency { context.JobData.TryGetValue(nameof(JobInfo.LockTimeOut), out var lockTime); + // 某些提供者如果无法保证锁一致性, 那么需要用分布式锁 if (lockTime != null && (lockTime is int time && time > 0)) { var jobId = context.JobData.GetOrDefault(nameof(JobInfo.Id)); - var jobLockKey = string.Format(LockKeyFormat, context.JobType.Name, jobId); + var jobLockKey = string.Format(LockKeyFormat, tenantId?.ToString() ?? "Default", context.JobType.Name, jobId); var distributedLock = context.ServiceProvider.GetRequiredService(); - await using (await distributedLock.TryAcquireAsync(jobLockKey, TimeSpan.FromSeconds(time))) + + var handle = await distributedLock.TryAcquireAsync(jobLockKey, TimeSpan.FromSeconds(time)); + if (handle == null) + { + // 抛出异常 通过监听器使其重试 + throw new AbpBackgroundTaskConcurrentException(context.JobType); + } + + await using (handle) { await InternalExecuteAsync(context); } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Primitives/SleepJob.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Primitives/SleepJob.cs new file mode 100644 index 000000000..d2f65f17e --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.BackgroundTasks/LINGYUN/Abp/BackgroundTasks/Primitives/SleepJob.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.BackgroundTasks.Primitives; + +public class SleepJob : IJobRunnable +{ + public async Task ExecuteAsync(JobRunnableContext context) + { + context.JobData.TryGetValue("Delay", out var sleep); + + Console.WriteLine($"Sleep {sleep ?? 20000} milliseconds."); + + await Task.Delay(sleep?.To() ?? 20000); + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN.Abp.TaskManagement.Application.Contracts.csproj b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN.Abp.TaskManagement.Application.Contracts.csproj index d7b51dbfa..19dfce08a 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN.Abp.TaskManagement.Application.Contracts.csproj +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN.Abp.TaskManagement.Application.Contracts.csproj @@ -9,6 +9,7 @@ + diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobLogGetListInput.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobLogGetListInput.cs index 2967be0aa..2c8ee69c9 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobLogGetListInput.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobLogGetListInput.cs @@ -5,6 +5,7 @@ namespace LINGYUN.Abp.TaskManagement; public class BackgroundJobLogGetListInput : PagedAndSortedResultRequestDto { + public Guid? JobId { get; set; } /// /// 其他过滤条件 /// diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/IBackgroundJobLogAppService.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/IBackgroundJobLogAppService.cs index cc41aae14..6acde52ff 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/IBackgroundJobLogAppService.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/IBackgroundJobLogAppService.cs @@ -6,6 +6,7 @@ public interface IBackgroundJobLogAppService : IReadOnlyAppService< BackgroundJobLogDto, long, - BackgroundJobLogGetListInput> + BackgroundJobLogGetListInput>, + IDeleteAppService { } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissionDefinitionProvider.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissionDefinitionProvider.cs new file mode 100644 index 000000000..34503780c --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissionDefinitionProvider.cs @@ -0,0 +1,60 @@ +using LINGYUN.Abp.TaskManagement.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.TaskManagement.Permissions; + +public class TaskManagementPermissionDefinitionProvider : PermissionDefinitionProvider +{ + public override void Define(IPermissionDefinitionContext context) + { + var group = context.AddGroup( + TaskManagementPermissions.GroupName, + L("Permissions:TaskManagement"), + MultiTenancySides.Host); + + var backgroundJobs = group.AddPermission( + TaskManagementPermissions.BackgroundJobs.Default, + L("Permissions:BackgroundJobs"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Create, + L("Permissions:CreateJob"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Update, + L("Permissions:UpdateJob"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Delete, + L("Permissions:DeleteJob"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Trigger, + L("Permissions:TriggerJob"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Pause, + L("Permissions:PauseJob"), + MultiTenancySides.Host); + backgroundJobs.AddChild( + TaskManagementPermissions.BackgroundJobs.Resume, + L("Permissions:ResumeJob"), + MultiTenancySides.Host); + + var backgroundJobLogs = group.AddPermission( + TaskManagementPermissions.BackgroundJobLogs.Default, + L("Permissions:BackgroundJobLogs"), + MultiTenancySides.Host); + backgroundJobLogs.AddChild( + TaskManagementPermissions.BackgroundJobLogs.Delete, + L("Permissions:DeleteJobLogs"), + MultiTenancySides.Host); + } + + private ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissions.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissions.cs index 8ca7655fe..b30f69d67 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissions.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/Permissions/TaskManagementPermissions.cs @@ -14,4 +14,10 @@ public static class TaskManagementPermissions public const string Pause = Default + ".Pause"; public const string Resume = Default + ".Resume"; } + + public static class BackgroundJobLogs + { + public const string Default = GroupName + ".BackgroundJobLogs"; + public const string Delete = Default + ".Delete"; + } } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/TaskManagementRemoteServiceConsts.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/TaskManagementRemoteServiceConsts.cs new file mode 100644 index 000000000..c2d6dccd2 --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/TaskManagementRemoteServiceConsts.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.TaskManagement; + +public static class TaskManagementRemoteServiceConsts +{ + public const string RemoteServiceName = "TaskManagement"; + + public const string ModuleName = "task-management"; +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobLogAppService.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobLogAppService.cs new file mode 100644 index 000000000..012a1db32 --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobLogAppService.cs @@ -0,0 +1,53 @@ +using LINGYUN.Abp.TaskManagement.Permissions; +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.TaskManagement; + +[Authorize(TaskManagementPermissions.BackgroundJobLogs.Default)] +public class BackgroundJobLogAppService : TaskManagementApplicationService, IBackgroundJobLogAppService +{ + protected IBackgroundJobLogRepository BackgroundJobLogRepository { get; } + + public BackgroundJobLogAppService( + IBackgroundJobLogRepository backgroundJobLogRepository) + { + BackgroundJobLogRepository = backgroundJobLogRepository; + } + + [Authorize(TaskManagementPermissions.BackgroundJobLogs.Delete)] + public virtual Task DeleteAsync(long id) + { + return BackgroundJobLogRepository.DeleteAsync(id); + } + + public virtual async Task GetAsync(long id) + { + var backgroundJobLog = await BackgroundJobLogRepository.GetAsync(id); + + return ObjectMapper.Map(backgroundJobLog); + } + + public virtual async Task> GetListAsync(BackgroundJobLogGetListInput input) + { + var filter = new BackgroundJobLogFilter + { + BeginRunTime = input.BeginRunTime, + EndRunTime = input.EndRunTime, + HasExceptions = input.HasExceptions, + Filter = input.Filter, + Group = input.Group, + Name = input.Name, + Type = input.Type + }; + + var totalCount = await BackgroundJobLogRepository.GetCountAsync(filter, input.JobId); + var backgroundJobLogs = await BackgroundJobLogRepository.GetListAsync( + filter, input.JobId, input.Sorting, input.MaxResultCount, input.SkipCount); + + return new PagedResultDto(totalCount, + ObjectMapper.Map, List>(backgroundJobLogs)); + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/TaskManagementApplicationMapperProfile.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/TaskManagementApplicationMapperProfile.cs index 11468eb23..f250cfe5a 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/TaskManagementApplicationMapperProfile.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/TaskManagementApplicationMapperProfile.cs @@ -7,5 +7,6 @@ public class TaskManagementApplicationMapperProfile : Profile public TaskManagementApplicationMapperProfile() { CreateMap(); + CreateMap(); } } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/BackgroundJobInfoConsts.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/BackgroundJobInfoConsts.cs index bc316921f..25c26d24c 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/BackgroundJobInfoConsts.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/BackgroundJobInfoConsts.cs @@ -7,4 +7,5 @@ public static class BackgroundJobInfoConsts public static int MaxGroupLength { get; set; } = 50; public static int MaxTypeLength { get; set; } = 200; public static int MaxDescriptionLength { get; set; } = 255; + public static int MaxResultLength { get; set; } = 1000; } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/en.json b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/en.json index 10f2dda00..6f45cd09e 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/en.json +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/en.json @@ -1,6 +1,16 @@ { "culture": "en", "texts": { - "Permission:TaskManagement": "TaskManagement" + "Permissions:TaskManagement": "Task Management", + "Permissions:BackgroundJobs": "Background Jobs", + "Permissions:CreateJob": "Create Job", + "Permissions:UpdateJob": "Update Job", + "Permissions:DeleteJob": "Delete Job", + "Permissions:TriggerJob": "Trigger Job", + "Permissions:PauseJob": "Pause Job", + "Permissions:ResumeJob": "Resume Job", + "Permissions:BackgroundJobLogs": "BackgroundJobs Logs", + "Permissions:DeleteJobLogs": "Delete Job Logs", + "TaskManagement:01000": "A job named {Name} already exists in the Group {Group}!" } } \ No newline at end of file diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/zh-Hans.json index 5b3611e36..02a7e286b 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain.Shared/LINGYUN/Abp/TaskManagement/Localization/Resources/zh-Hans.json @@ -1,6 +1,16 @@ { "culture": "zh-Hans", "texts": { - "Permission:TaskManagement": "任务管理" + "Permissions:TaskManagement": "任务调度平台", + "Permissions:BackgroundJobs": "任务管理", + "Permissions:CreateJob": "新建作业", + "Permissions:UpdateJob": "编辑作业", + "Permissions:DeleteJob": "删除作业", + "Permissions:TriggerJob": "触发作业", + "Permissions:PauseJob": "暂停作业", + "Permissions:ResumeJob": "恢复作业", + "Permissions:BackgroundJobLogs": "日志管理", + "Permissions:DeleteJobLogs": "删除作业日志", + "TaskManagement:01000": "分组 {Group} 中已经存在一个名称为 {Name} 的作业!" } } \ No newline at end of file diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs index 4704f65b9..bb3d5d1e7 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobInfo.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.BackgroundTasks; using System; using System.Collections.Generic; +using Volo.Abp; using Volo.Abp.Data; using Volo.Abp.Domain.Entities.Auditing; @@ -21,6 +22,10 @@ public class BackgroundJobInfo : AuditedAggregateRoot /// public virtual string Type { get; protected set; } /// + /// 上一次执行结果 + /// + public virtual string Result { get; protected set; } + /// /// 任务参数 /// public virtual ExtraPropertyDictionary Args { get; protected set; } @@ -111,9 +116,9 @@ public class BackgroundJobInfo : AuditedAggregateRoot int maxCount = 0, int maxTryCount = 50) : base(id) { - Name = name; - Group = group; - Type = type; + Name = Check.NotNullOrWhiteSpace(name, nameof(name), BackgroundJobInfoConsts.MaxNameLength); + Group = Check.NotNullOrWhiteSpace(group, nameof(group), BackgroundJobInfoConsts.MaxGroupLength); + Type = Check.NotNullOrWhiteSpace(type, nameof(type), BackgroundJobInfoConsts.MaxTypeLength); Priority = priority; BeginTime = beginTime; EndTime = endTime; @@ -123,13 +128,15 @@ public class BackgroundJobInfo : AuditedAggregateRoot Status = JobStatus.Running; + // TODO: 是否需要将参数挪到另一个实体? + // 任务参数的建议是尽量最小化, 仅存储关键信息 Args = new ExtraPropertyDictionary(); Args.AddIfNotContains(args); } public void SetPeriodJob(string cron) { - Cron = cron; + Cron = Check.NotNullOrWhiteSpace(cron, nameof(cron), BackgroundJobInfoConsts.MaxCronLength); JobType = JobType.Period; } @@ -155,6 +162,20 @@ public class BackgroundJobInfo : AuditedAggregateRoot NextRunTime = nextRunTime; } + public void SetResult(string result) + { + if (result.IsNullOrWhiteSpace()) + { + return; + } + if (result.Length > BackgroundJobInfoConsts.MaxResultLength) + { + result = result.Substring(0, BackgroundJobInfoConsts.MaxResultLength - 1); + } + + Result = result; + } + public void SetStatus(JobStatus status) { Status = status; diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobLog.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobLog.cs index 9ae5ca1d0..192eaaacb 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobLog.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobLog.cs @@ -1,4 +1,5 @@ using System; +using Volo.Abp; using Volo.Abp.Domain.Entities; namespace LINGYUN.Abp.TaskManagement; @@ -13,12 +14,16 @@ public class BackgroundJobLog : Entity public virtual DateTime RunTime { get; protected set; } public virtual string Exception { get; protected set; } protected BackgroundJobLog() { } - public BackgroundJobLog(string type, string group, string name) + public BackgroundJobLog( + string type, + string group, + string name, + DateTime runTime) { - JobType = type; - JobGroup = group; - JobName = name; - RunTime = DateTime.Now; + JobType = Check.NotNullOrWhiteSpace(type, nameof(type), BackgroundJobInfoConsts.MaxTypeLength); + JobGroup = Check.NotNullOrWhiteSpace(group, nameof(group), BackgroundJobInfoConsts.MaxGroupLength); + JobName = Check.NotNullOrWhiteSpace(name, nameof(name), BackgroundJobInfoConsts.MaxNameLength); + RunTime = runTime; } public BackgroundJobLog SetMessage(string message, Exception ex) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobManager.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobManager.cs index 06b39aaea..bf7d50bd1 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobManager.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobManager.cs @@ -1,7 +1,9 @@ using LINGYUN.Abp.BackgroundTasks; using System.Threading.Tasks; +using Volo.Abp; using Volo.Abp.Domain.Services; using Volo.Abp.ObjectMapping; +using Volo.Abp.Uow; namespace LINGYUN.Abp.TaskManagement; @@ -9,15 +11,18 @@ public class BackgroundJobManager : DomainService { protected IObjectMapper ObjectMapper { get; } protected IJobScheduler JobScheduler { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } protected IBackgroundJobInfoRepository BackgroundJobInfoRepository { get; } public BackgroundJobManager( IObjectMapper objectMapper, IJobScheduler jobScheduler, + IUnitOfWorkManager unitOfWorkManager, IBackgroundJobInfoRepository backgroundJobInfoRepository) { ObjectMapper = objectMapper; JobScheduler = jobScheduler; + UnitOfWorkManager = unitOfWorkManager; BackgroundJobInfoRepository = backgroundJobInfoRepository; } @@ -28,7 +33,16 @@ public class BackgroundJobManager : DomainService if (jobInfo.IsEnabled && jobInfo.JobType == JobType.Period) { var job = ObjectMapper.Map(jobInfo); - await JobScheduler.QueueAsync(job); + if (await JobScheduler.ExistsAsync(job)) + { + throw new BusinessException(TaskManagementErrorCodes.JobNameAlreadyExists) + .WithData("Group", job.Group) + .WithData("Name", job.Name); + } + UnitOfWorkManager.Current.OnCompleted(async () => + { + await JobScheduler.QueueAsync(job); + }); } return jobInfo; @@ -40,13 +54,19 @@ public class BackgroundJobManager : DomainService if (!jobInfo.IsEnabled || resetJob) { - var job = ObjectMapper.Map(jobInfo); - await JobScheduler.RemoveAsync(job); + UnitOfWorkManager.Current.OnCompleted(async () => + { + var job = ObjectMapper.Map(jobInfo); + await JobScheduler.RemoveAsync(job); + }); } if (resetJob && jobInfo.JobType == JobType.Period) { - await QueueAsync(jobInfo); + UnitOfWorkManager.Current.OnCompleted(async () => + { + await QueueAsync(jobInfo); + }); } return jobInfo; @@ -54,10 +74,13 @@ public class BackgroundJobManager : DomainService public virtual async Task DeleteAsync(BackgroundJobInfo jobInfo) { - var job = ObjectMapper.Map(jobInfo); - await JobScheduler.RemoveAsync(job); - await BackgroundJobInfoRepository.DeleteAsync(jobInfo); + + UnitOfWorkManager.Current.OnCompleted(async () => + { + var job = ObjectMapper.Map(jobInfo); + await JobScheduler.RemoveAsync(job); + }); } public virtual async Task QueueAsync(BackgroundJobInfo jobInfo) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobStore.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobStore.cs index e5498ab6f..189f0bf9c 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobStore.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Domain/LINGYUN/Abp/TaskManagement/BackgroundJobStore.cs @@ -56,6 +56,7 @@ public class BackgroundJobStore : IJobStore, ITransientDependency backgroundJobInfo.SetNextRunTime(jobInfo.NextRunTime); backgroundJobInfo.SetLastRunTime(jobInfo.LastRunTime); backgroundJobInfo.SetStatus(jobInfo.Status); + backgroundJobInfo.SetResult(jobInfo.Result); backgroundJobInfo.TriggerCount = jobInfo.TriggerCount; backgroundJobInfo.TryCount = jobInfo.TryCount; backgroundJobInfo.IsAbandoned = jobInfo.IsAbandoned; @@ -79,6 +80,7 @@ public class BackgroundJobStore : IJobStore, ITransientDependency backgroundJobInfo.SetNextRunTime(jobInfo.NextRunTime); backgroundJobInfo.SetLastRunTime(jobInfo.LastRunTime); backgroundJobInfo.SetStatus(jobInfo.Status); + backgroundJobInfo.SetResult(jobInfo.Result); backgroundJobInfo.TriggerCount = jobInfo.TriggerCount; backgroundJobInfo.IsAbandoned = jobInfo.IsAbandoned; backgroundJobInfo.TryCount = jobInfo.TryCount; @@ -107,7 +109,8 @@ public class BackgroundJobStore : IJobStore, ITransientDependency var jogLog = new BackgroundJobLog( eventData.Type.Name, eventData.Group, - eventData.Name) + eventData.Name, + eventData.RunTime) { JobId = eventData.Key }; diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/EfCoreBackgroundJobInfoRepository.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/EfCoreBackgroundJobInfoRepository.cs index 8cc7bc601..ff840e35c 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/EfCoreBackgroundJobInfoRepository.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/EfCoreBackgroundJobInfoRepository.cs @@ -32,7 +32,7 @@ public class EfCoreBackgroundJobInfoRepository : CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) - .AllAsync(x => x.Group.Equals(group) && x.Name.Equals(name), + .AnyAsync(x => x.Group.Equals(group) && x.Name.Equals(name), GetCancellationToken(cancellationToken)); } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContextModelCreatingExtensions.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContextModelCreatingExtensions.cs index c32fabef7..e85773fb2 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContextModelCreatingExtensions.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.EntityFrameworkCore/LINGYUN/Abp/TaskManagement/EntityFrameworkCore/TaskManagementDbContextModelCreatingExtensions.cs @@ -43,6 +43,9 @@ public static class TaskManagementDbContextModelCreatingExtensions b.Property(p => p.Description) .HasColumnName(nameof(BackgroundJobInfo.Description)) .HasMaxLength(BackgroundJobInfoConsts.MaxDescriptionLength); + b.Property(p => p.Result) + .HasColumnName(nameof(BackgroundJobInfo.Result)) + .HasMaxLength(BackgroundJobInfoConsts.MaxResultLength); b.Property(p => p.Args) .HasColumnName(nameof(BackgroundJobInfo.Args)) .HasConversion(new ExtraPropertiesValueConverter(b.Metadata.ClrType)) diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobInfoController.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobInfoController.cs new file mode 100644 index 000000000..dd755ebbd --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobInfoController.cs @@ -0,0 +1,84 @@ +using LINGYUN.Abp.TaskManagement.Permissions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.TaskManagement; + +[RemoteService(Name = TaskManagementRemoteServiceConsts.RemoteServiceName)] +[Area(TaskManagementRemoteServiceConsts.ModuleName)] +[Authorize(TaskManagementPermissions.BackgroundJobs.Default)] +[Route($"api/{TaskManagementRemoteServiceConsts.ModuleName}/background-jobs")] +public class BackgroundJobInfoController : TaskManagementController, IBackgroundJobInfoAppService +{ + protected IBackgroundJobInfoAppService BackgroundJobInfoAppService { get; } + + public BackgroundJobInfoController( + IBackgroundJobInfoAppService backgroundJobInfoAppService) + { + BackgroundJobInfoAppService = backgroundJobInfoAppService; + } + + [HttpPost] + [Authorize(TaskManagementPermissions.BackgroundJobs.Create)] + public Task CreateAsync(BackgroundJobInfoCreateDto input) + { + return BackgroundJobInfoAppService.CreateAsync(input); + } + + [HttpDelete] + [Route("{id}")] + [Authorize(TaskManagementPermissions.BackgroundJobs.Delete)] + public Task DeleteAsync(Guid id) + { + return BackgroundJobInfoAppService.DeleteAsync(id); + } + + [HttpGet] + [Route("{id}")] + public Task GetAsync(Guid id) + { + return BackgroundJobInfoAppService.GetAsync(id); + } + + [HttpGet] + public Task> GetListAsync(BackgroundJobInfoGetListInput input) + { + return BackgroundJobInfoAppService.GetListAsync(input); + } + + [HttpPut] + [Route("{id}/pause")] + [Authorize(TaskManagementPermissions.BackgroundJobs.Pause)] + public Task PauseAsync(Guid id) + { + return BackgroundJobInfoAppService.PauseAsync(id); + } + + [HttpPut] + [Route("{id}/resume")] + [Authorize(TaskManagementPermissions.BackgroundJobs.Resume)] + public Task ResumeAsync(Guid id) + { + return BackgroundJobInfoAppService.ResumeAsync(id); + } + + [HttpPut] + [Route("{id}/trigger")] + [Authorize(TaskManagementPermissions.BackgroundJobs.Trigger)] + public Task TriggerAsync(Guid id) + { + return BackgroundJobInfoAppService.TriggerAsync(id); + } + + [HttpPut] + [Route("{id}")] + [Authorize(TaskManagementPermissions.BackgroundJobs.Update)] + public Task UpdateAsync(Guid id, BackgroundJobInfoUpdateDto input) + { + return BackgroundJobInfoAppService.UpdateAsync(id, input); + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobLogController.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobLogController.cs new file mode 100644 index 000000000..a84ddb52a --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/BackgroundJobLogController.cs @@ -0,0 +1,44 @@ +using LINGYUN.Abp.TaskManagement.Permissions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.TaskManagement; + +[RemoteService(Name = TaskManagementRemoteServiceConsts.RemoteServiceName)] +[Area(TaskManagementRemoteServiceConsts.ModuleName)] +[Authorize(TaskManagementPermissions.BackgroundJobLogs.Default)] +[Route($"api/{TaskManagementRemoteServiceConsts.ModuleName}/background-jobs/logs")] +public class BackgroundJobLogController : TaskManagementController, IBackgroundJobLogAppService +{ + protected IBackgroundJobLogAppService BackgroundJobLogAppService { get; } + + public BackgroundJobLogController( + IBackgroundJobLogAppService backgroundJobLogAppService) + { + BackgroundJobLogAppService = backgroundJobLogAppService; + } + + [HttpDelete] + [Route("{id}")] + [Authorize(TaskManagementPermissions.BackgroundJobLogs.Delete)] + public Task DeleteAsync(long id) + { + return BackgroundJobLogAppService.DeleteAsync(id); + } + + [HttpGet] + [Route("{id}")] + public Task GetAsync(long id) + { + return BackgroundJobLogAppService.GetAsync(id); + } + + [HttpGet] + public Task> GetListAsync(BackgroundJobLogGetListInput input) + { + return BackgroundJobLogAppService.GetListAsync(input); + } +} diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/TaskManagementController.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/TaskManagementController.cs new file mode 100644 index 000000000..0e011fd88 --- /dev/null +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.HttpApi/LINGYUN/Abp/TaskManagement/TaskManagementController.cs @@ -0,0 +1,12 @@ +using LINGYUN.Abp.TaskManagement.Localization; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.TaskManagement; + +public abstract class TaskManagementController : AbpControllerBase +{ + protected TaskManagementController() + { + LocalizationResource = typeof(TaskManagementResource); + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.Designer.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.Designer.cs new file mode 100644 index 000000000..bb69b999d --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.Designer.cs @@ -0,0 +1,188 @@ +// +using System; +using LY.MicroService.TaskManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LY.MicroService.TaskManagement.Migrations +{ + [DbContext(typeof(TaskManagementMigrationsDbContext))] + [Migration("20220109030916_Add-Module-Task-Management")] + partial class AddModuleTaskManagement + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Args") + .HasColumnType("longtext") + .HasColumnName("Args"); + + b.Property("BeginTime") + .HasColumnType("datetime(6)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Cron"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("Description"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Group"); + + b.Property("Interval") + .HasColumnType("int"); + + b.Property("IsAbandoned") + .HasColumnType("tinyint(1)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("JobType") + .HasColumnType("int"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("LastRunTime") + .HasColumnType("datetime(6)"); + + b.Property("LockTimeOut") + .HasColumnType("int"); + + b.Property("MaxCount") + .HasColumnType("int"); + + b.Property("MaxTryCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("Name"); + + b.Property("NextRunTime") + .HasColumnType("datetime(6)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TriggerCount") + .HasColumnType("int"); + + b.Property("TryCount") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("Type"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Group"); + + b.ToTable("TK_BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Exception") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)") + .HasColumnName("Exception"); + + b.Property("JobGroup") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("JobGroup"); + + b.Property("JobId") + .HasColumnType("char(36)"); + + b.Property("JobName") + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("JobName"); + + b.Property("JobType") + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("JobType"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("varchar(1000)") + .HasColumnName("Message"); + + b.Property("RunTime") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("JobGroup", "JobName"); + + b.ToTable("TK_BackgroundJobLogs", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.cs new file mode 100644 index 000000000..1c04c8779 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109030916_Add-Module-Task-Management.cs @@ -0,0 +1,108 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LY.MicroService.TaskManagement.Migrations +{ + public partial class AddModuleTaskManagement : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "TK_BackgroundJobLogs", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + JobId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + JobName = table.Column(type: "varchar(100)", maxLength: 100, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + JobGroup = table.Column(type: "varchar(50)", maxLength: 50, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + JobType = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Message = table.Column(type: "varchar(1000)", maxLength: 1000, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + RunTime = table.Column(type: "datetime(6)", nullable: false), + Exception = table.Column(type: "varchar(2000)", maxLength: 2000, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_TK_BackgroundJobLogs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "TK_BackgroundJobs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Group = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Type = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Args = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Status = table.Column(type: "int", nullable: false), + IsEnabled = table.Column(type: "tinyint(1)", nullable: false), + Description = table.Column(type: "varchar(255)", maxLength: 255, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + LockTimeOut = table.Column(type: "int", nullable: false), + BeginTime = table.Column(type: "datetime(6)", nullable: false), + EndTime = table.Column(type: "datetime(6)", nullable: true), + LastRunTime = table.Column(type: "datetime(6)", nullable: true), + NextRunTime = table.Column(type: "datetime(6)", nullable: true), + JobType = table.Column(type: "int", nullable: false), + Cron = table.Column(type: "varchar(50)", maxLength: 50, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Priority = table.Column(type: "int", nullable: false), + TriggerCount = table.Column(type: "int", nullable: false), + TryCount = table.Column(type: "int", nullable: false), + MaxTryCount = table.Column(type: "int", nullable: false), + MaxCount = table.Column(type: "int", nullable: false), + Interval = table.Column(type: "int", nullable: false), + IsAbandoned = table.Column(type: "tinyint(1)", nullable: false), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationTime = table.Column(type: "datetime(6)", nullable: false), + CreatorId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + LastModificationTime = table.Column(type: "datetime(6)", nullable: true), + LastModifierId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_TK_BackgroundJobs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_TK_BackgroundJobLogs_JobGroup_JobName", + table: "TK_BackgroundJobLogs", + columns: new[] { "JobGroup", "JobName" }); + + migrationBuilder.CreateIndex( + name: "IX_TK_BackgroundJobs_Name_Group", + table: "TK_BackgroundJobs", + columns: new[] { "Name", "Group" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "TK_BackgroundJobLogs"); + + migrationBuilder.DropTable( + name: "TK_BackgroundJobs"); + } + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.Designer.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.Designer.cs new file mode 100644 index 000000000..72dfca939 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.Designer.cs @@ -0,0 +1,193 @@ +// +using System; +using LY.MicroService.TaskManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LY.MicroService.TaskManagement.Migrations +{ + [DbContext(typeof(TaskManagementMigrationsDbContext))] + [Migration("20220109033926_Add-Field-Result-With-Background-Job-Info")] + partial class AddFieldResultWithBackgroundJobInfo + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Args") + .HasColumnType("longtext") + .HasColumnName("Args"); + + b.Property("BeginTime") + .HasColumnType("datetime(6)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Cron"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("Description"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Group"); + + b.Property("Interval") + .HasColumnType("int"); + + b.Property("IsAbandoned") + .HasColumnType("tinyint(1)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("JobType") + .HasColumnType("int"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("LastRunTime") + .HasColumnType("datetime(6)"); + + b.Property("LockTimeOut") + .HasColumnType("int"); + + b.Property("MaxCount") + .HasColumnType("int"); + + b.Property("MaxTryCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("Name"); + + b.Property("NextRunTime") + .HasColumnType("datetime(6)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Result") + .HasMaxLength(1000) + .HasColumnType("varchar(1000)") + .HasColumnName("Result"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TriggerCount") + .HasColumnType("int"); + + b.Property("TryCount") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("Type"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Group"); + + b.ToTable("TK_BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Exception") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)") + .HasColumnName("Exception"); + + b.Property("JobGroup") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("JobGroup"); + + b.Property("JobId") + .HasColumnType("char(36)"); + + b.Property("JobName") + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("JobName"); + + b.Property("JobType") + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("JobType"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("varchar(1000)") + .HasColumnName("Message"); + + b.Property("RunTime") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("JobGroup", "JobName"); + + b.ToTable("TK_BackgroundJobLogs", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.cs new file mode 100644 index 000000000..644c17adb --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/20220109033926_Add-Field-Result-With-Background-Job-Info.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LY.MicroService.TaskManagement.Migrations +{ + public partial class AddFieldResultWithBackgroundJobInfo : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Result", + table: "TK_BackgroundJobs", + type: "varchar(1000)", + maxLength: 1000, + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Result", + table: "TK_BackgroundJobs"); + } + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/TaskManagementMigrationsDbContextModelSnapshot.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/TaskManagementMigrationsDbContextModelSnapshot.cs new file mode 100644 index 000000000..233b57e47 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Migrations/TaskManagementMigrationsDbContextModelSnapshot.cs @@ -0,0 +1,191 @@ +// +using System; +using LY.MicroService.TaskManagement.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LY.MicroService.TaskManagement.Migrations +{ + [DbContext(typeof(TaskManagementMigrationsDbContext))] + partial class TaskManagementMigrationsDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Args") + .HasColumnType("longtext") + .HasColumnName("Args"); + + b.Property("BeginTime") + .HasColumnType("datetime(6)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Cron"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("varchar(255)") + .HasColumnName("Description"); + + b.Property("EndTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Group") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("Group"); + + b.Property("Interval") + .HasColumnType("int"); + + b.Property("IsAbandoned") + .HasColumnType("tinyint(1)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("JobType") + .HasColumnType("int"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("LastRunTime") + .HasColumnType("datetime(6)"); + + b.Property("LockTimeOut") + .HasColumnType("int"); + + b.Property("MaxCount") + .HasColumnType("int"); + + b.Property("MaxTryCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("Name"); + + b.Property("NextRunTime") + .HasColumnType("datetime(6)"); + + b.Property("Priority") + .HasColumnType("int"); + + b.Property("Result") + .HasMaxLength(1000) + .HasColumnType("varchar(1000)") + .HasColumnName("Result"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TriggerCount") + .HasColumnType("int"); + + b.Property("TryCount") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("Type"); + + b.HasKey("Id"); + + b.HasIndex("Name", "Group"); + + b.ToTable("TK_BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TaskManagement.BackgroundJobLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Exception") + .HasMaxLength(2000) + .HasColumnType("varchar(2000)") + .HasColumnName("Exception"); + + b.Property("JobGroup") + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasColumnName("JobGroup"); + + b.Property("JobId") + .HasColumnType("char(36)"); + + b.Property("JobName") + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("JobName"); + + b.Property("JobType") + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasColumnName("JobType"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("varchar(1000)") + .HasColumnName("Message"); + + b.Property("RunTime") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("JobGroup", "JobName"); + + b.ToTable("TK_BackgroundJobLogs", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs index 453210150..ef8042545 100644 --- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/TaskManagementHttpApiHostModule.cs @@ -6,6 +6,8 @@ using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.MultiTenancy.DbFinder; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.TaskManagement; +using LINGYUN.Abp.TaskManagement.EntityFrameworkCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; @@ -41,9 +43,9 @@ namespace LY.MicroService.TaskManagement; typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpDbFinderMultiTenancyModule), typeof(AbpBackgroundTasksQuartzModule), - //typeof(TaskManagementApplicationModule), - //typeof(TaskManagementHttpApiModule), - //typeof(TaskManagementEntityFrameworkCoreModule), + typeof(TaskManagementApplicationModule), + typeof(TaskManagementHttpApiModule), + typeof(TaskManagementEntityFrameworkCoreModule), typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.Development.json index 3315406f2..25b1a9c80 100644 --- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.Development.json @@ -93,7 +93,7 @@ "Override": { "System": "Warning", "Microsoft": "Warning", - "DotNetCore": "Debug" + "DotNetCore": "Warning" } }, "WriteTo": [ diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.json b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.json index 67e1bc4bd..1e85dd7a6 100644 --- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.json +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/appsettings.json @@ -9,7 +9,7 @@ "MinimumLevel": { "Default": "Debug", "Override": { - "Microsoft.EntityFrameworkCore": "Debug", + "Microsoft.EntityFrameworkCore": "Warning", "System": "Information", "Microsoft": "Information" }