添加项目文件。
This commit is contained in:
11
HT.Cloud.Service/AutoJob/IJobTask.cs
Normal file
11
HT.Cloud.Service/AutoJob/IJobTask.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
using HT.Cloud.Code;
|
||||
|
||||
namespace HT.Cloud.Service.AutoJob
|
||||
{
|
||||
public interface IJobTask
|
||||
{
|
||||
//执行方法
|
||||
Task<AlwaysResult> Start();
|
||||
}
|
||||
}
|
32
HT.Cloud.Service/AutoJob/IOCJobFactory.cs
Normal file
32
HT.Cloud.Service/AutoJob/IOCJobFactory.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Quartz;
|
||||
using Quartz.Spi;
|
||||
using System;
|
||||
|
||||
namespace HT.Cloud.Service.AutoJob
|
||||
{
|
||||
/// <summary>
|
||||
/// 依赖注入必须,代替原本的SimpleJobFactory
|
||||
/// </summary>
|
||||
public class IOCJobFactory : IJobFactory
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public IOCJobFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||
{
|
||||
var serviceScope = _serviceProvider.CreateScope(); // 获得一个ioc对象,指定创建scope级别的实例(在job里面需要依赖注入ef,但是startup里面配置的ef是scope级别的,必须指定为scope,不然报错)。不写的话,默认是单例。
|
||||
return serviceScope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob; // 依赖注入一个 job 然后返回
|
||||
}
|
||||
|
||||
public void ReturnJob(IJob job)
|
||||
{
|
||||
var disposable = job as IDisposable;
|
||||
disposable?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
46
HT.Cloud.Service/AutoJob/Job/SaveServerStateJob.cs
Normal file
46
HT.Cloud.Service/AutoJob/Job/SaveServerStateJob.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using HT.Cloud.Code;
|
||||
using HT.Cloud.Domain.SystemSecurity;
|
||||
using HT.Cloud.Service.SystemSecurity;
|
||||
|
||||
namespace HT.Cloud.Service.AutoJob
|
||||
{
|
||||
[ServiceDescription("服务器监控")]
|
||||
public class SaveServerStateJob : IJobTask
|
||||
{
|
||||
private IWebHostEnvironment _hostingEnvironment;
|
||||
private ServerStateService _server;
|
||||
|
||||
public SaveServerStateJob(ISqlSugarClient context)
|
||||
{
|
||||
_hostingEnvironment = GlobalContext.HostingEnvironment;
|
||||
_server = new ServerStateService(context);
|
||||
}
|
||||
|
||||
public async Task<AlwaysResult> Start()
|
||||
{
|
||||
AlwaysResult obj = new AlwaysResult();
|
||||
try
|
||||
{
|
||||
ServerStateEntity entity = new ServerStateEntity();
|
||||
var computer = ComputerHelper.GetComputerInfo();
|
||||
entity.F_ARM = computer.RAMRate;
|
||||
entity.F_CPU = computer.CPURate;
|
||||
entity.F_IIS = "0";
|
||||
entity.F_WebSite = _hostingEnvironment.ContentRootPath;
|
||||
await _server.SubmitForm(entity);
|
||||
obj.state = ResultType.success.ToString();
|
||||
obj.message = "服务器状态更新成功!";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
obj.state = ResultType.error.ToString();
|
||||
obj.message = "服务器状态更新失败!" + ex.Message;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
146
HT.Cloud.Service/AutoJob/JobCenter.cs
Normal file
146
HT.Cloud.Service/AutoJob/JobCenter.cs
Normal file
@ -0,0 +1,146 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
using Quartz.Spi;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using HT.Cloud.Code;
|
||||
using HT.Cloud.Domain.SystemSecurity;
|
||||
using HT.Cloud.Service.SystemSecurity;
|
||||
|
||||
namespace HT.Cloud.Service.AutoJob
|
||||
{
|
||||
/// <summary>
|
||||
/// quartz 主机服务
|
||||
/// </summary>
|
||||
[DisallowConcurrentExecution]
|
||||
public class JobCenter : IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// 定时作业计划生成工厂,这一项在startup有配置集群模式
|
||||
/// </summary>
|
||||
private readonly ISchedulerFactory _schedulerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// 定时作业工厂
|
||||
/// </summary>
|
||||
private readonly IJobFactory _jobFactory;
|
||||
|
||||
private OpenJobsService _service;
|
||||
private IScheduler _scheduler;
|
||||
|
||||
/// <summary>
|
||||
/// 构造注入
|
||||
/// </summary>
|
||||
public JobCenter(OpenJobsService service, ISchedulerFactory schedulerFactory, IJobFactory jobFactory)
|
||||
{
|
||||
_service = service;
|
||||
_jobFactory = jobFactory;
|
||||
_schedulerFactory = schedulerFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量启动定时任务
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
|
||||
_scheduler.JobFactory = _jobFactory;
|
||||
if (GlobalContext.SystemConfig.IsCluster == false || GlobalContext.SystemConfig.NeedClear == true)
|
||||
{
|
||||
await _scheduler.Clear();
|
||||
}
|
||||
List<OpenJobEntity> obj = await _service.GetAllList(null);
|
||||
obj = obj.Where(a => a.F_EnabledMark == true).ToList();
|
||||
if (obj.Count > 0)
|
||||
{
|
||||
await AddScheduleJob(obj, cancellationToken);
|
||||
}
|
||||
await _scheduler.Start();
|
||||
//if (!GlobalContext.SystemConfig.Debug)
|
||||
//{
|
||||
// List<OpenJobEntity> obj = await new OpenJobService().GetList(null);
|
||||
// if (obj.Count>0)
|
||||
// {
|
||||
// AddScheduleJob(obj);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await ClearScheduleJob();
|
||||
}
|
||||
|
||||
#region 添加任务计划
|
||||
|
||||
/// <summary>
|
||||
/// 添加任务计划
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task AddScheduleJob(List<OpenJobEntity> entityList, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (OpenJobEntity entity in entityList)
|
||||
{
|
||||
entity.F_StarRunTime = DateTime.Now;
|
||||
entity.F_EndRunTime = DateTime.Now.AddSeconds(-1);
|
||||
DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(entity.F_StarRunTime, 1);
|
||||
DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(DateTime.MaxValue.AddDays(-1), 1);
|
||||
await _service.SubmitForm(entity, entity.F_Id);
|
||||
|
||||
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
|
||||
.StartAt(starRunTime)
|
||||
.EndAt(endRunTime)
|
||||
.WithIdentity(entity.F_JobName, entity.F_JobGroup)
|
||||
.WithCronSchedule(entity.F_CronExpress)
|
||||
.Build();
|
||||
((CronTriggerImpl)trigger).MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;
|
||||
// 判断数据库中有没有记录过,有的话,quartz会自动从数据库中提取信息创建 schedule
|
||||
if (!await _scheduler.CheckExists(new JobKey(entity.F_JobName, entity.F_JobGroup)))
|
||||
{
|
||||
IJobDetail job = JobBuilder.Create<JobExecute>().WithIdentity(entity.F_JobName, entity.F_JobGroup).Build();
|
||||
job.JobDataMap.Add("F_Id", entity.F_Id);
|
||||
await _scheduler.ScheduleJob(job, trigger, cancellationToken);
|
||||
//存在相同名字的Job或Trigger,更新调度任务
|
||||
//IList<ICronTrigger> triggers = new List<ICronTrigger> { trigger };
|
||||
//await _scheduler.ScheduleJob(job, new ReadOnlyCollection<ICronTrigger>(triggers), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteWithTime(ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 添加任务计划
|
||||
|
||||
#region 清除任务计划
|
||||
|
||||
/// <summary>
|
||||
/// 清除任务计划
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task ClearScheduleJob()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _scheduler.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteWithTime(ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 清除任务计划
|
||||
}
|
||||
}
|
211
HT.Cloud.Service/AutoJob/JobExecute.cs
Normal file
211
HT.Cloud.Service/AutoJob/JobExecute.cs
Normal file
@ -0,0 +1,211 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Quartz;
|
||||
using Quartz.Impl.Triggers;
|
||||
using Quartz.Spi;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using HT.Cloud.Code;
|
||||
using HT.Cloud.DataBase;
|
||||
using HT.Cloud.Domain.SystemSecurity;
|
||||
using HT.Cloud.Service.SystemSecurity;
|
||||
|
||||
namespace HT.Cloud.Service.AutoJob
|
||||
{
|
||||
public class JobExecute : IJob
|
||||
{
|
||||
private IScheduler _scheduler;
|
||||
private ISchedulerFactory _schedulerFactory;
|
||||
private IJobFactory _iocJobfactory;
|
||||
private readonly IHttpClientFactory _httpClient;
|
||||
|
||||
public JobExecute(ISchedulerFactory schedulerFactory, IJobFactory iocJobfactory, IHttpClientFactory httpClient)
|
||||
{
|
||||
_scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();
|
||||
_scheduler.JobFactory = iocJobfactory;
|
||||
_schedulerFactory = schedulerFactory;
|
||||
_iocJobfactory = iocJobfactory;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public Task Execute(IJobExecutionContext context)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
string jobId = "";
|
||||
JobDataMap jobData = null;
|
||||
OpenJobEntity dbJobEntity = null;
|
||||
DateTime now = DateTime.Now;
|
||||
var dbContext = GlobalContext.RootServices.GetRequiredService<ISqlSugarClient>();
|
||||
try
|
||||
{
|
||||
jobData = context.JobDetail.JobDataMap;
|
||||
jobId = jobData.GetString("F_Id");
|
||||
// 获取数据库中的任务
|
||||
dbJobEntity = await dbContext.Queryable<OpenJobEntity>().Where(a=>a.F_Id== jobId).FirstAsync();
|
||||
if (dbJobEntity != null)
|
||||
{
|
||||
if (dbJobEntity.F_EnabledMark == true)
|
||||
{
|
||||
CronTriggerImpl trigger = context.Trigger as CronTriggerImpl;
|
||||
if (trigger != null)
|
||||
{
|
||||
if (trigger.CronExpressionString != dbJobEntity.F_CronExpress)
|
||||
{
|
||||
// 更新任务周期
|
||||
trigger.CronExpressionString = dbJobEntity.F_CronExpress;
|
||||
await _scheduler.RescheduleJob(trigger.Key, trigger);
|
||||
return;
|
||||
}
|
||||
|
||||
#region 执行任务
|
||||
|
||||
OpenJobLogEntity log = new OpenJobLogEntity();
|
||||
log.F_Id = Utils.GuId();
|
||||
log.F_JobId = jobId;
|
||||
log.F_JobName = dbJobEntity.F_JobName;
|
||||
log.F_CreatorTime = now;
|
||||
AlwaysResult result = new AlwaysResult();
|
||||
if (dbJobEntity.F_JobType == 0)
|
||||
{
|
||||
//反射执行就行
|
||||
var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
|
||||
//反射取指定前后缀的dll
|
||||
var referencedAssemblies = Directory.GetFiles(path, "HT.Cloud.*.dll").Select(Assembly.LoadFrom).ToArray();
|
||||
var types = referencedAssemblies
|
||||
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces()
|
||||
.Contains(typeof(IJobTask)))).ToArray();
|
||||
string filename = dbJobEntity.F_FileName;
|
||||
var implementType = types.Where(x => x.IsClass && x.FullName == filename).FirstOrDefault();
|
||||
var obj = System.Activator.CreateInstance(implementType, dbContext); // 创建实例(带参数)
|
||||
MethodInfo method = implementType.GetMethod("Start", new Type[] { }); // 获取方法信息
|
||||
object[] parameters = null;
|
||||
result = ((Task<AlwaysResult>)method.Invoke(obj, parameters)).GetAwaiter().GetResult(); // 调用方法,参数为空
|
||||
if (result.state.ToString() == ResultType.success.ToString())
|
||||
{
|
||||
log.F_EnabledMark = true;
|
||||
log.F_Description = "执行成功," + result.message.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.F_EnabledMark = false;
|
||||
log.F_Description = "执行失败," + result.message.ToString();
|
||||
}
|
||||
}
|
||||
else if (dbJobEntity.F_JobType == 5)
|
||||
{
|
||||
var dbContextTemp = dbContext.AsTenant().GetConnectionScope(dbJobEntity.F_JobDBProvider);
|
||||
try
|
||||
{
|
||||
dbContextTemp.Ado.BeginTran();
|
||||
if (!string.IsNullOrEmpty(dbJobEntity.F_JobSqlParm))
|
||||
{
|
||||
var dic = dbJobEntity.F_JobSqlParm.ToObject<Dictionary<string, object>>();
|
||||
List<SugarParameter> list = new List<SugarParameter>();
|
||||
foreach (var item in dic)
|
||||
{
|
||||
list.Add(new SugarParameter(item.Key, item.Value));
|
||||
}
|
||||
var dbResult = await dbContextTemp.Ado.SqlQueryAsync<dynamic>(dbJobEntity.F_JobSql, list);
|
||||
log.F_EnabledMark = true;
|
||||
log.F_Description = "执行成功," + dbResult.ToJson();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbResult = await dbContextTemp.Ado.SqlQueryAsync<dynamic>(dbJobEntity.F_JobSql);
|
||||
log.F_EnabledMark = true;
|
||||
log.F_Description = "执行成功," + dbResult.ToJson();
|
||||
}
|
||||
dbContextTemp.Ado.CommitTran();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.F_EnabledMark = false;
|
||||
log.F_Description = "执行失败," + ex.Message;
|
||||
dbContextTemp.Ado.RollbackTran();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpMethod method = HttpMethod.Get;
|
||||
switch (dbJobEntity.F_JobType)
|
||||
{
|
||||
case 1:
|
||||
method = HttpMethod.Get;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
method = HttpMethod.Post;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
method = HttpMethod.Put;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
method = HttpMethod.Delete;
|
||||
break;
|
||||
}
|
||||
var dic = dbJobEntity.F_RequestHeaders.ToObject<Dictionary<string, string>>();
|
||||
if (dic == null)
|
||||
{
|
||||
dic = new Dictionary<string, string>();
|
||||
}
|
||||
//请求头添加租户号
|
||||
dic.Add("dbNumber", dbJobEntity.F_DbNumber);
|
||||
try
|
||||
{
|
||||
var temp = await new HttpWebClient(_httpClient).ExecuteAsync(dbJobEntity.F_RequestUrl, method, dbJobEntity.F_RequestString, dic);
|
||||
log.F_EnabledMark = true;
|
||||
log.F_Description = $"执行成功。{temp}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.F_EnabledMark = false;
|
||||
log.F_Description = "执行失败," + ex.Message.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion 执行任务
|
||||
|
||||
dbContext.Ado.BeginTran();
|
||||
if (log.F_EnabledMark == true)
|
||||
{
|
||||
await dbContext.Updateable<OpenJobEntity>(a => new OpenJobEntity
|
||||
{
|
||||
F_LastRunMark = true,
|
||||
F_LastRunTime = now,
|
||||
}).Where(a => a.F_Id == jobId).ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await dbContext.Updateable<OpenJobEntity>(a => new OpenJobEntity
|
||||
{
|
||||
F_LastRunMark = false,
|
||||
F_LastRunTime = now,
|
||||
F_LastRunErrTime = now,
|
||||
F_LastRunErrMsg = log.F_Description
|
||||
}).Where(a => a.F_Id == jobId).ExecuteCommandAsync();
|
||||
}
|
||||
if (dbJobEntity.F_IsLog == "是")
|
||||
{
|
||||
dbContext.Insertable(log).ExecuteCommand();
|
||||
}
|
||||
dbContext.Ado.CommitTran();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteWithTime(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user