#region << 版 本 注 释 >>
|
/*----------------------------------------------------------------
|
* 命名空间:WIDESEAWCS_QuartzJob
|
* 创建者:胡童庆
|
* 创建时间:2024/8/2 16:13:36
|
* 版本:V1.0.0
|
* 描述:调度服务实现类
|
*
|
* ----------------------------------------------------------------
|
* 修改人:
|
* 修改时间:
|
* 版本:V1.0.1
|
* 修改说明:
|
*
|
*----------------------------------------------------------------*/
|
#endregion << 版 本 注 释 >>
|
|
using Quartz.Impl.Triggers;
|
using Quartz.Impl;
|
using Quartz.Spi;
|
using Quartz;
|
using System;
|
using System.Collections.Generic;
|
using System.Collections.Specialized;
|
using System.Linq;
|
using System.Reflection;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEAWCS_Core;
|
using WIDESEAWCS_Core.Helper;
|
using WIDESEAWCS_QuartzJob.DTO;
|
using WIDESEAWCS_QuartzJob.CustomException;
|
|
namespace WIDESEAWCS_QuartzJob
|
{
|
public class SchedulerCenterServer : ISchedulerCenter
|
{
|
private Task<IScheduler> _scheduler;
|
private readonly IJobFactory _iocjobFactory;
|
public SchedulerCenterServer(IJobFactory jobFactory)
|
{
|
_iocjobFactory = jobFactory;
|
_scheduler = GetSchedulerAsync();
|
}
|
private Task<IScheduler> GetSchedulerAsync()
|
{
|
if (_scheduler != null)
|
return this._scheduler;
|
else
|
{
|
try
|
{
|
// 从Factory中获取Scheduler实例
|
NameValueCollection collection = new NameValueCollection
|
{
|
{ "quartz.serializer.type", "binary" },
|
};
|
StdSchedulerFactory factory = new StdSchedulerFactory(collection);
|
return _scheduler = factory.GetScheduler();
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.JobFactoryInstanceException, ex.Message), innerException: ex);
|
}
|
|
}
|
}
|
|
/// <summary>
|
/// 开启任务调度
|
/// </summary>
|
/// <returns></returns>
|
public async Task<WebResponseContent> StartScheduleAsync()
|
{
|
WebResponseContent result = new WebResponseContent();
|
try
|
{
|
this._scheduler.Result.JobFactory = this._iocjobFactory;
|
if (!this._scheduler.Result.IsStarted)
|
{
|
//等待任务运行完成
|
await this._scheduler.Result.Start();
|
await Console.Out.WriteLineAsync(QuartzJobInfoMessage.StartJobSuccess);
|
result = WebResponseContent.Instance.OK(QuartzJobInfoMessage.StartJobSuccess);
|
return result;
|
}
|
else
|
{
|
result = WebResponseContent.Instance.Error(QuartzJobInfoMessage.JobHasStart);
|
return result;
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StartJobException, ex.Message), innerException: ex);
|
}
|
}
|
|
/// <summary>
|
/// 停止任务调度
|
/// </summary>
|
/// <returns></returns>
|
public async Task<WebResponseContent> StopScheduleAsync()
|
{
|
WebResponseContent result = new WebResponseContent();
|
try
|
{
|
if (!this._scheduler.Result.IsShutdown)
|
{
|
//等待任务运行完成
|
await this._scheduler.Result.Shutdown();
|
await Console.Out.WriteLineAsync(QuartzJobInfoMessage.StopJobSuccess);
|
result = WebResponseContent.Instance.OK(QuartzJobInfoMessage.StopJobSuccess);
|
return result;
|
}
|
else
|
{
|
result = WebResponseContent.Instance.Error(QuartzJobInfoMessage.JobHasStop);
|
return result;
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StopJobException, ex.Message), innerException: ex);
|
}
|
}
|
|
/// <summary>
|
/// 添加一个计划任务(映射程序集指定IJob实现类)
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="tasksQz"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> AddScheduleJobAsync(DispatchInfoDTO tasksQz)
|
{
|
WebResponseContent result = new WebResponseContent();
|
|
if (tasksQz != null)
|
{
|
try
|
{
|
JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup);
|
if (await _scheduler.Result.CheckExists(jobKey))
|
{
|
result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobHasAdd, tasksQz.Name));
|
return result;
|
}
|
#region 设置开始时间和结束时间
|
|
if (tasksQz.BeginTime == null)
|
{
|
tasksQz.BeginTime = DateTime.Now;
|
}
|
DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(tasksQz.BeginTime, 1);//设置开始时间
|
if (tasksQz.EndTime == null)
|
{
|
tasksQz.EndTime = DateTime.MaxValue.AddDays(-1);
|
}
|
DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(tasksQz.EndTime, 1);//设置暂停时间
|
|
#endregion
|
|
#region 通过反射获取程序集类型和类
|
|
var basePath = AppContext.BaseDirectory;
|
var dllFile = Path.Combine(basePath, $"{tasksQz.AssemblyName}.dll");
|
|
if (!File.Exists(dllFile))
|
{
|
var msg = $"{tasksQz.AssemblyName}.dll未找到,请检查数据或文件";
|
//log.Error(msg);
|
throw new Exception(msg);
|
}
|
|
Assembly assembly = Assembly.Load(new AssemblyName(tasksQz.AssemblyName));
|
Type jobType = assembly.GetType(tasksQz.AssemblyName + "." + tasksQz.ClassName);
|
|
#endregion
|
|
//传入反射出来的执行程序集
|
//IJobDetail jobDetail = JobBuilder.Create(jobType)
|
// .WithIdentity(tasksQz.Id.ToString(), tasksQz.JobGroup)
|
// .Build();
|
//jobDetail.JobDataMap.Add("JobParams", tasksQz.JobParams);
|
|
IJobDetail job = new JobDetailImpl(tasksQz.Id.ToString(), tasksQz.JobGroup, jobType);
|
job.JobDataMap.Add("JobParams", tasksQz.JobParams);
|
|
ITrigger trigger = CreateSimpleTrigger(tasksQz);
|
|
// 告诉Quartz使用我们的触发器来安排作业
|
await _scheduler.Result.ScheduleJob(job, trigger);
|
//await _scheduler.Result.ScheduleJob(jobDetail, trigger);
|
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.JobAddSuccess, tasksQz.Name));
|
return result;
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.AddJobException, tasksQz.Name, ex.Message), innerException: ex);
|
}
|
}
|
else
|
{
|
result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobNotExist, tasksQz?.Name));
|
return result;
|
}
|
}
|
|
/// <summary>
|
/// 任务是否存在?
|
/// </summary>
|
/// <returns></returns>
|
public async Task<bool> IsExistScheduleJobAsync(DispatchInfoDTO sysSchedule)
|
{
|
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
|
if (await _scheduler.Result.CheckExists(jobKey))
|
{
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 停止一个指定的计划任务
|
/// </summary>
|
/// <returns></returns>
|
public async Task<WebResponseContent> StopScheduleJobAsync(DispatchInfoDTO sysSchedule)
|
{
|
WebResponseContent result = new WebResponseContent();
|
try
|
{
|
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
|
if (!await _scheduler.Result.CheckExists(jobKey))
|
{
|
result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.JobNotExist, sysSchedule.Name));
|
return result;
|
}
|
else
|
{
|
await this._scheduler.Result.DeleteJob(jobKey);
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.StopAJobSuccess, sysSchedule.Name));
|
return result;
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.StopAJobException, sysSchedule.Name, ex.Message), innerException: ex);
|
}
|
}
|
|
/// <summary>
|
/// 恢复指定的计划任务
|
/// </summary>
|
/// <param name="sysSchedule"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> ResumeJob(DispatchInfoDTO sysSchedule)
|
{
|
WebResponseContent result = new WebResponseContent();
|
try
|
{
|
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
|
if (!await _scheduler.Result.CheckExists(jobKey))
|
{
|
result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.ResumeJobNotExist, sysSchedule.Name));
|
return result;
|
}
|
await this._scheduler.Result.ResumeJob(jobKey);
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ResumeJobSuccess, sysSchedule.Name));
|
return result;
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.ResumeJobException, sysSchedule.Name, ex.Message), innerException: ex);
|
}
|
}
|
|
/// <summary>
|
/// 暂停指定的计划任务
|
/// </summary>
|
/// <param name="sysSchedule"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> PauseJob(DispatchInfoDTO sysSchedule)
|
{
|
WebResponseContent result = new WebResponseContent();
|
try
|
{
|
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
|
if (!await _scheduler.Result.CheckExists(jobKey))
|
{
|
result = WebResponseContent.Instance.Error(string.Format(QuartzJobInfoMessage.PauseJobNotExist, sysSchedule.Name));
|
return result;
|
}
|
await this._scheduler.Result.PauseJob(jobKey);
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.PauseJobSuccess, sysSchedule.Name));
|
return result;
|
}
|
catch (Exception)
|
{
|
throw;
|
}
|
}
|
|
#region 状态状态帮助方法
|
//public async Task<List<DispatchInfoDTO>> GetTaskStaus(DispatchInfoDTO sysSchedule)
|
//{
|
|
// var ls = new List<TaskInfoDto>();
|
// var noTask = new List<TaskInfoDto>{ new TaskInfoDto {
|
// jobId = sysSchedule.Id.ObjToString(),
|
// jobGroup = sysSchedule.JobGroup,
|
// triggerId = "",
|
// triggerGroup = "",
|
// triggerStatus = "不存在"
|
// } };
|
// JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
|
// IJobDetail job = await this._scheduler.Result.GetJobDetail(jobKey);
|
// if (job == null)
|
// {
|
// return noTask;
|
// }
|
// //info.Append(string.Format("任务ID:{0}\r\n任务名称:{1}\r\n", job.Key.Name, job.Description));
|
// var triggers = await this._scheduler.Result.GetTriggersOfJob(jobKey);
|
// if (triggers == null || triggers.Count == 0)
|
// {
|
// return noTask;
|
// }
|
// foreach (var trigger in triggers)
|
// {
|
// var triggerStaus = await this._scheduler.Result.GetTriggerState(trigger.Key);
|
// string state = GetTriggerState(triggerStaus.ObjToString());
|
// ls.Add(new TaskInfoDto
|
// {
|
// jobId = job.Key.Name,
|
// jobGroup = job.Key.Group,
|
// triggerId = trigger.Key.Name,
|
// triggerGroup = trigger.Key.Group,
|
// triggerStatus = state
|
// });
|
// //info.Append(string.Format("触发器ID:{0}\r\n触发器名称:{1}\r\n状态:{2}\r\n", item.Key.Name, item.Description, state));
|
|
// }
|
// return ls;
|
//}
|
public string GetTriggerState(string key)
|
{
|
string state = null;
|
if (key != null)
|
key = key.ToUpper();
|
switch (key)
|
{
|
case "1":
|
state = "暂停";
|
break;
|
case "2":
|
state = "完成";
|
break;
|
case "3":
|
state = "出错";
|
break;
|
case "4":
|
state = "阻塞";
|
break;
|
case "0":
|
state = "正常";
|
break;
|
case "-1":
|
state = "不存在";
|
break;
|
case "BLOCKED":
|
state = "阻塞";
|
break;
|
case "COMPLETE":
|
state = "完成";
|
break;
|
case "ERROR":
|
state = "出错";
|
break;
|
case "NONE":
|
state = "不存在";
|
break;
|
case "NORMAL":
|
state = "正常";
|
break;
|
case "PAUSED":
|
state = "暂停";
|
break;
|
}
|
return state;
|
}
|
#endregion
|
|
#region 创建触发器帮助方法
|
|
/// <summary>
|
/// 创建SimpleTrigger触发器(简单触发器)
|
/// </summary>
|
/// <param name="sysSchedule"></param>
|
/// <returns></returns>
|
private ITrigger CreateSimpleTrigger(DispatchInfoDTO sysSchedule)
|
{
|
ITrigger trigger = TriggerBuilder.Create()
|
.WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup)
|
.StartAt(sysSchedule.BeginTime.GetValueOrDefault())
|
.WithSimpleSchedule(x => x
|
.WithIntervalInSeconds(sysSchedule.IntervalSecond)
|
.RepeatForever()
|
)
|
.EndAt(sysSchedule.EndTime.GetValueOrDefault())
|
.Build();
|
return trigger;
|
}
|
#endregion
|
|
/// <summary>
|
/// 立即执行 一个任务 执行一次
|
/// </summary>
|
/// <param name="tasksQz"></param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> ExecuteJobAsync(DispatchInfoDTO tasksQz)
|
{
|
var result = new WebResponseContent();
|
try
|
{
|
JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup);
|
|
//判断任务是否存在,存在则 触发一次,不存在则先添加一个任务,触发以后再 停止任务
|
if (!await _scheduler.Result.CheckExists(jobKey))
|
{
|
//不存在 则 添加一个计划任务
|
await AddScheduleJobAsync(tasksQz);
|
|
//触发执行一次
|
await _scheduler.Result.TriggerJob(jobKey);
|
|
//停止任务
|
await StopScheduleJobAsync(tasksQz);
|
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ExecuteJobSuccess, tasksQz.Name));
|
}
|
else
|
{
|
await _scheduler.Result.TriggerJob(jobKey);
|
result = WebResponseContent.Instance.OK(string.Format(QuartzJobInfoMessage.ExecuteJobSuccess, tasksQz.Name));
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new QuartzJobException(string.Format(QuartzJobExceptionMessage.ResumeJobException, tasksQz.Name, ex.Message), innerException: ex);
|
}
|
|
return result;
|
}
|
}
|
}
|