using FluentScheduler; using Newtonsoft.Json; using Rhea.Common; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; using Tiger.Model.Minsun; namespace Tiger.Business { /// /// /// public class InterfaceServiceNew: IInterfaceService { #region Sundial计划调度 旧版本使用 public Sundial.ISchedulerFactory _schedulerFactory { get; set; } /// /// 设置计划任务工厂类 /// /// public void SetSchedulerFactory(Sundial.ISchedulerFactory schedulerFactory) { _schedulerFactory = schedulerFactory; } /// /// 根据实体类名及作业名称添加作业 /// /// /// /// public ApiAction AddJob(TJob newEntity, TskJobParam jobParam) where TJob : class, Sundial.IJob { ApiAction apiAction = new(); Sundial.TriggerBuilder triggerBuilder = Sundial.Triggers.Period(jobParam.Period*60*1000).LoadFrom(new { TriggerId = jobParam.JobName + "_trigger1", }); _schedulerFactory.AddJob(jobParam.JobName, triggerBuilder); var trigger = GetJob(jobParam.JobName).GetTrigger($"{jobParam.JobName}_trigger1"); TSK_JOB entity = ReturnDetail(jobParam.JobName); entity.Remark = jobParam.Remark; entity.JobType = typeof(TJob).Name; entity.JobName = jobParam.JobName; entity.TriggersWithGhost = new List { JsonConvert.DeserializeObject(JsonConvert.SerializeObject(trigger)) }; entity.Triggers[0].Args = jobParam.Period.ToString(); apiAction = SaveJob(entity); apiAction.Data = entity; return apiAction; } /// /// 根据作业名称添加作业 /// /// /// /// public ApiAction AddJob(string jobname, params Sundial.TriggerBuilder[] triggerBuilders) where TJob : class, Sundial.IJob { ApiAction apiAction = new(); triggerBuilders[0].LoadFrom(new { TriggerId = jobname + "_trigger1", }); _schedulerFactory.AddJob(jobname, triggerBuilders); var trigger = GetJob(jobname).GetTrigger($"{jobname}_trigger1"); TSK_JOB entity = ReturnDetail(jobname); entity.TriggersWithGhost = new List { JsonConvert.DeserializeObject(JsonConvert.SerializeObject(trigger)) }; apiAction = SaveJob(entity); apiAction.Data = entity; return apiAction; } /// /// 更新作业 /// /// /// public ApiAction UpdateJob(TSK_JOB job) { ApiAction apiAction = new ApiAction(); Sundial.IScheduler scheduler = GetJob(job.JobName); var trigger = scheduler.GetTrigger($"{job.JobName}_trigger1"); if (trigger.Status == Sundial.TriggerStatus.Running) { apiAction.IsSuccessed = false; apiAction.Message = $"作业[{job.JobName}]正在运行不能编辑"; } var triggerEntity = Biz.Db.Queryable().Where(x => x.JobId == job.ID).First(); if (triggerEntity != null) { triggerEntity.Status = (int)trigger.Status; triggerEntity.Args = job.uPeriod.ToString(); } var db = Business.Biz.Db; //保存到数据库 var dbTran = db.UseTran(() => { if (job != null) { db.Updateable(job, "system").ExecuteCommand(); } if (triggerEntity != null) { db.Updateable(triggerEntity, "system").ExecuteCommand(); } }); if (!dbTran.IsSuccess) { apiAction.GetResponse().CatchExceptionWithLog(dbTran.ErrorException, $"作业保存到数据库异常"); } //更新触发器周期 scheduler.UpdateTrigger($"{job.JobName}_trigger1", triggerBuilder => { triggerBuilder.SetArgs(job.uPeriod * 60 * 1000); }); ; return apiAction; } private TSK_JOB ReturnDetail(string jobname) { var jobDetail = GetJob(jobname).GetJobDetail(); return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(jobDetail)); } /// /// 启动所有作业 /// public void StartAllJob() { _schedulerFactory.StartAll(); } /// /// 启动单个作业 /// /// public void StartJob(string jobname) { // 带返回值 Sundial.IScheduler scheduler; var scheduleResult = _schedulerFactory.TryRunJob(jobname, out scheduler); } /// /// 获取单个作业 /// /// /// public Sundial.IScheduler GetJob(string jobname) { Sundial.IScheduler scheduler; var scheduleResult = _schedulerFactory.TryGetJob(jobname, out scheduler); return scheduler; } /// /// 获取所有作业 /// /// public List GetJobs() { return _schedulerFactory.GetJobs().ToList(); } /// /// 暂停作业 /// /// public void PauseJob(string jobname) { var scheduler = GetJob(jobname); if (scheduler != null) { scheduler.Pause(); } } /// /// 删除作业 /// /// public void RemoveJob(string jobname) { var scheduler = GetJob(jobname); if (scheduler != null) { scheduler.Remove(); } } /// /// 从数据库加载作业 /// public void AddJobFromDB() { try { var jobs = Biz.Db.Queryable().IncludesAllFirstLayer().ToList(); foreach (var job in jobs) { Type type = Type.GetType($"{job.AssemblyName}.{job.JobType},{job.AssemblyName}", throwOnError: true); _schedulerFactory.AddJob(type, job.JobName, Sundial.Triggers.Period(Convert.ToInt32(job.Triggers?[0].Args ?? "3") * 60 * 1000)); if (job.Triggers[0]?.Status == 3) { Work.DoAsync(() => { Thread.Sleep(2000); PauseJob(job.JobName); }); } } } catch (System.Exception ex) { Logger.Console.Fatal(ex, "Add Job From DB Exception"); } } /// /// 作业保存到数据库 /// /// private ApiAction SaveJob(TSK_JOB entity) { var action = new ApiAction(); entity.ID = Guid.NewGuid().ToString("N"); entity.Triggers[0].JobId = entity.ID; if (Biz.Db.Queryable().Where(x => x.JobName == entity.JobName && x.JobType == entity.JobType && x.AssemblyName == entity.AssemblyName).Any()) { action.IsSuccessed = false; action.Message = $"作业已经存在,不能保存数据"; return action; } var db = Business.Biz.Db; //保存到数据库 var dbTran = db.UseTran(() => { if (entity != null) { db.Insertable(entity, "system").ExecuteCommand(); } if (entity.Triggers.Any()) { db.Insertable(entity.Triggers, "system").ExecuteCommand(); } }); if (!dbTran.IsSuccess) { action.GetResponse().CatchExceptionWithLog(dbTran.ErrorException, $"作业保存到数据库异常"); } return action; } #endregion #region 新版本计划调度 FluentScheduler /// /// 初始化计划调度 /// public void JobInitialize() { JobManager.Initialize(); JobManager.JobException += info => Logger.Scheduler.Error("An error just happened with a scheduled job: " + info.Exception); JobManager.JobStart += info => Logger.Scheduler.Info($"{info.Name}: started"); JobManager.JobEnd += info => Logger.Scheduler.Info($"{info.Name}: ended ({info.Duration})"); } /// /// 添加工作任务 /// /// /// /// /// public ApiAction AddJob(TJob newEntity, FluentJobParam jobParam) where TJob : class, IJob { ApiAction apiAction = new(); try { JobManager.AddJob((s) => s.ToRunEvery(5).Seconds()); //Sundial.TriggerBuilder triggerBuilder = Sundial.Triggers.Period(jobParam.Period * 60 * 1000).LoadFrom(new //{ // TriggerId = jobParam.JobName + "_trigger1", //}); //_schedulerFactory.AddJob(jobParam.JobName, triggerBuilder); //var trigger = GetJob(jobParam.JobName).GetTrigger($"{jobParam.JobName}_trigger1"); //TSK_JOB entity = ReturnDetail(jobParam.JobName); //entity.Remark = jobParam.Remark; //entity.JobType = typeof(TJob).Name; //entity.JobName = jobParam.JobName; //entity.TriggersWithGhost = new List { JsonConvert.DeserializeObject(JsonConvert.SerializeObject(trigger)) }; //entity.Triggers[0].Args = jobParam.Period.ToString(); //apiAction = SaveJob(entity); //apiAction.Data = entity; } catch (System.Exception ex) { Logger.Console.Fatal(ex, "Add Job From DB Exception"); } return apiAction; } /// /// 从数据库批量添加任务 /// public void AddJobsFromDB() { try { var jobs = Biz.Db.Queryable().IncludesAllFirstLayer().ToList(); // 声明一个Registry类 var registry = new Registry(); foreach (var job in jobs) { Type type = Type.GetType($"{job.AssemblyName}.{job.JobType},{job.AssemblyName}", throwOnError: true); dynamic _type = Activator.CreateInstance(type); TrigArgs args = JsonConvert.DeserializeObject(job.Triggers[0].Args); Schedule schedule = Schedule(_type,job.JobName, registry); SpecificTimeUnit specificTimeUnit = null; TimeUnit timeUnit = null; if (args.NonReentrant == "Y") { schedule = schedule.NonReentrant(); } if (args.ToRunNow == "Y") { specificTimeUnit = schedule.ToRunNow(); } if (args.ToRunOnceIn > 0) { timeUnit = schedule.ToRunOnceIn(args.ToRunOnceIn); } else if (args.ToRunEvery >= 0) { timeUnit = schedule.ToRunEvery(args.ToRunEvery); } //按时间类型来运行 switch (args.Type) { case TrigArgs.EveryType.Milliseconds: timeUnit.Milliseconds(); break; case TrigArgs.EveryType.Seconds: timeUnit.Seconds(); break; case TrigArgs.EveryType.Minutes: timeUnit.Minutes(); break; case TrigArgs.EveryType.Hours: if (args.Minutes > 0) { timeUnit.Hours().At(args.Minutes); } else { timeUnit.Hours(); } break; case TrigArgs.EveryType.Days: if (args.Hours>0 && args.Minutes > 0 ) { timeUnit.Days().At(args.Hours, args.Minutes); } else { timeUnit.Days(); } break; case TrigArgs.EveryType.Weeks: if (args.Hours > 0 && args.Minutes > 0) { timeUnit.Weeks().At(args.Hours, args.Minutes); } else { timeUnit.Weeks(); } break; case TrigArgs.EveryType.Weekdays: if (args.Hours > 0 && args.Minutes > 0) { timeUnit.Weekdays().At(args.Hours, args.Minutes); } else { timeUnit.Weekdays(); } break; } } } catch (System.Exception ex) { Logger.Console.Fatal(ex, "Add Job From DB Exception"); } } /// /// 根据实体名注册计划 /// /// /// /// /// /// private Schedule Schedule(TJob entity, string JobName, Registry registry) where TJob : class, IJob { return registry.Schedule().WithName(JobName); } /// /// 停止服务 /// public void Stop() { JobManager.Stop(); } /// /// 在任务完成后等待或者停止 /// public void StopAndBlock() { JobManager.StopAndBlock(); } #endregion } }