痛并快乐
自上一次 Sundial 发布已过 12 天,借助 Furion 框架的人气,Sundial 在 Nuget 平台下载量达到了 1900+ 次,随着越来越多的开发者使用,也暴露出了之前架构设计一些不灵活的问题,收集到了不少建议和问题反馈。
这一次不再是独自一人,为了尽快优化架构和功能改进,拉了4个小伙伴一起对所有代码、注释、文档进行了完整性审查工作,历尽5天的时间,终于解决了现有的所有问题还添加了不少新特性。
这十多天被各种问题搞得焦头烂额,但痛并快乐着~
项目概况
- 仓库地址:https://gitee.com/dotnetchina/Sundial
- 文档地址:https://furion.baiqian.ltd/docs/job
亮点展现
此版本在解决不少问题的同时,也增加了不少亮点。
1. 简化作业执行上下文默认字符串输出行为
public class MyJob : IJob { private readonly ILogger<MyJob> _logger; public MyJob(ILogger<MyJob> logger) { _logger = logger; } public Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { _logger.LogInformation($"{context}"); return Task.CompletedTask; } }
services.AddSchedule(options => { // 注册作业,并配置作业触发器 options.AddJob<MyJob>(Triggers.Secondly()); // 表示每秒执行 });
info: 2022-12-02 16:51:33.5032989 +08:00 星期五 L System.Logging.ScheduleService[0] #1 Schedule hosted service is running. info: 2022-12-02 16:51:33.5180669 +08:00 星期五 L System.Logging.ScheduleService[0] #1 Schedule hosted service is preloading... info: 2022-12-02 16:51:34.1452041 +08:00 星期五 L System.Logging.ScheduleService[0] #1 The <job1_trigger1> trigger for scheduler of <job1> successfully appended to the schedule. info: 2022-12-02 16:51:34.1541701 +08:00 星期五 L System.Logging.ScheduleService[0] #1 The scheduler of <job1> successfully appended to the schedule. warn: 2022-12-02 16:51:34.1748401 +08:00 星期五 L System.Logging.ScheduleService[0] #1 Schedule hosted service preload completed, and a total of <1> schedulers are appended. info: 2022-12-02 16:51:35.0712571 +08:00 星期五 L MyJob[0] #4 <job1> [C] <job1 job1_trigger1> * * * * * * 1ts 2022-12-02 16:51:35.000 -> 2022-12-02 16:51:36.000 info: 2022-12-02 16:51:36.0317375 +08:00 星期五 L MyJob[0] #14 <job1> [C] <job1 job1_trigger1> * * * * * * 2ts 2022-12-02 16:51:36.000 -> 2022-12-02 16:51:37.000 info: 2022-12-02 16:51:37.0125007 +08:00 星期五 L MyJob[0] #9 <job1> [C] <job1 job1_trigger1> * * * * * * 3ts 2022-12-02 16:51:37.000 -> 2022-12-02 16:51:38.000 info: 2022-12-02 16:51:38.0179920 +08:00 星期五 L MyJob[0] #8 <job1> [C] <job1 job1_trigger1> * * * * * * 4ts 2022-12-02 16:51:38.000 -> 2022-12-02 16:51:39.000
JobExecutionContext 重写了 ToString() 方法并提供以下几种格式:
# 持续运行格式 <作业Id> 作业描述 [并行C/串行S] <作业Id 触发器Id> 触发器字符串 触发器描述 触发次数ts 触发时间 -> 下一次触发时间 # 触发停止格式 <作业Id> 作业描述 [并行C/串行S] <作业Id 触发器Id> 触发器字符串 触发器描述 触发次数ts 触发时间 [触发器终止状态]
2. 添加动态委托作业功能
service.AddSchedule(options => { options.AddJob((serviceProvider, context, stoppingToken) => { serviceProvider.GetLogger().LogInformation($"{context}"); return Task.CompletedTask; }, Triggers.PeriodSeconds(5)); });
3. 支持动态编译作业处理程序代码
// 初始化 NatashaInitializer.Preheating(); // 创建程序集(可自定义编写程序集名称) var oop = new AssemblyCSharpBuilder("JobAssembly") { Domain = DomainManagement.Random() }; // 添加代码 oop.Add(@" using Furion.Schedule; using Microsoft.Extensions.Logging; using System; using System.Threading; using System.Threading.Tasks; namespace YourProject; public class MyJob : IJob { private readonly ILogger<MyJob> _logger; public MyJob(ILogger<MyJob> logger) { _logger = logger; } public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) { _logger.LogInformation($""我是 Roslyn 方式创建的:{context}""); await Task.CompletedTask; } } "); // 生成运行时 MyJob 类型 var jobType = oop.GetTypeFromShortName("MyJob");
4. 提供更多内置作业触发器方法和特性
// 间隔 Period 方式 // 创建毫秒周期(间隔)作业触发器构建器 var triggerBuilder = Triggers.Period(5000); // 创建秒周期(间隔)作业触发器构建器 var triggerBuilder = Triggers.PeriodSeconds(5); // 创建分钟周期(间隔)作业触发器构建器 var triggerBuilder = Triggers.PeriodMinutes(5); // 创建小时周期(间隔)作业触发器构建器 var triggerBuilder = Triggers.PeriodHours(5); // Cron 表达式方式 // 创建 Cron 表达式作业触发器构建器 var triggerBuilder = Triggers.Cron("* * * * *", CronStringFormat.Default); // 创建每秒开始作业触发器构建器 var triggerBuilder = Triggers.Secondly(); // 创建每分钟开始作业触发器构建器 var triggerBuilder = Triggers.Minutely(); // 创建每小时开始作业触发器构建器 var triggerBuilder = Triggers.Hourly(); // 创建每天(午夜)开始作业触发器构建器 var triggerBuilder = Triggers.Daily(); // 创建每月1号(午夜)开始作业触发器构建器 var triggerBuilder = Triggers.Monthly(); // 创建每周日(午夜)开始作业触发器构建器 var triggerBuilder = Triggers.Weekly(); // 创建每年1月1号(午夜)开始作业触发器构建器 var triggerBuilder = Triggers.Yearly(); // 创建每周一至周五(午夜)开始作业触发器构建器 var triggerBuilder = Triggers.Workday(); // Cron 表达式 Macro At 方式 // 每第 3 秒 var triggerBuilder = Triggers.SecondlyAt(3); // 每第 3,5,6 秒 var triggerBuilder = Triggers.SecondlyAt(3, 5, 6); // 每分钟第 3 秒 var triggerBuilder = Triggers.MinutelyAt(3); // 每分钟第 3,5,6 秒 var triggerBuilder = Triggers.MinutelyAt(3, 5, 6); // 每小时第 3 分钟 var triggerBuilder = Triggers.HourlyAt(3); // 每小时第 3,5,6 分钟 var triggerBuilder = Triggers.HourlyAt(3, 5, 6); // 每天第 3 小时正(点) var triggerBuilder = Triggers.DailyAt(3); // 每天第 3,5,6 小时正(点) var triggerBuilder = Triggers.DailyAt(3, 5, 6); // 每月第 3 天零点正 var triggerBuilder = Triggers.MonthlyAt(3); // 每月第 3,5,6 天零点正 var triggerBuilder = Triggers.MonthlyAt(3, 5, 6); // 每周星期 3 零点正 var triggerBuilder = Triggers.WeeklyAt(3); var triggerBuilder = Triggers.WeeklyAt("WED"); // SUN(星期天),MON,TUE,WED,THU,FRI,SAT // 每周星期 3,5,6 零点正 var triggerBuilder = Triggers.WeeklyAt(3, 5, 6); var triggerBuilder = Triggers.WeeklyAt("WED", "FRI", "SAT"); // 还支持混合 var triggerBuilder = Triggers.WeeklyAt(3, "FRI", 6); // 每年第 3 月 1 日零点正 var triggerBuilder = Triggers.YearlyAt(3); var triggerBuilder = Triggers.YearlyAt("MAR"); // JAN(一月),FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC // 每年第 3,5,6 月 1 日零点正 var triggerBuilder = Triggers.YearlyAt(3); var triggerBuilder = Triggers.YearlyAt(3, 5, 6); var triggerBuilder = Triggers.YearlyAt("MAR", "MAY", "JUN"); // 还支持混合 var triggerBuilder = Triggers.YearlyAt(3, "MAY", 6);
5. 改进作业持久化设计
public class DbJobPersistence : IJobPersistence { public IEnumerable<SchedulerBuilder> Preload() { // 作业调度服务启动时运行时初始化,可通过数据库加载,或者其他方式 return Array.Empty<SchedulerBuilder>(); } public SchedulerBuilder OnLoading(SchedulerBuilder builder) { // 如果是更新操作,则 return builder.Updated(); 将生成 UPDATE 语句 // 如果是新增操作,则 return builder.Appended(); 将生成 INSERT 语句 // 如果是删除操作,则 return builder.Removed(); 将生成 DELETE 语句 // 如果无需标记操作,返回 builder 默认值即可 return builder; } public void OnChanged(PersistenceContext context) { var sql = context.ConvertToSQL("job_detail"); // 这里执行 sql 即可 💖 } public void OnTriggerChanged(PersistenceTriggerContext context) { var sql = context.ConvertToSQL("job_trigger"); // 这里执行 sql 即可 💖 } }
还有更多更多功能改进可查阅文档:https://furion.baiqian.ltd/docs/job
本期更新
-
新特性
- [新增] 定时任务间隔分钟作业触发器
Triggers.PeriodMinutes(5)
和[PeriodMinutes(5)]
特性 4.8.2.8 ⏱️2022.12.01 8e1f06f - [新增] 定时任务工作日作业触发器
Triggers.Workday()
和[Workday]
特性 4.8.2.6 ⏱️2022.11.30 28b2d20 - [新增] 定时任务作业校对功能,可对误差进行校正 4.8.2.6 ⏱️2022.11.30 f725a25
- [新增] 定时任务
Triggers
所有带At
的Cron
表达式触发器构建器及特性 4.8.2.5 ⏱️2022.11.29 #I63PLR - [新增] 定时任务批量添加
SchedulerBuilder
作业功能 4.8.2.4 ⏱️2022.11.29 5faa67b - [新增] 定时任务
BuildSqlType
配置,可设置生成不同数据库类型的SQL
语句 4.8.2.3 ⏱️2022.11.29 293f9bc !675 - [新增]
JobDetail
和Trigger
自定义ConvertToSQL
输出SQL
配置 4.8.2 ⏱️2022.11.27 0bb9d8f - [新增] 作业触发器
ResetOnlyOnce
属性,支持只运行一次的作业重新启动服务重复执行 4.8.1.5 ⏱️2022.11.25 a8be728 - [新增] 动态作业处理程序委托支持 4.8.1.8 ⏱️2022.11.27 e02266c
- [新增] 定时任务间隔分钟作业触发器
-
突破性变化
- [调整] 定时任务底层所有代码,日志,注释,文档 4.8.1.10 ⏱️2022.12.05
-
问题修复
- [修复] 作业触发器不符合下一次执行规律但
NextRunTime
不为null
情况 4.8.1.5 ⏱️2022.11.25 a8be728 - [修复] 运行时启动/暂停作业无效问题 4.8.1.6 ⏱️2022.11.25 #I6368M
- [修复] 定时任务生成的
SQL
语句不支持MySQL
问题 4.8.1.7 ⏱️2022.11.26 #I638ZC
- [修复] 作业触发器不符合下一次执行规律但
-
其他更改
- [调整] 定时任务调度器时间精度,控制持续执行一年误差在
100ms
以内 4.8.2.9 ⏱️2022.12.01 334d089 - [调整] 定时任务作业计划工厂
GetNextRunJobs()
方法逻辑 4.8.2.7 ⏱️2022.11.30 #I63VS2
- [调整] 定时任务调度器时间精度,控制持续执行一年误差在
-
文档
- [新增] 作业触发器
ResetOnlyOnce
文档 4.8.1.5 ⏱️2022.11.25 a8be728 - [新增] 通过
Roslyn
动态编译代码创建IJob
类型文档 4.8.1.5 ⏱️2022.11.25 2c5e5be - [新增] 自定义
JobDetail
和Trigger
输出SQL
文档 4.8.2 ⏱️2022.11.27 0bb9d8f
- [新增] 作业触发器
还没有评论,来说两句吧...