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
{
///
///
///
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(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 listTrig = new List();
foreach (var schedule in JobManager.RunningSchedules)
{
var job = Biz.Db.Queryable().Where(q => q.JobName == schedule.Name).First();
if (job != null)
{
TSK_TRIG trig = new TSK_TRIG();
trig = Biz.Db.Queryable().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, $"作业保存到数据库异常");
}
}
///
/// 添加工作任务
///
///
///
///
///
public ApiAction AddJob(TJob newEntity, FluentJobParam jobParam) where TJob : class, ITJob
{
ApiAction apiAction = new();
try
{
JobManager.AddJob((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().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;
}
///
/// 删除作业
///
///
public void RemovefJob(string jobname)
{
JobManager.RemoveJob(jobname);
}
///
/// 从数据库批量添加任务
///
public Registry AddJobsFromDB()
{
// 声明一个Registry类
var registry = new Registry();
try
{
var jobs = Biz.Db.Queryable().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(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;
}
///
/// 根据实体名注册计划
///
///
///
///
///
///
private Schedule Schedule(TJob entity, string JobName, Registry registry) where TJob : class, ITJob
{
return registry.Schedule().WithName(typeof(TJob).Name);
}
///
/// 生成计划
///
///
///
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;
}
}
///
/// 停止服务
///
public void Stop()
{
JobManager.Stop();
}
///
/// 在任务完成后等待或者停止
///
public void StopAndBlock()
{
JobManager.StopAndBlock();
}
#endregion
}
}