This commit is contained in:
cjd
2025-11-04 21:09:16 +08:00
parent 8260e293c7
commit bb90a020dc
592 changed files with 61749 additions and 27 deletions

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Quartz" Version="3.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DouyinApi.Common\DouyinApi.Common.csproj" />
<ProjectReference Include="..\DouyinApi.IServices\DouyinApi.IServices.csproj" />
<ProjectReference Include="..\DouyinApi.Repository\DouyinApi.Repository.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,60 @@
using DouyinApi.Common;
using DouyinApi.IServices;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Tasks
{
public class Job1TimedService : IHostedService, IDisposable
{
private Timer _timer;
private readonly IBlogArticleServices _blogArticleServices;
// 这里可以注入
public Job1TimedService(IBlogArticleServices blogArticleServices)
{
_blogArticleServices = blogArticleServices;
}
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 1 is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(60 * 60));//一个小时
return Task.CompletedTask;
}
private void DoWork(object state)
{
try
{
var model = _blogArticleServices.GetBlogDetails(1).Result;
Console.WriteLine($"Job 1 启动成功获取id=1的博客title为:{model?.btitle}");
}
catch (Exception ex)
{
Console.WriteLine($"Error:{ex.Message}");
}
ConsoleHelper.WriteSuccessLine($"Job 1 {DateTime.Now}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 1 is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}

View File

@@ -0,0 +1,47 @@
using DouyinApi.Common;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Tasks
{
public class Job2TimedService : IHostedService, IDisposable
{
private Timer _timer;
// 这里可以注入
public Job2TimedService()
{
}
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 2 is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(60 * 60 * 2));//两个小时
return Task.CompletedTask;
}
private void DoWork(object state)
{
ConsoleHelper.WriteWarningLine($"Job 2 {DateTime.Now}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 2 is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}

View File

@@ -0,0 +1,78 @@
using DouyinApi.Model;
using DouyinApi.Model.Models;
using DouyinApi.Model.ViewModels;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DouyinApi.Tasks
{
/// <summary>
/// 服务调度接口
/// </summary>
public interface ISchedulerCenter
{
/// <summary>
/// 开启任务调度
/// </summary>
/// <returns></returns>
Task<MessageModel<string>> StartScheduleAsync();
/// <summary>
/// 停止任务调度
/// </summary>
/// <returns></returns>
Task<MessageModel<string>> StopScheduleAsync();
/// <summary>
///
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<MessageModel<string>> AddScheduleJobAsync(TasksQz sysSchedule);
/// <summary>
/// 停止一个任务
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<MessageModel<string>> StopScheduleJobAsync(TasksQz sysSchedule);
/// <summary>
/// 检测任务是否存在
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<bool> IsExistScheduleJobAsync(TasksQz sysSchedule);
/// <summary>
/// 暂停指定的计划任务
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<MessageModel<string>> PauseJob(TasksQz sysSchedule);
/// <summary>
/// 恢复一个任务
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<MessageModel<string>> ResumeJob(TasksQz sysSchedule);
/// <summary>
/// 获取任务触发器状态
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
Task<List<TaskInfoDto>> GetTaskStaus(TasksQz sysSchedule);
/// <summary>
/// 获取触发器标识
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
string GetTriggerState(string key);
/// <summary>
/// 立即执行 一个任务
/// </summary>
/// <param name="tasksQz"></param>
/// <returns></returns>
Task<MessageModel<string>> ExecuteJobAsync(TasksQz tasksQz);
}
}

View File

@@ -0,0 +1,50 @@
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
using System;
namespace DouyinApi.Tasks
{
public class JobFactory : IJobFactory
{
/// <summary>
/// 注入反射获取依赖对象
/// </summary>
private readonly IServiceProvider _serviceProvider;
public JobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <summary>
/// 实现接口Job
/// </summary>
/// <param name="bundle"></param>
/// <param name="scheduler"></param>
/// <returns></returns>
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
var serviceScope = _serviceProvider.CreateScope();
var job = serviceScope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob;
return job;
}
catch (Exception)
{
throw;
}
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
}

View File

@@ -0,0 +1,85 @@
using DouyinApi.Common.Helper;
using DouyinApi.IServices;
using DouyinApi.Model.Models;
using Quartz;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace DouyinApi.Tasks
{
public class JobBase
{
public ITasksQzServices _tasksQzServices;
public ITasksLogServices _tasksLogServices;
public JobBase(ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
{
_tasksQzServices = tasksQzServices;
_tasksLogServices = tasksLogServices;
}
/// <summary>
/// 执行指定任务
/// </summary>
/// <param name="context"></param>
/// <param name="action"></param>
public async Task<string> ExecuteJob(IJobExecutionContext context, Func<Task> func)
{
//记录Job
TasksLog tasksLog = new TasksLog();
//JOBID
int jobid = context.JobDetail.Key.Name.ObjToInt();
//JOB组名
string groupName = context.JobDetail.Key.Group;
//日志
tasksLog.JobId = jobid;
tasksLog.RunTime = DateTime.Now;
string jobHistory = $"【{tasksLog.RunTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行开始】【Id{jobid},组别:{groupName}】";
try
{
await func();//执行任务
tasksLog.EndTime = DateTime.Now;
tasksLog.RunResult = true;
jobHistory += $",【{tasksLog.EndTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行成功】";
JobDataMap jobPars = context.JobDetail.JobDataMap;
tasksLog.RunPars = jobPars.GetString("JobParam");
}
catch (Exception ex)
{
tasksLog.EndTime = DateTime.Now;
tasksLog.RunResult = false;
//JobExecutionException e2 = new JobExecutionException(ex);
//true 是立即重新执行任务
//e2.RefireImmediately = true;
tasksLog.ErrMessage = ex.Message;
tasksLog.ErrStackTrace = ex.StackTrace;
jobHistory += $",【{tasksLog.EndTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行失败:{ex.Message}】";
}
finally
{
tasksLog.TotalTime = Math.Round((tasksLog.EndTime - tasksLog.RunTime).TotalSeconds,3);
jobHistory += $"(耗时:{tasksLog.TotalTime}秒)";
if (_tasksQzServices != null)
{
var model = await _tasksQzServices.QueryById(jobid);
if (model != null)
{
if(_tasksLogServices != null) await _tasksLogServices.Add(tasksLog);
model.RunTimes += 1;
if (model.TriggerType == 0) model.CycleHasRunTimes += 1;
if (model.TriggerType == 0 && model.CycleRunTimes != 0 && model.CycleHasRunTimes >= model.CycleRunTimes) model.IsStart = false;//循环完善,当循环任务完成后,停止该任务,防止下次启动再次执行
var separator = "<br>";
// 这里注意数据库字段的长度问题超过限制会造成数据库remark不更新问题。
model.Remark =
$"{jobHistory}{separator}" + string.Join(separator, StringHelper.GetTopDataBySeparator(model.Remark, separator, 9));
await _tasksQzServices.Update(model);
}
}
}
//Console.Out.WriteLine(jobHistory);
return jobHistory;
}
}
}

View File

@@ -0,0 +1,147 @@
using DouyinApi.Common.LogHelper;
using DouyinApi.IServices;
using DouyinApi.Model.Models;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到
/// </summary>
namespace DouyinApi.Tasks
{
public class Job_AccessTrendLog_Quartz : JobBase, IJob
{
private readonly IAccessTrendLogServices _accessTrendLogServices;
private readonly IWebHostEnvironment _environment;
public Job_AccessTrendLog_Quartz(IAccessTrendLogServices accessTrendLogServices, IWebHostEnvironment environment, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
: base(tasksQzServices, tasksLogServices)
{
_accessTrendLogServices = accessTrendLogServices;
_environment = environment;
_tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
var executeLog = await ExecuteJob(context, async () => await Run(context));
}
public async Task Run(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
var lastestLogDatetime = (await _accessTrendLogServices.Query(null, d => d.UpdateTime, false)).FirstOrDefault()?.UpdateTime;
if (lastestLogDatetime == null)
{
lastestLogDatetime = Convert.ToDateTime("2021-09-01");
}
var accLogs = GetAccessLogs().Where(d => d.User != "" && d.BeginTime.ObjToDate() >= lastestLogDatetime).ToList();
var logUpdate = DateTime.Now;
var activeUsers = (from n in accLogs
group n by new { n.User } into g
select new ActiveUserVM
{
user = g.Key.User,
count = g.Count(),
}).ToList();
foreach (var item in activeUsers)
{
var user = (await _accessTrendLogServices.Query(d => d.UserInfo != "" && d.UserInfo == item.user)).FirstOrDefault();
if (user != null)
{
user.Count += item.count;
user.UpdateTime = logUpdate;
await _accessTrendLogServices.Update(user);
}
else
{
await _accessTrendLogServices.Add(new AccessTrendLog()
{
Count = item.count,
UpdateTime = logUpdate,
UserInfo = item.user
});
}
}
// 重新拉取
var actUsers = await _accessTrendLogServices.Query(d => d.UserInfo != "", d => d.Count, false);
actUsers = actUsers.Take(15).ToList();
List<ActiveUserVM> activeUserVMs = new();
foreach (var item in actUsers)
{
activeUserVMs.Add(new ActiveUserVM()
{
user = item.UserInfo,
count = item.Count
});
}
Parallel.For(0, 1, e =>
{
LogLock.OutLogAOP("ACCESSTRENDLOG", "", new string[] { activeUserVMs.GetType().ToString(), JsonConvert.SerializeObject(activeUserVMs) }, false);
});
}
private List<UserAccessFromFIles> GetAccessLogs()
{
List<UserAccessFromFIles> userAccessModels = new();
var accessLogs = LogLock.ReadLog(
Path.Combine(_environment.ContentRootPath, "Log"), "RecordAccessLogs_", Encoding.UTF8, ReadType.Prefix, 2
).ObjToString().TrimEnd(',');
try
{
return JsonConvert.DeserializeObject<List<UserAccessFromFIles>>("[" + accessLogs + "]");
}
catch (Exception)
{
var accLogArr = accessLogs.Split("\n");
foreach (var item in accLogArr)
{
if (item.ObjToString() != "")
{
try
{
var accItem = JsonConvert.DeserializeObject<UserAccessFromFIles>(item.TrimEnd(','));
userAccessModels.Add(accItem);
}
catch (Exception)
{
}
}
}
}
return userAccessModels;
}
}
public class UserAccessFromFIles
{
public string User { get; set; }
public string IP { get; set; }
public string API { get; set; }
public string BeginTime { get; set; }
public string OPTime { get; set; }
public string RequestMethod { get; set; } = "";
public string Agent { get; set; }
}
}

View File

@@ -0,0 +1,101 @@
using DouyinApi.IServices;
using Quartz;
using System;
using System.Threading.Tasks;
using DouyinApi.Common.Utility;
using DouyinApi.Model.Models;
using DouyinApi.Repository.UnitOfWorks;
using SqlSugar;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到
/// </summary>
namespace DouyinApi.Tasks
{
[DisallowConcurrentExecution]
public class Job_Blogs_Quartz : JobBase, IJob
{
private readonly IBlogArticleServices _blogArticleServices;
private readonly IGuestbookServices _guestbookServices;
private readonly IUnitOfWorkManage _uowm;
private readonly ISqlSugarClient _db;
private SqlSugarScope db => _db as SqlSugarScope;
public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices,
IGuestbookServices guestbookServices, IUnitOfWorkManage uowm, ISqlSugarClient db)
: base(tasksQzServices, tasksLogServices)
{
_blogArticleServices = blogArticleServices;
_guestbookServices = guestbookServices;
_uowm = uowm;
this._db = db;
}
/// <summary>
/// 直接写就没有锁库 上下文ContextID一样
/// </summary>
/// <param name="context"></param>
public async Task Execute2(IJobExecutionContext context)
{
try
{
db.BeginTran();
Console.WriteLine(_uowm.GetDbClient().ContextID);
await db.Insertable(new Guestbook()
{
username = "bbb",
blogId = 1,
createdate = DateTime.Now,
isshow = true
}).ExecuteReturnSnowflakeIdAsync();
await db.Insertable(new PasswordLib()
{
PLID = IdGeneratorUtility.NextId(),
IsDeleted = false,
plAccountName = "aaa",
plCreateTime = DateTime.Now
}).ExecuteReturnSnowflakeIdAsync();
db.BeginTran();
Console.WriteLine(db.ContextID);
await db.Insertable(new PasswordLib()
{
PLID = IdGeneratorUtility.NextId(),
IsDeleted = false,
plAccountName = "aaa",
plCreateTime = DateTime.Now
}).ExecuteReturnSnowflakeIdAsync();
db.CommitTran();
Console.WriteLine(db.ContextID);
db.CommitTran();
Console.WriteLine("完成");
}
catch (Exception e)
{
db.RollbackTran();
}
}
/// <summary>
/// 但是调用其他类方法 上下文ContextID就不一样
/// </summary>
/// <param name="context"></param>
public async Task Execute(IJobExecutionContext context)
{
var executeLog = await ExecuteJob(context, async () => await Run(context));
}
public async Task Run(IJobExecutionContext context)
{
System.Console.WriteLine($"Job_Blogs_Quartz 执行 {DateTime.Now.ToShortTimeString()}");
var list = await _blogArticleServices.Query();
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
//int jobId = data.GetInt("JobParam");
await _guestbookServices.TestTranPropagationTran2();
}
}
}

View File

@@ -0,0 +1,83 @@
using DouyinApi.Common.LogHelper;
using DouyinApi.IServices;
using DouyinApi.Model.Models;
using Microsoft.AspNetCore.Hosting;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到
/// </summary>
namespace DouyinApi.Tasks
{
public class Job_OperateLog_Quartz : JobBase, IJob
{
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, IWebHostEnvironment environment, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
: base(tasksQzServices, tasksLogServices)
{
_operateLogServices = operateLogServices;
_environment = environment;
}
public async Task Execute(IJobExecutionContext context)
{
var executeLog = await ExecuteJob(context, async () => await Run(context));
}
public async Task Run(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
List<LogInfo> excLogs = new List<LogInfo>();
var exclogContent = LogLock.ReadLog(Path.Combine(_environment.ContentRootPath, "Log"), $"GlobalExceptionLogs_{DateTime.Now.ToString("yyyMMdd")}.log", Encoding.UTF8);
if (!string.IsNullOrEmpty(exclogContent))
{
excLogs = exclogContent.Split("--------------------------------")
.Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
.Select(d => new LogInfo
{
Datetime = (d.Split("|")[0]).Split(',')[0].ObjToDate(),
Content = d.Split("|")[1]?.Replace("\r\n", "<br>"),
LogColor = "EXC",
Import = 9,
}).ToList();
}
var filterDatetime = DateTime.Now.AddHours(-1);
excLogs = excLogs.Where(d => d.Datetime >= filterDatetime).ToList();
var operateLogs = new List<OperateLog>() { };
excLogs.ForEach(m =>
{
operateLogs.Add(new OperateLog()
{
LogTime = m.Datetime,
Description = m.Content,
IPAddress = m.IP,
UserId = 0,
IsDeleted = false,
});
});
if (operateLogs.Count > 0)
{
var logsIds = await _operateLogServices.Add(operateLogs);
}
}
}
}

View File

@@ -0,0 +1,47 @@
using DouyinApi.Common.Helper;
using DouyinApi.IServices;
using Microsoft.Extensions.Logging;
using Quartz;
using System.Threading.Tasks;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
/// </summary>
namespace DouyinApi.Tasks
{
public class Job_URL_Quartz : JobBase, IJob
{
private readonly ILogger<Job_URL_Quartz> _logger;
public Job_URL_Quartz(ILogger<Job_URL_Quartz> logger, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
: base(tasksQzServices, tasksLogServices)
{
_tasksQzServices = tasksQzServices;
_logger = logger;
}
public async Task Execute(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
}
public async Task Run(IJobExecutionContext context, int jobid)
{
if (jobid > 0)
{
JobDataMap data = context.JobDetail.JobDataMap;
string pars = data.GetString("JobParam");
if (!string.IsNullOrWhiteSpace(pars))
{
var log = await HttpHelper.GetAsync(pars);
_logger.LogInformation(log);
}
}
}
}
}

View File

@@ -0,0 +1,497 @@
using DouyinApi.Model;
using DouyinApi.Model.Models;
using DouyinApi.Model.ViewModels;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Threading.Tasks;
namespace DouyinApi.Tasks
{
/// <summary>
/// 任务调度管理中心
/// </summary>
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
{
// 从Factory中获取Scheduler实例
NameValueCollection collection = new NameValueCollection
{
{ "quartz.serializer.type", "binary" },
};
StdSchedulerFactory factory = new StdSchedulerFactory(collection);
return _scheduler = factory.GetScheduler();
}
}
/// <summary>
/// 开启任务调度
/// </summary>
/// <returns></returns>
public async Task<MessageModel<string>> StartScheduleAsync()
{
var result = new MessageModel<string>();
try
{
this._scheduler.Result.JobFactory = this._iocjobFactory;
if (!this._scheduler.Result.IsStarted)
{
//等待任务运行完成
await this._scheduler.Result.Start();
await Console.Out.WriteLineAsync("任务调度开启!");
result.success = true;
result.msg = $"任务调度开启成功";
return result;
}
else
{
result.success = false;
result.msg = $"任务调度已经开启";
return result;
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 停止任务调度
/// </summary>
/// <returns></returns>
public async Task<MessageModel<string>> StopScheduleAsync()
{
var result = new MessageModel<string>();
try
{
if (!this._scheduler.Result.IsShutdown)
{
//等待任务运行完成
await this._scheduler.Result.Shutdown();
await Console.Out.WriteLineAsync("任务调度停止!");
result.success = true;
result.msg = $"任务调度停止成功";
return result;
}
else
{
result.success = false;
result.msg = $"任务调度已经停止";
return result;
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 添加一个计划任务映射程序集指定IJob实现类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tasksQz"></param>
/// <returns></returns>
public async Task<MessageModel<string>> AddScheduleJobAsync(TasksQz tasksQz)
{
var result = new MessageModel<string>();
if (tasksQz != null)
{
try
{
JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup);
if (await _scheduler.Result.CheckExists(jobKey))
{
result.success = false;
result.msg = $"该任务计划已经在执行:【{tasksQz.Name}】,请勿重复启动!";
return result;
}
if(tasksQz.TriggerType == 0 && tasksQz.CycleRunTimes != 0 && tasksQz.CycleHasRunTimes>=tasksQz.CycleRunTimes)
{
result.success = false;
result.msg = $"该任务计划已完成:【{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
Assembly assembly = Assembly.Load(new AssemblyName(tasksQz.AssemblyName));
Type jobType = assembly.GetType(tasksQz.AssemblyName + "." + tasksQz.ClassName);
#endregion
//判断任务调度是否开启
if (!_scheduler.Result.IsStarted)
{
await StartScheduleAsync();
}
//传入反射出来的执行程序集
IJobDetail job = new JobDetailImpl(tasksQz.Id.ToString(), tasksQz.JobGroup, jobType);
job.JobDataMap.Add("JobParam", tasksQz.JobParams);
ITrigger trigger;
#region
//IJobDetail job = JobBuilder.Create<T>()
// .WithIdentity(sysSchedule.Name, sysSchedule.JobGroup)
// .Build();
#endregion
if (tasksQz.Cron != null && CronExpression.IsValidExpression(tasksQz.Cron) && tasksQz.TriggerType > 0)
{
trigger = CreateCronTrigger(tasksQz);
((CronTriggerImpl)trigger).MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;
}
else
{
trigger = CreateSimpleTrigger(tasksQz);
}
// 告诉Quartz使用我们的触发器来安排作业
await _scheduler.Result.ScheduleJob(job, trigger);
//await Task.Delay(TimeSpan.FromSeconds(120));
//await Console.Out.WriteLineAsync("关闭了调度器!");
//await _scheduler.Result.Shutdown();
result.success = true;
result.msg = $"【{tasksQz.Name}】成功";
return result;
}
catch (Exception ex)
{
result.success = false;
result.msg = $"任务计划异常:【{ex.Message}】";
return result;
}
}
else
{
result.success = false;
result.msg = $"任务计划不存在:【{tasksQz?.Name}】";
return result;
}
}
/// <summary>
/// 任务是否存在?
/// </summary>
/// <returns></returns>
public async Task<bool> IsExistScheduleJobAsync(TasksQz 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<MessageModel<string>> StopScheduleJobAsync(TasksQz sysSchedule)
{
var result = new MessageModel<string>();
try
{
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
if (!await _scheduler.Result.CheckExists(jobKey))
{
result.success = false;
result.msg = $"未找到要暂停的任务:【{sysSchedule.Name}】";
return result;
}
else
{
await this._scheduler.Result.DeleteJob(jobKey);
result.success = true;
result.msg = $"【{sysSchedule.Name}】成功";
return result;
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 恢复指定的计划任务
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
public async Task<MessageModel<string>> ResumeJob(TasksQz sysSchedule)
{
var result = new MessageModel<string>();
try
{
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
if (!await _scheduler.Result.CheckExists(jobKey))
{
result.success = false;
result.msg = $"未找到要恢复的任务:【{sysSchedule.Name}】";
return result;
}
await this._scheduler.Result.ResumeJob(jobKey);
result.success = true;
result.msg = $"【{sysSchedule.Name}】成功";
return result;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 暂停指定的计划任务
/// </summary>
/// <param name="sysSchedule"></param>
/// <returns></returns>
public async Task<MessageModel<string>> PauseJob(TasksQz sysSchedule)
{
var result = new MessageModel<string>();
try
{
JobKey jobKey = new JobKey(sysSchedule.Id.ToString(), sysSchedule.JobGroup);
if (!await _scheduler.Result.CheckExists(jobKey))
{
result.success = false;
result.msg = $"未找到要暂停的任务:【{sysSchedule.Name}】";
return result;
}
await this._scheduler.Result.PauseJob(jobKey);
result.success = true;
result.msg = $"【{sysSchedule.Name}】成功";
return result;
}
catch (Exception)
{
throw;
}
}
#region
public async Task<List<TaskInfoDto>> GetTaskStaus(TasksQz 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>
/// <param name="starRunTime"></param>
/// <param name="endRunTime"></param>
/// <returns></returns>
private ITrigger CreateSimpleTrigger(TasksQz sysSchedule)
{
if (sysSchedule.CycleRunTimes > 0)
{
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup)
.StartAt(sysSchedule.BeginTime.Value)
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(sysSchedule.IntervalSecond)
.WithRepeatCount(sysSchedule.CycleRunTimes - 1))
.EndAt(sysSchedule.EndTime.Value)
.Build();
return trigger;
}
else
{
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup)
.StartAt(sysSchedule.BeginTime.Value)
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(sysSchedule.IntervalSecond)
.RepeatForever()
)
.EndAt(sysSchedule.EndTime.Value)
.Build();
return trigger;
}
// 触发作业立即运行然后每10秒重复一次无限循环
}
/// <summary>
/// 创建类型Cron的触发器
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
private ITrigger CreateCronTrigger(TasksQz sysSchedule)
{
// 作业触发器
return TriggerBuilder.Create()
.WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup)
.StartAt(sysSchedule.BeginTime.Value)//开始时间
.EndAt(sysSchedule.EndTime.Value)//结束数据
.WithCronSchedule(sysSchedule.Cron)//指定cron表达式
.ForJob(sysSchedule.Id.ToString(), sysSchedule.JobGroup)//作业名称
.Build();
}
#endregion
/// <summary>
/// 立即执行 一个任务
/// </summary>
/// <param name="tasksQz"></param>
/// <returns></returns>
public async Task<MessageModel<string>> ExecuteJobAsync(TasksQz tasksQz)
{
var result = new MessageModel<string>();
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.success = true;
result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
}
else
{
await _scheduler.Result.TriggerJob(jobKey);
result.success = true;
result.msg = $"立即执行计划任务:【{tasksQz.Name}】成功";
}
}
catch (Exception ex)
{
result.msg = $"立即执行计划任务失败:【{ex.Message}】";
}
return result;
}
}
}