| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- namespace Admin.NET.Core.Service;
- /// <summary>
- /// 定时任务服务
- /// </summary>
- [ApiDescriptionSettings(Name = "定时任务", Order = 188)]
- public class SysTimerService : IDynamicApiController, ITransient
- {
- private readonly SqlSugarRepository<SysTimer> _sysTimerRep;
- private readonly ISysCacheService _sysCacheService;
- public SysTimerService(SqlSugarRepository<SysTimer> sysTimerRep,
- ISysCacheService sysCacheService)
- {
- _sysTimerRep = sysTimerRep;
- _sysCacheService = sysCacheService;
- }
- /// <summary>
- /// 获取任务分页列表
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [HttpGet("/sysTimer/page")]
- public async Task<SqlSugarPagedList<TimerOutput>> GetTimerPage([FromQuery] PageTimerInput input)
- {
- var workers = SpareTime.GetWorkers().ToList();
- var timers = await _sysTimerRep.AsQueryable()
- .WhereIF(!string.IsNullOrWhiteSpace(input.TimerName), u => u.TimerName.Contains(input.TimerName))
- .Select<TimerOutput>()
- .ToPagedListAsync(input.Page, input.PageSize);
- timers.Items.ToList().ForEach(u =>
- {
- var timer = workers.FirstOrDefault(m => m.WorkerName == u.TimerName);
- if (timer != null)
- {
- u.Status = timer.Status;
- u.Tally = timer.Tally;
- u.Exception = JSON.Serialize(timer.Exception);
- }
- });
- return timers;
- }
- /// <summary>
- /// 增加任务
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [HttpPost("/sysTimer/add")]
- public async Task AddTimer(AddTimerInput input)
- {
- var isExist = await _sysTimerRep.IsAnyAsync(u => u.TimerName == input.TimerName);
- if (isExist) throw Oops.Oh(ErrorCodeEnum.D1100);
- var timer = input.Adapt<SysTimer>();
- await _sysTimerRep.InsertAsync(timer);
- CreateTimer(timer); // 添加到任务调度里
- }
- /// <summary>
- /// 删除任务
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [HttpPost("/sysTimer/delete")]
- public async Task DeleteTimer(DeleteTimerInput input)
- {
- var timer = await _sysTimerRep.GetFirstAsync(u => u.Id == input.Id);
- if (timer == null) throw Oops.Oh(ErrorCodeEnum.D1101);
- await _sysTimerRep.DeleteAsync(timer);
- SpareTime.Cancel(timer.TimerName); // 从调度器里取消
- }
- /// <summary>
- /// 更新任务
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [HttpPost("/sysTimer/update")]
- public async Task UpdateTimber(UpdateTimerInput input)
- {
- var isExist = await _sysTimerRep.IsAnyAsync(u => u.TimerName == input.TimerName && u.Id != input.Id);
- if (isExist) throw Oops.Oh(ErrorCodeEnum.D1100);
- // 先从调度器里取消
- var oldTimer = await _sysTimerRep.GetFirstAsync(u => u.Id == input.Id);
- SpareTime.Cancel(oldTimer.TimerName);
- var timer = input.Adapt<SysTimer>();
- await _sysTimerRep.AsUpdateable(timer).IgnoreColumns(true).ExecuteCommandAsync();
- CreateTimer(timer); // 再添加到任务调度里
- }
- /// <summary>
- /// 设置任务状态
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- [HttpPost("/sysTimer/setStatus")]
- public async void SetStatusTimer(SetTimerStatusInput input)
- {
- if (input.Status == SpareTimeStatus.Stopped)
- SpareTime.Stop(input.TimerName);
- else if (input.Status == SpareTimeStatus.Running)
- {
- var spareTime = SpareTime.GetWorkers().ToList().Find(u => u.WorkerName == input.TimerName);
- if (spareTime == null)
- {
- var timer = await _sysTimerRep.GetFirstAsync(u => u.TimerName == input.TimerName);
- CreateTimer(timer);
- }
- SpareTime.Start(input.TimerName); // 若StartNow=flase则不会启动任务
- }
- }
- /// <summary>
- /// 创建定时任务
- /// </summary>
- /// <param name="input"></param>
- private async void CreateTimer(SysTimer input)
- {
- Action<SpareTimer, long> action = null;
- switch (input.RequestType)
- {
- case RequestTypeEnum.Run: // 创建本地方法委托
- {
- var taskMethod = GetTimerMethodList()?.Result.FirstOrDefault(m => m.RequestUrl == input.RequestUrl);
- if (taskMethod == null) break;
- var typeInstance = Activator.CreateInstance(taskMethod.DeclaringType);
- action = (Action<SpareTimer, long>)Delegate.CreateDelegate(typeof(Action<SpareTimer, long>), typeInstance, taskMethod.MethodName);
- break;
- }
- default: // 创建网络任务委托
- {
- action = async (_, _) =>
- {
- var requestUrl = input.RequestUrl.Trim();
- requestUrl = requestUrl?.IndexOf("http") == 0 ? requestUrl : "http://" + requestUrl; // 默认http协议
- var requestParameters = input.RequestPara;
- var headersString = input.Headers;
- var headers = string.IsNullOrEmpty(headersString)
- ? null : JSON.Deserialize<Dictionary<string, string>>(headersString);
- switch (input.RequestType)
- {
- case RequestTypeEnum.Get:
- await requestUrl.SetHeaders(headers).GetAsync();
- break;
- case RequestTypeEnum.Post:
- await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PostAsync();
- break;
- case RequestTypeEnum.Put:
- await requestUrl.SetHeaders(headers).SetQueries(requestParameters).PutAsync();
- break;
- case RequestTypeEnum.Delete:
- await requestUrl.SetHeaders(headers).DeleteAsync();
- break;
- }
- };
- break;
- }
- }
- if (action == null) return;
- // 缓存任务配置参数供任务运行时读取
- if (input.RequestType == RequestTypeEnum.Run)
- {
- var timerParaName = $"{input.TimerName}_para";
- var timerPara = await _sysCacheService.ExistsAsync(timerParaName);
- var requestPara = string.IsNullOrEmpty(input.RequestPara);
- // 若没有任务配置但存在缓存则删除
- if (requestPara && timerPara)
- await _sysCacheService.RemoveAsync(timerParaName);
- else if (!requestPara)
- await _sysCacheService.SetAsync(timerParaName, JSON.Deserialize<Dictionary<string, string>>(input.RequestPara));
- }
- // 创建定时任务
- switch (input.TimerType)
- {
- case SpareTimeTypes.Interval:
- if (input.DoOnce)
- SpareTime.DoOnce((int)input.Interval * 1000, action, input.TimerName, input.Remark, input.StartNow, executeType: input.ExecuteType);
- else
- SpareTime.Do((int)input.Interval * 1000, action, input.TimerName, input.Remark, input.StartNow, executeType: input.ExecuteType);
- break;
- case SpareTimeTypes.Cron:
- SpareTime.Do(input.Cron, action, input.TimerName, input.Remark, input.StartNow, executeType: input.ExecuteType);
- break;
- }
- }
- /// <summary>
- /// 获取所有定时任务方法列表(贴spareTime特性)
- /// </summary>
- /// <returns></returns>
- private async Task<IEnumerable<TimerMethod>> GetTimerMethodList()
- {
- // 有缓存就返回缓存
- var timerMethodList = await _sysCacheService.GetAsync<IEnumerable<TimerMethod>>(CacheConst.KeyTimer);
- if (timerMethodList != null) return timerMethodList;
- timerMethodList = App.EffectiveTypes
- .Where(u => u.IsClass && !u.IsInterface && !u.IsAbstract && typeof(ISpareTimeWorker).IsAssignableFrom(u))
- .SelectMany(u => u.GetMethods(BindingFlags.Public | BindingFlags.Instance)
- .Where(m => m.IsDefined(typeof(SpareTimeAttribute), false) &&
- m.GetParameters().Length == 2 &&
- m.GetParameters()[0].ParameterType == typeof(SpareTimer) &&
- m.GetParameters()[1].ParameterType == typeof(long) && m.ReturnType == typeof(void))
- .Select(m =>
- {
- // 默认获取第一条任务特性
- var spareTimeAttribute = m.GetCustomAttribute<SpareTimeAttribute>();
- return new TimerMethod
- {
- TimerName = spareTimeAttribute.WorkerName,
- RequestUrl = $"{m.DeclaringType.Name}/{m.Name}",
- Cron = spareTimeAttribute.CronExpression,
- DoOnce = spareTimeAttribute.DoOnce,
- ExecuteType = spareTimeAttribute.ExecuteType,
- Interval = (int)spareTimeAttribute.Interval / 1000,
- StartNow = spareTimeAttribute.StartNow,
- RequestType = RequestTypeEnum.Run,
- Remark = spareTimeAttribute.Description,
- TimerType = string.IsNullOrEmpty(spareTimeAttribute.CronExpression) ? SpareTimeTypes.Interval : SpareTimeTypes.Cron,
- MethodName = m.Name,
- DeclaringType = m.DeclaringType
- };
- }));
- await _sysCacheService.SetAsync(CacheConst.KeyTimer, timerMethodList);
- return timerMethodList;
- }
- /// <summary>
- /// 启动自启动任务
- /// </summary>
- [NonAction]
- public async void StartTimer()
- {
- var timerList = await _sysTimerRep.GetListAsync(t => t.StartNow);
- timerList.ForEach(CreateTimer);
- }
- }
|