using System.Reflection; using Mapster; using Microsoft.AspNetCore.Mvc; using Quartz; using Quartz.Impl.Matchers; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Timing; using Yi.Framework.Rbac.Application.Contracts.Dtos.Task; using Yi.Framework.Rbac.Application.Contracts.IServices; using Yi.Framework.Rbac.Domain.Shared.Enums; namespace Yi.Framework.Rbac.Application.Services { public class TaskService : ApplicationService, ITaskService { private readonly ISchedulerFactory _schedulerFactory; private readonly IClock _clock; public TaskService(ISchedulerFactory schedulerFactory, IClock clock) { _clock=clock; _schedulerFactory = schedulerFactory; } /// /// 单查job /// /// /// [HttpGet("task/{jobId}")] public async Task GetAsync([FromRoute] string jobId) { var scheduler = await _schedulerFactory.GetScheduler(); var jobDetail = await scheduler.GetJobDetail(new JobKey(jobId)); var trigger = (await scheduler.GetTriggersOfJob(new JobKey(jobId))).First(); //状态 var state = await scheduler.GetTriggerState(trigger.Key); var output = new TaskGetOutput { JobId = jobDetail.Key.Name, GroupName = jobDetail.Key.Group, JobType = jobDetail.JobType.Name, Properties = Newtonsoft.Json.JsonConvert.SerializeObject(jobDetail.JobDataMap), Concurrent = !jobDetail.ConcurrentExecutionDisallowed, Description = jobDetail.Description, LastRunTime = _clock.Normalize( trigger.GetPreviousFireTimeUtc()?.DateTime??DateTime.MinValue), NextRunTime = _clock.Normalize(trigger.GetNextFireTimeUtc()?.DateTime ?? DateTime.MinValue), AssemblyName = jobDetail.JobType.Assembly.GetName().Name, Status = state.ToString() }; if (trigger is ISimpleTrigger simple) { output.TriggerArgs =Math.Round(simple.RepeatInterval.TotalMinutes,2) .ToString() + "分钟"; output.Type = JobTypeEnum.Millisecond; output.Millisecond = simple.RepeatInterval.TotalMilliseconds; } else if (trigger is ICronTrigger cron) { output.TriggerArgs = cron.CronExpressionString!; output.Type = JobTypeEnum.Cron; output.Cron=cron.CronExpressionString; } return output; } /// /// 多查job /// /// public async Task> GetListAsync([FromQuery] TaskGetListInput input) { var items = new List(); var scheduler = await _schedulerFactory.GetScheduler(); var groups = await scheduler.GetJobGroupNames(); foreach (var groupName in groups) { foreach (var jobKey in await scheduler.GetJobKeys(GroupMatcher.GroupEquals(groupName))) { string jobName = jobKey.Name; string jobGroup = jobKey.Group; var triggers = (await scheduler.GetTriggersOfJob(jobKey)).First(); items.Add(await GetAsync(jobName)); } } var output = items.Skip((input.SkipCount - 1) * input.MaxResultCount).Take(input.MaxResultCount) .OrderByDescending(x => x.LastRunTime) .ToList(); return new PagedResultDto(items.Count(), output.Adapt>()); } /// /// 创建job /// /// /// public async Task CreateAsync(TaskCreateInput input) { var scheduler = await _schedulerFactory.GetScheduler(); //设置启动时执行一次,然后最大只执行一次 //jobBuilder var jobClassType = Assembly.Load(input.AssemblyName).GetTypes().Where(x => x.Name == input.JobType).FirstOrDefault(); if (jobClassType is null) { throw new UserFriendlyException($"程序集:{input.AssemblyName},{input.JobType} 不存在"); } var jobBuilder = JobBuilder.Create(jobClassType).WithIdentity(new JobKey(input.JobId, input.GroupName)) .WithDescription(input.Description); if (!input.Concurrent) { jobBuilder.DisallowConcurrentExecution(); } //triggerBuilder TriggerBuilder triggerBuilder = null; switch (input.Type) { case JobTypeEnum.Cron: triggerBuilder = TriggerBuilder.Create() .WithCronSchedule(input.Cron); break; case JobTypeEnum.Millisecond: triggerBuilder = TriggerBuilder.Create().StartNow() .WithSimpleSchedule(x => x .WithInterval(TimeSpan.FromMilliseconds(input.Millisecond ?? 10000)) .RepeatForever() ); break; } //作业计划,单个jobBuilder与多个triggerBuilder组合 await scheduler.ScheduleJob(jobBuilder.Build(), triggerBuilder.Build()); } /// /// 移除job /// /// /// public async Task DeleteAsync(IEnumerable id) { var scheduler = await _schedulerFactory.GetScheduler(); await scheduler.DeleteJobs(id.Select(x => new JobKey(x)).ToList()); } /// /// 暂停job /// /// /// [HttpPut] public async Task PauseAsync(string jobId) { var scheduler = await _schedulerFactory.GetScheduler(); await scheduler.PauseJob(new JobKey(jobId)); } /// /// 开始job /// /// /// [HttpPut] public async Task StartAsync(string jobId) { var scheduler = await _schedulerFactory.GetScheduler(); await scheduler.ResumeJob(new JobKey(jobId)); } /// /// 更新job /// /// /// /// public async Task UpdateAsync(string id, TaskUpdateInput input) { await DeleteAsync(new List() { id }); await CreateAsync(input.Adapt()); } [HttpPost("task/run-once/{id}")] public async Task RunOnceAsync([FromRoute] string id) { var scheduler = await _schedulerFactory.GetScheduler(); var jobDetail = await scheduler.GetJobDetail(new JobKey(id)); var jobBuilder = JobBuilder.Create(jobDetail.JobType).WithIdentity(new JobKey(Guid.NewGuid().ToString())); //设置启动时执行一次,然后最大只执行一次 var trigger = TriggerBuilder.Create().WithIdentity(Guid.NewGuid().ToString()).StartNow() .WithSimpleSchedule(x => x .WithIntervalInHours(1) .WithRepeatCount(1)) .Build(); await scheduler.ScheduleJob(jobBuilder.Build(), trigger); } } }