Quartz scheduler 如何在Quartz.Net中处理作业恢复

Quartz scheduler 如何在Quartz.Net中处理作业恢复,quartz-scheduler,scheduling,quartz.net,job-scheduling,quartz,Quartz Scheduler,Scheduling,Quartz.net,Job Scheduling,Quartz,我在使用.NET Core 2.2平台的应用程序中使用了Quartz 3.0.7。 我使用ms sql server进行Quartz操作跟踪。Quartz跟踪并将其动作存储在数据库中,一切正常。 我的StdSchedulerFactory的配置: ["quartz.scheduler.instanceName"] = "StdScheduler", ["quartz.scheduler.instanceId"] = $"{Environment.M

我在使用.NET Core 2.2平台的应用程序中使用了Quartz 3.0.7。 我使用ms sql server进行Quartz操作跟踪。Quartz跟踪并将其动作存储在数据库中,一切正常。 我的StdSchedulerFactory的配置:

            ["quartz.scheduler.instanceName"] = "StdScheduler",
            ["quartz.scheduler.instanceId"] = $"{Environment.MachineName}-{Guid.NewGuid()}",
            ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
            ["quartz.jobStore.useProperties"] = "true",
            ["quartz.jobStore.dataSource"] = "default",
            ["quartz.jobStore.tablePrefix"] = "QRTZ_",
            // if running MS SQL Server we need this
            ["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz",

            ["quartz.dataSource.default.connectionString"] = @"Server=DESKTOP-D64SJFJ\MSSQLSERVER14;Database=quartz;Trusted_Connection=True;",
            ["quartz.dataSource.default.provider"] = "SqlServer",
            [$"{StdSchedulerFactory.PropertyObjectSerializer}.type"] = "json",
            [StdSchedulerFactory.PropertySchedulerInterruptJobsOnShutdownWithWait] = "true",
我想恢复每个被中断的作业。我应该如何组织我的IHostedService逻辑以支持工作恢复? 当我在作业运行期间关闭应用程序时,当我再次启动应用程序时,中断的作业不会运行。 我的IHostedService代码:

    public class QuartzHostedService : IHostedService
{
    private readonly ISchedulerFactory _schedulerFactory;
    private readonly IJobFactory _jobFactory;
    private readonly IEnumerable<JobSchedule> _jobSchedules;

    public QuartzHostedService(
        ISchedulerFactory schedulerFactory,
        IJobFactory jobFactory,
        IEnumerable<JobSchedule> jobSchedules)
    {
        _schedulerFactory = schedulerFactory;
        _jobSchedules = jobSchedules;
        _jobFactory = jobFactory;
    }
    public IScheduler Scheduler { get; set; }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
        Scheduler.JobFactory = _jobFactory;

        await Scheduler.Start(cancellationToken);

        foreach (var jobSchedule in _jobSchedules)
        {
            var job = CreateJob(jobSchedule);
            var trigger = CreateTrigger(jobSchedule);

            if (!await Scheduler.CheckExists(job.Key, cancellationToken))
            {
                // if the job doesn't already exist, we can create it, along with its trigger. this prevents us
                // from creating multiple instances of the same job when running in a clustered environment
                await Scheduler.ScheduleJob(job, trigger);
            }
            else
            {
                // if the job has exactly one trigger, we can just reschedule it, which allows us to update the schedule for
                // that trigger.
                var triggers = await Scheduler.GetTriggersOfJob(job.Key);
                if (triggers.Count == 1)
                {
                    await Scheduler.RescheduleJob(triggers.First().Key, trigger);
                }
                else
                {
                    // if for some reason the job has multiple triggers, it's easiest to just delete and re-create the job,
                    // since we want to enforce a one-to-one relationship between jobs and triggers
                    await Scheduler.DeleteJob(job.Key);
                    await Scheduler.ScheduleJob(job, trigger);
                }
            }
        }
    }


    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await Scheduler?.Shutdown(cancellationToken);
    }

    private static IJobDetail CreateJob(JobSchedule schedule)
    {
        var jobType = schedule.JobType;
        return JobBuilder
            .Create(jobType)
            .WithIdentity(jobType.FullName)
            .WithDescription(jobType.Name)
            .RequestRecovery(true)
            .StoreDurably()
            .Build();
    }

    private static ITrigger CreateTrigger(JobSchedule schedule)
    {
        return TriggerBuilder
            .Create()
            .WithIdentity($"{schedule.JobType.FullName}.trigger")
            .WithCronSchedule(schedule.CronExpression)
            .WithDescription(schedule.CronExpression)
            .Build();
    }
}
公共类QuartzHostedService:IHostedService
{
私有只读isSchedulerFactory\u schedulerFactory;
私有只读IJobFactory\u jobFactory;
私有只读IEnumerable\u作业计划;
公共托管服务(
IsSchedulerFactory schedulerFactory,
IJobFactory jobFactory,
i可数作业计划表)
{
_schedulerFactory=schedulerFactory;
_作业计划=作业计划;
_jobFactory=jobFactory;
}
公共ISScheduler调度程序{get;set;}
公共异步任务StartAsync(CancellationToken CancellationToken)
{
Scheduler=wait_schedulerFactory.GetScheduler(cancellationToken);
Scheduler.JobFactory=\u JobFactory;
等待调度程序启动(cancellationToken);
foreach(var作业计划在_作业计划中)
{
var job=CreateJob(作业计划);
var trigger=CreateTrigger(作业计划);
如果(!wait Scheduler.check存在(job.Key,cancellationToken))
{
//如果作业不存在,我们可以创建它以及它的触发器。这会阻止我们
//在群集环境中运行时创建同一作业的多个实例
wait Scheduler.ScheduleJob(作业,触发器);
}
其他的
{
//如果作业只有一个触发器,我们可以重新安排它,这样我们就可以更新作业的计划
//那个扳机。
var triggers=wait Scheduler.GetTriggersOfJob(job.Key);
if(triggers.Count==1)
{
wait Scheduler.RescheduleJob(triggers.First().Key,trigger);
}
其他的
{
//如果由于某种原因,作业有多个触发器,则最简单的方法是删除并重新创建作业,
//因为我们想要在作业和触发器之间实现一对一的关系
wait Scheduler.DeleteJob(job.Key);
wait Scheduler.ScheduleJob(作业,触发器);
}
}
}
}
公共异步任务StopAsync(CancellationToken CancellationToken)
{
等待调度程序?关机(取消令牌);
}
专用静态IJobDetail CreateJob(作业时间表)
{
var jobType=schedule.jobType;
返回工
.Create(作业类型)
.WithIdentity(作业类型.全名)
.WithDescription(作业类型.名称)
.RequestRecovery(真)
.可储存的()
.Build();
}
专用静态ITrigger CreateTrigger(作业计划)
{
返回触发器生成器
.Create()
.WithIdentity($“{schedule.JobType.FullName}.trigger”)
.WithCronSchedule(schedule.CronExpression)
.WithDescription(schedule.CronExpression)
.Build();
}
}
My startup.cs:

private void ConfigureQuartz(IServiceCollection services)
    {
        services.AddHostedService<QuartzHostedService>();

        services.AddSingleton<IJobFactory, SingletonJobFactory>();
        services.AddSingleton<ISchedulerFactory>(new StdSchedulerFactory(StdSchedulerFactoryConfiguration()));

        services.AddSingleton<AuthKeyExpiresJob>();
        //services.AddSingleton<AuthKeyWillExpireJob>();

        services.AddSingleton(new JobSchedule(
            typeof(AuthKeyExpiresJob),
            "0 14 11 ? * *"));
    }
private void ConfigureQuartz(IServiceCollection服务)
{
services.AddHostedService();
services.AddSingleton();
AddSingleton(新的StdSchedulerFactory(StdSchedulerFactoryConfiguration());
services.AddSingleton();
//services.AddSingleton();
服务。添加Singleton(新作业计划(
类型(AuthKeyExpiresJob),
"0 14 11 ? * *"));
}