From 6f3b05c06125b457d0c78e259f3befe4910881cf Mon Sep 17 00:00:00 2001 From: Ben Lin <maobin001@msn.com> Date: 星期日, 27 十月 2024 16:54:29 +0800 Subject: [PATCH] 计划任务更新 --- Tiger.Business/Services/Base/InterfaceServiceNew.cs | 350 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 322 insertions(+), 28 deletions(-) diff --git a/Tiger.Business/Services/Base/InterfaceServiceNew.cs b/Tiger.Business/Services/Base/InterfaceServiceNew.cs index 76a0bfb..93e4aea 100644 --- a/Tiger.Business/Services/Base/InterfaceServiceNew.cs +++ b/Tiger.Business/Services/Base/InterfaceServiceNew.cs @@ -1,29 +1,37 @@ -锘縰sing Newtonsoft.Json; +锘縰sing FluentScheduler; +using Newtonsoft.Json; using Rhea.Common; using Sundial; using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; +using Tiger.Model.Entitys.MES.Position; using Tiger.Model.Minsun; -using static System.Collections.Specialized.BitVector32; +using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser; +using static Tiger.Model.TrigArgs; namespace Tiger.Business { - public class InterfaceServiceNew: IInterfaceService + /// <summary> + /// + /// </summary> + public class InterfaceServiceNew : IInterfaceService { + #region Sundial璁″垝璋冨害 鏃х増鏈娇鐢� - public ISchedulerFactory _schedulerFactory { get; set; } + public Sundial.ISchedulerFactory _schedulerFactory { get; set; } /// <summary> /// 璁剧疆璁″垝浠诲姟宸ュ巶绫� /// </summary> /// <param name="schedulerFactory"></param> - public void SetSchedulerFactory(ISchedulerFactory schedulerFactory) + public void SetSchedulerFactory(Sundial.ISchedulerFactory schedulerFactory) { _schedulerFactory = schedulerFactory; } @@ -34,10 +42,10 @@ /// <typeparam name="TJob"></typeparam> /// <param name="newEntity"></param> /// <param name="jobParam"></param> - public ApiAction AddJob<TJob>(TJob newEntity, TskJobParam jobParam) where TJob : class, IJob + public ApiAction AddJob<TJob>(TJob newEntity, TskJobParam jobParam) where TJob : class, Sundial.IJob { ApiAction apiAction = new(); - TriggerBuilder triggerBuilder = Triggers.Period(jobParam.Period*60*1000).LoadFrom(new + Sundial.TriggerBuilder triggerBuilder = Sundial.Triggers.Period(jobParam.Period * 60 * 1000).LoadFrom(new { TriggerId = jobParam.JobName + "_trigger1", }); @@ -60,7 +68,7 @@ /// <typeparam name="TJob"></typeparam> /// <param name="jobname"></param> /// <param name="triggerBuilders"></param> - public ApiAction AddJob<TJob>(string jobname, params TriggerBuilder[] triggerBuilders) where TJob : class, IJob + public ApiAction AddJob<TJob>(string jobname, params Sundial.TriggerBuilder[] triggerBuilders) where TJob : class, Sundial.IJob { ApiAction apiAction = new(); triggerBuilders[0].LoadFrom(new @@ -84,9 +92,9 @@ public ApiAction UpdateJob(TSK_JOB job) { ApiAction apiAction = new ApiAction(); - IScheduler scheduler = GetJob(job.JobName); + Sundial.IScheduler scheduler = GetJob(job.JobName); var trigger = scheduler.GetTrigger($"{job.JobName}_trigger1"); - if (trigger.Status == TriggerStatus.Running) + if (trigger.Status == Sundial.TriggerStatus.Running) { apiAction.IsSuccessed = false; apiAction.Message = $"浣滀笟[{job.JobName}]姝e湪杩愯涓嶈兘缂栬緫"; @@ -143,7 +151,8 @@ public void StartJob(string jobname) { // 甯﹁繑鍥炲�� - var scheduleResult = _schedulerFactory.TryRunJob(jobname); + Sundial.IScheduler scheduler; + var scheduleResult = _schedulerFactory.TryRunJob(jobname, out scheduler); } /// <summary> @@ -151,9 +160,9 @@ /// </summary> /// <param name="jobname"></param> /// <returns></returns> - public IScheduler GetJob(string jobname) + public Sundial.IScheduler GetJob(string jobname) { - IScheduler scheduler; + Sundial.IScheduler scheduler; var scheduleResult = _schedulerFactory.TryGetJob(jobname, out scheduler); return scheduler; } @@ -162,7 +171,7 @@ /// 鑾峰彇鎵�鏈変綔涓� /// </summary> /// <returns></returns> - public List<IScheduler> GetJobs() + public List<Sundial.IScheduler> GetJobs() { return _schedulerFactory.GetJobs().ToList(); } @@ -199,20 +208,20 @@ { try { - var jobs = Biz.Db.Queryable<TSK_JOB>().IncludesAllFirstLayer().ToList(); - foreach (var job in jobs) - { - Type type = Type.GetType($"{job.AssemblyName}.{job.JobType},{job.AssemblyName}", throwOnError: true); - _schedulerFactory.AddJob(type, job.JobName, 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); - }); - } - } + var jobs = Biz.Db.Queryable<TSK_JOB>().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) { @@ -254,5 +263,290 @@ } return action; } + #endregion + + #region 鏂扮増鏈鍒掕皟搴� FluentScheduler + /// <summary> + /// 鍒濆鍖栬鍒掕皟搴� + /// </summary> + public void JobInitialize() + { + JobManager.Initialize(AddJobsFromDB()); + 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\r\n"); + JobManager.JobEnd += info => Logger.Scheduler.Info($"{info.Name}: ended ({info.Duration})\r\n"); + SaveRunningStatus(); //淇濆瓨鐘舵�� + } + + private void SaveRunningStatus() + { + List<TSK_TRIG> listTrig = new List<TSK_TRIG>(); + foreach (var schedule in JobManager.RunningSchedules) + { + var job = Biz.Db.Queryable<TSK_JOB>().Where(q => q.JobName == schedule.Name).First(); + if (job != null) + { + TSK_TRIG trig = new TSK_TRIG(); + trig = Biz.Db.Queryable<TSK_TRIG>().Where(q => q.JobId == job.ID).First(); + trig.Status = TSK_TRIG.Statuss.Running.GetValue(); + trig.StartTime = DateTime.Now; + listTrig.Add(trig); + } + } + var db = Biz.Db; + //淇濆瓨鍒版暟鎹簱 + var dbTran = db.UseTran(() => + { + if (listTrig.Count > 0) + { + db.Updateable(listTrig, "system").UpdateColumns(q => new { q.Status, q.UPDATE_USER, q.UPDATE_TIME }).ExecuteCommand(); + } + }); + if (!dbTran.IsSuccess) + { + Logger.Scheduler.Trace(dbTran.ErrorException, $"浣滀笟淇濆瓨鍒版暟鎹簱寮傚父"); + } + } + + /// <summary> + /// 娣诲姞宸ヤ綔浠诲姟 + /// </summary> + /// <typeparam name="TJob"></typeparam> + /// <param name="newEntity"></param> + /// <param name="jobParam"></param> + /// <returns></returns> + public ApiAction AddTskJob<TJob>(TJob newEntity, FluentJobParam jobParam) where TJob : class, ITJob + { + ApiAction apiAction = new(); + try + { + if (!JobManager.AllSchedules.Any(q => q.Name == jobParam.JobName)) + { + JobManager.AddJob<TJob>((s) => GenerateSchedule(jobParam.Args, s.WithName(jobParam.JobName))); + string guid = Guid.NewGuid().ToString("N"); + TSK_JOB job = Biz.Db.Queryable<TSK_JOB>().Where(x => x.JobName == jobParam.JobName).First() ?? new() + { + ID = guid, + Remark = jobParam.Remark, + JobType = jobParam.JobName, + AssemblyName = jobParam.AssemblyName, + JobName = jobParam.JobName, + }; + var trigger = Biz.Db.Queryable<TSK_TRIG>().Where(x => x.JobId == job.ID).First() ?? new TSK_TRIG() + { + JobId = guid, + StartTime = DateTime.Now, + NumberOfRuns = 1, + }; + trigger.Args = JsonConvert.SerializeObject(jobParam.Args); + trigger.Status = TSK_TRIG.Statuss.Running.GetValue(); + var db = Biz.Db; + //淇濆瓨鍒版暟鎹簱 + var dbTran = db.UseTran(() => + { + var y = db.Storageable(job) + .WhereColumns(t => new { t.JobName, t.GHOST_ROW }) + .ToStorage(); + y.AsInsertable.ExecuteCommand(); + y.AsUpdateable.IgnoreColumns(x => x.ID).ExecuteCommand(); + + var z = db.Storageable(trigger) + .WhereColumns(t => new { t.JobId, t.GHOST_ROW }) + .ToStorage(); + z.AsInsertable.ExecuteCommand(); + z.AsUpdateable.IgnoreColumns(x => x.ID).ExecuteCommand(); + }); + if (!dbTran.IsSuccess) + { + apiAction.CatchExceptionWithLog(dbTran.ErrorException, $"娣诲姞宸ヤ綔浠诲姟鏃朵繚瀛樺埌鏁版嵁搴撳紓甯�"); + } + } + + } + catch (System.Exception ex) + { + apiAction.CatchExceptionWithLog(ex); + } + if (!apiAction.IsSuccessed) { JobManager.RemoveJob(jobParam.JobName); } + return apiAction; + } + + /// <summary> + /// 鍒犻櫎浣滀笟 + /// </summary> + /// <param name="jobname"></param> + public void RemovefJob(string jobname) + { + if (JobManager.AllSchedules.Any(q => q.Name == jobname)) + { + string guid = Guid.NewGuid().ToString("N"); + TSK_JOB job = Biz.Db.Queryable<TSK_JOB>().Where(x => x.JobName == jobname).First(); + var trigger = Biz.Db.Queryable<TSK_TRIG>().Where(x => x.JobId == job.ID).First(); + trigger.Status = TSK_TRIG.Statuss.Stop.GetValue(); + var db = Biz.Db; + //淇濆瓨鍒版暟鎹簱 + var dbTran = db.UseTran(() => + { + db.Updateable(trigger, "system_job").UpdateColumns(q=>new { q.Status,q.UPDATE_TIME,q.UPDATE_USER}).ExecuteCommand(); + }); + if (!dbTran.IsSuccess) + { + Logger.Scheduler.Fatal(dbTran.ErrorException, $"娣诲姞宸ヤ綔浠诲姟鏃朵繚瀛樺埌鏁版嵁搴撳紓甯�"); + } + } + JobManager.RemoveJob(jobname); + } + + /// <summary> + /// 浠庢暟鎹簱鎵归噺娣诲姞浠诲姟 + /// </summary> + public Registry AddJobsFromDB() + { + // 澹版槑涓�涓猂egistry绫� + var registry = new Registry(); + try + { + var jobs = Biz.Db.Queryable<TSK_JOB>().IncludesAllFirstLayer().ToList(); + foreach (var job in jobs) + { + if (job.JobName == "fU9C_MES_GetWo" || job.JobName == "fTest") + { + Type type = Type.GetType($"{job.AssemblyName}.{job.JobType},{job.AssemblyName}", throwOnError: true); + dynamic _type = Activator.CreateInstance(type); + TrigArgs args = JsonConvert.DeserializeObject<TrigArgs>(job.Triggers[0].Args); + Schedule schedule = Schedule(_type, job.JobName, registry); + //鐢熸垚璁″垝 + GenerateSchedule(args, schedule); + } + } + } + catch (System.Exception ex) + { + Logger.Console.Fatal(ex, "Add Job From DB Exception"); + } + return registry; + } + + /// <summary> + /// 鏍规嵁瀹炰綋鍚嶆敞鍐岃鍒� + /// </summary> + /// <typeparam name="TJob"></typeparam> + /// <param name="entity"></param> + /// <param name="JobName"></param> + /// <param name="registry"></param> + /// <returns></returns> + private Schedule Schedule<TJob>(TJob entity, string JobName, Registry registry) where TJob : class, ITJob + { + return registry.Schedule<TJob>().WithName(typeof(TJob).Name); + } + + /// <summary> + /// 鐢熸垚璁″垝 + /// </summary> + /// <param name="args"></param> + /// <param name="schedule"></param> + private void GenerateSchedule(TrigArgs args, Schedule schedule) + { + SpecificTimeUnit specificTimeUnit = null; + TimeUnit timeUnit = null; + if (args.NonReentrant == "Y") { schedule = schedule.NonReentrant(); } //灏辨槸鏄惁璺熶箣鍓嶇殑杩樻病杩愯瀹岀殑璁″垝鍚屾椂杩愯銆� + switch (args.runType) + { + case RunType.ToRunNow: + specificTimeUnit = schedule.ToRunNow(); //椹笂杩愯 + break; + case RunType.ToRunOnceAt: + specificTimeUnit = schedule.ToRunOnceAt(args.ToRunOnceAtDt.AddMinutes(args.NowAddMinutes)); //杩愯涓�娆″湪鍝釜鏃堕棿, + break; + case RunType.ToRunOnceIn: + timeUnit = schedule.ToRunOnceIn(args.ToRunOnceIn); //鍦ㄥ灏戝悗杩愯涓�娆� + break; + case RunType.ToRunEvery: + timeUnit = schedule.ToRunEvery(args.ToRunEvery); //姣忛殧澶氬皯杩愯涓�鍥� + break; + } + if (specificTimeUnit != null) { timeUnit = specificTimeUnit.AndEvery(args.ToRunEvery); } //姣忛殧澶氬皯杩愯涓�鍥烇紝鍔犲湪ToRunNow銆乀oRunOnceAt鍚庨潰 + //鎸夋椂闂寸被鍨嬫潵杩愯 + switch (args.Type) + { + case TrigArgs.EveryType.Milliseconds: + timeUnit.Milliseconds(); + break; + case TrigArgs.EveryType.Seconds: + timeUnit.Seconds(); //琛ㄧず鎸夌锛屽灏戠瑕佺湅鍓嶉潰Every鐨勬暟锛屾瘮濡傦細ToRunEvery(5).Seconds() 杩欎釜灏辫〃绀� 闅�5绉掕繍琛屼竴娆� + break; + case TrigArgs.EveryType.Minutes: + timeUnit.Minutes(); + break; + case TrigArgs.EveryType.Hours: + if (args.Minutes > 0) + { + timeUnit.Hours().At(args.Minutes); //琛ㄧず鎸夋瘡灏忔椂鐨勫垎閽燂紝澶氬皯鍒嗚鐪嬪墠闈very鐨勬暟锛屾瘮濡傦細ToRunEvery(1).Hours().At(5) 杩欎釜灏辫〃绀� 闅�1灏忔椂鐨勭5鍒嗛挓杩愯涓�娆� + } + else + { + timeUnit.Hours(); + } + break; + case TrigArgs.EveryType.Days: + if (args.Hours > 0) + { + timeUnit.Days().At(args.Hours, args.Minutes); //琛ㄧず鎸夊ぉ锛屽灏戝ぉ瑕佺湅鍓嶉潰Every鐨勬暟锛屾瘮濡傦細ToRunEvery(2).Days().At(14, 15) 杩欎釜灏辫〃绀� 闅�2澶╃殑14:15杩愯涓�娆� + } + else + { + timeUnit.Days(); + } + break; + case TrigArgs.EveryType.Weeks: + if (args.Hours > 0) + { + timeUnit.Weeks().At(args.Hours, args.Minutes); //琛ㄧず鎸夊懆锛屽灏戝懆瑕佺湅鍓嶉潰Every鐨勬暟锛屾瘮濡傦細ToRunEvery(1).Weeks().At(14, 15) 杩欎釜灏辫〃绀� 闅�1鍛ㄧ殑14:15杩愯涓�娆� + } + else + { + timeUnit.Weeks(); + } + break; + case TrigArgs.EveryType.Weekdays: + if (args.Hours > 0) + { + timeUnit.Weekdays().At(args.Hours, args.Minutes); + } + else + { + timeUnit.Weekdays(); + } + break; + case TrigArgs.EveryType.Months: + if (args.Days > 0 && args.Hours > 0) + { + timeUnit.Months().On(args.Days).At(args.Hours, args.Minutes); + } + else + { + timeUnit.Months(); + } + break; + } + } + + /// <summary> + /// 鍋滄鏈嶅姟 + /// </summary> + public void Stop() + { + JobManager.Stop(); + } + + /// <summary> + /// 鍦ㄤ换鍔″畬鎴愬悗绛夊緟鎴栬�呭仠姝� + /// </summary> + public void StopAndBlock() + { + JobManager.StopAndBlock(); + } + + #endregion } } -- Gitblit v1.9.3