using FluentScheduler;
|
using Newtonsoft.Json;
|
using Rhea.Common;
|
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 Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser;
|
using static Tiger.Model.TrigArgs;
|
|
namespace Tiger.Business
|
{
|
/// <summary>
|
///
|
/// </summary>
|
public class InterfaceServiceNew : IInterfaceService
|
{
|
#region Sundial计划调度 旧版本使用
|
|
public Sundial.ISchedulerFactory _schedulerFactory { get; set; }
|
/// <summary>
|
/// 设置计划任务工厂类
|
/// </summary>
|
/// <param name="schedulerFactory"></param>
|
public void SetSchedulerFactory(Sundial.ISchedulerFactory schedulerFactory)
|
{
|
_schedulerFactory = schedulerFactory;
|
}
|
|
/// <summary>
|
/// 根据实体类名及作业名称添加作业
|
/// </summary>
|
/// <typeparam name="TJob"></typeparam>
|
/// <param name="newEntity"></param>
|
/// <param name="jobParam"></param>
|
public ApiAction AddJob<TJob>(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<TJob>(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<TSK_TRIG> { JsonConvert.DeserializeObject<TSK_TRIG>(JsonConvert.SerializeObject(trigger)) };
|
entity.Triggers[0].Args = jobParam.Period.ToString();
|
apiAction = SaveJob(entity);
|
apiAction.Data = entity;
|
return apiAction;
|
}
|
|
/// <summary>
|
/// 根据作业名称添加作业
|
/// </summary>
|
/// <typeparam name="TJob"></typeparam>
|
/// <param name="jobname"></param>
|
/// <param name="triggerBuilders"></param>
|
public ApiAction AddJob<TJob>(string jobname, params Sundial.TriggerBuilder[] triggerBuilders) where TJob : class, Sundial.IJob
|
{
|
ApiAction apiAction = new();
|
triggerBuilders[0].LoadFrom(new
|
{
|
TriggerId = jobname + "_trigger1",
|
});
|
_schedulerFactory.AddJob<TJob>(jobname, triggerBuilders);
|
var trigger = GetJob(jobname).GetTrigger($"{jobname}_trigger1");
|
TSK_JOB entity = ReturnDetail(jobname);
|
entity.TriggersWithGhost = new List<TSK_TRIG> { JsonConvert.DeserializeObject<TSK_TRIG>(JsonConvert.SerializeObject(trigger)) };
|
apiAction = SaveJob(entity);
|
apiAction.Data = entity;
|
return apiAction;
|
}
|
|
/// <summary>
|
/// 更新作业
|
/// </summary>
|
/// <param name="job"></param>
|
/// <returns></returns>
|
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<TSK_TRIG>().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<TSK_JOB>(JsonConvert.SerializeObject(jobDetail));
|
}
|
|
/// <summary>
|
/// 启动所有作业
|
/// </summary>
|
public void StartAllJob()
|
{
|
_schedulerFactory.StartAll();
|
}
|
|
/// <summary>
|
/// 启动单个作业
|
/// </summary>
|
/// <param name="jobname"></param>
|
public void StartJob(string jobname)
|
{
|
// 带返回值
|
Sundial.IScheduler scheduler;
|
var scheduleResult = _schedulerFactory.TryRunJob(jobname, out scheduler);
|
}
|
|
/// <summary>
|
/// 获取单个作业
|
/// </summary>
|
/// <param name="jobname"></param>
|
/// <returns></returns>
|
public Sundial.IScheduler GetJob(string jobname)
|
{
|
Sundial.IScheduler scheduler;
|
var scheduleResult = _schedulerFactory.TryGetJob(jobname, out scheduler);
|
return scheduler;
|
}
|
|
/// <summary>
|
/// 获取所有作业
|
/// </summary>
|
/// <returns></returns>
|
public List<Sundial.IScheduler> GetJobs()
|
{
|
return _schedulerFactory.GetJobs().ToList();
|
}
|
|
/// <summary>
|
/// 暂停作业
|
/// </summary>
|
/// <param name="jobname"></param>
|
public void PauseJob(string jobname)
|
{
|
var scheduler = GetJob(jobname);
|
if (scheduler != null)
|
{
|
scheduler.Pause();
|
}
|
}
|
/// <summary>
|
/// 删除作业
|
/// </summary>
|
/// <param name="jobname"></param>
|
public void RemoveJob(string jobname)
|
{
|
var scheduler = GetJob(jobname);
|
if (scheduler != null)
|
{
|
scheduler.Remove();
|
}
|
}
|
|
/// <summary>
|
/// 从数据库加载作业
|
/// </summary>
|
public void AddJobFromDB()
|
{
|
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, 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");
|
}
|
}
|
|
/// <summary>
|
/// 作业保存到数据库
|
/// </summary>
|
/// <param name="entity"></param>
|
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<TSK_JOB>().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
|
/// <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 AddJob<TJob>(TJob newEntity, FluentJobParam jobParam) where TJob : class, ITJob
|
{
|
ApiAction apiAction = new();
|
try
|
{
|
JobManager.AddJob<TJob>((s) => GenerateSchedule(jobParam.Args, s.WithName(typeof(TJob).Name)));
|
string guid = Guid.NewGuid().ToString("N");
|
var trigger = new TSK_TRIG()
|
{
|
JobId = guid,
|
Args = JsonConvert.SerializeObject(jobParam.Args),
|
Status = TSK_TRIG.Statuss.Running.GetValue(),
|
StartTime = DateTime.Now,
|
NumberOfRuns = 1,
|
};
|
TSK_JOB job = new()
|
{
|
ID = guid,
|
Remark = jobParam.Remark,
|
JobType = typeof(TJob).Name,
|
AssemblyName = jobParam.AssemblyName,
|
JobName = jobParam.JobName,
|
};
|
if (Biz.Db.Queryable<TSK_JOB>().Any(q=>q.JobName == typeof(TJob).Name)) {
|
apiAction.IsSuccessed = false;
|
apiAction.LocaleMsg = new($"任务已经存在");
|
return apiAction;
|
}
|
var db = Biz.Db;
|
//保存到数据库
|
var dbTran = db.UseTran(() =>
|
{
|
if (job != null)
|
{
|
db.Insertable(job, "system").ExecuteCommand();
|
}
|
if (trigger != null)
|
{
|
db.Insertable(trigger, "system").ExecuteCommand();
|
}
|
});
|
if (!dbTran.IsSuccess)
|
{
|
Logger.Scheduler.Trace(dbTran.ErrorException, $"添加工作任务时保存到数据库异常");
|
}
|
//apiAction.Data = entity;
|
|
}
|
catch (System.Exception ex)
|
{
|
Logger.Console.Fatal(ex, "Add Job From DB Exception");
|
}
|
return apiAction;
|
}
|
|
/// <summary>
|
/// 删除作业
|
/// </summary>
|
/// <param name="jobname"></param>
|
public void RemovefJob(string jobname)
|
{
|
JobManager.RemoveJob(jobname);
|
}
|
|
/// <summary>
|
/// 从数据库批量添加任务
|
/// </summary>
|
public Registry AddJobsFromDB()
|
{
|
// 声明一个Registry类
|
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、ToRunOnceAt后面
|
//按时间类型来运行
|
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); //表示按每小时的分钟,多少分要看前面Every的数,比如: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
|
}
|
}
|