使用Quartz.NET处理链接作业的失败

时间:2015-07-29 20:47:19

标签: c# quartz.net

我能够使用Quartz.NET安排3个链式作业。这个策略运作良好:

var j1 = new TestJob1();
var j2 = new TestJob2();
var j3 = new TestJob3();

var jd1 = j1.Build();
var jd2 = j2.Build();
var jd3 = j3.Build();


var chain = new JobChainingJobListener("jobchain");
chain.AddJobChainLink(jd1.Key, jd2.Key);
chain.AddJobChainLink(jd2.Key, jd3.Key);


Scheduler.ListenerManager.AddJobListener(chain, GroupMatcher<JobKey>.AnyGroup());

Scheduler.ScheduleJob(jd1, j1.JobTrigger());
Scheduler.AddJob(jd2, true);
Scheduler.AddJob(jd3, true);


Scheduler.Start();

每项工作的代码如下:

public class TestJob1 : BaseJob, IJob
    {
        public override ITrigger JobTrigger()
        {
             return TriggerBuilder.Create()
                 .WithSimpleSchedule(
                     ssb =>
                     ssb.WithInterval(new TimeSpan(0, 0, 0, 10)).RepeatForever().WithMisfireHandlingInstructionFireNow())
                 .Build();
        }

        public void Execute(IJobExecutionContext context)
        {
            Debug.WriteLine($"Running Job 1 at {DateTime.Now.ToString("O")}");
        }
    }

    public class TestJob2 : BaseJob, IJob
    {
        public override ITrigger JobTrigger()
        {
            throw new System.NotImplementedException();
        }

        public void Execute(IJobExecutionContext context)
        {
            Debug.WriteLine($"Running Job 2 at {DateTime.Now.ToString("O")}");
            throw new Exception("forced error");
        }
    }

    public class TestJob3 : BaseJob, IJob
    {
        public override ITrigger JobTrigger()
        {
            throw new System.NotImplementedException();
        }

        public void Execute(IJobExecutionContext context)
        {
            Debug.WriteLine($"Running Job 3 at {DateTime.Now.ToString("O")}");
        }
    }

如果你看到,TestJob2在运行时抛出异常。即使在这种情况下,TestJob3也会被解雇。我的业务要求是,如果TestJob2失败,不应该触发TestJob3。请注意,实际上我不需要为job2和job3实现触发器,因为我在没有触发器的情况下将这些作业添加到调度程序中。

如何做到这一点?

提前致谢, 马里奥

3 个答案:

答案 0 :(得分:1)

虽然JobChain对我来说是新手,但我仍然会使用基本clr api调用并通过链接任务(https://msdn.microsoft.com/en-us/library/ee372288(v=vs.110).aspx)来利用任务并行库(tpl)。

这个特殊的代码将四个不同的任务链接在一起,如果没有先前的完成,就无法触发。我希望Quartz做的就是安排并致电我的工作。如果我偏离石英api,我很抱歉,但我只想提供一种处理多项任务的方式。

在我的工作中,我输入作业执行并执行调用Process()

private async Task<Boolean> Process()
{   
   Task<bool> t1 = Task<bool>.Factory.StartNew(() =>
   {
      return processThis();
   });


   Task<bool> t2 = t1.ContinueWith((ProcessMore) =>
   {
      return processMoreStuff();
   });

   Task<bool> t3 = t2.ContinueWith((ProcessEvenMore) =>
   {
      return processEvenMoreStuff();
   });

   Task<bool> t4 = t3.ContinueWith((ProcessStillSomeMore) =>
   {
      return processStillMoreStuff();
   });


    var result = await t4;

   try
   {
      Task.WaitAll(t1, t2, t3, t4);
   }
   catch (Exception ex)
   {
      System.Diagnostics.Trace.WriteLine(ex.Message);
   }

   return result;
}

答案 1 :(得分:1)

过去我必须连接工作但我没有使用JobChainingJobListener。 我做的是在第(n)个工作完成后添加并安排第(n + 1)个工作。这有助于例如当要执行的下一个作业取决于当前作业的结果时,就像在您的情况下一样。

继续使用JobChainingJobListener我认为当TestJob2成功结束时,你可以获得TestJob3并在其数据映射中设置一个标志。当TestJob2中存在异常时,TestJob3仍将被执行,但您只需检查您的标志,看它是否需要继续执行。

答案 2 :(得分:1)

子类JobChainingJobListener,并使用JobChainingJobListenerFailOnError代替JobChainingJobListener

/// <summary>
/// JobChainingJobListener that doesn't run subsequent jobs when one fails.
/// </summary>
public class JobChainingJobListenerFailOnError : JobChainingJobListener
{
    public JobChainingJobListenerFailOnError(String name) : base(name) { }

    public override void JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
    {
        //Only call the base method if jobException is null.  Otherwise, an
        //error has occurred & we don't want to continue chaining
        if (jobException == null)
            base.JobWasExecuted(context, jobException);
    }
}