使用 Quartz.NET 处理链式作业的失败
Handling failures of chained jobs using 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 实现触发器,因为我在没有触发器的情况下将这些作业添加到调度程序。
如何做到这一点?
提前致谢,
马里奥
虽然 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;
}
我过去不得不链接作业,但我没有使用 JobChainingJobListener。
我所做的是在第 (n) 个作业完成时添加并安排第 (n+1) 个作业。例如,当要执行的下一个作业取决于当前作业的结果时,这很有用,就像您的情况一样。
要继续使用 JobChainingJobListener,我认为当 TestJob2 成功结束时,您可以获取 TestJob3 并在其数据映射中设置一个标志。当 TestJob2 出现异常时,TestJob3 仍会执行,但您只需检查您的标志以查看它是否需要继续执行。
子类 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);
}
}
我能够使用 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 实现触发器,因为我在没有触发器的情况下将这些作业添加到调度程序。
如何做到这一点?
提前致谢, 马里奥
虽然 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;
}
我过去不得不链接作业,但我没有使用 JobChainingJobListener。 我所做的是在第 (n) 个作业完成时添加并安排第 (n+1) 个作业。例如,当要执行的下一个作业取决于当前作业的结果时,这很有用,就像您的情况一样。
要继续使用 JobChainingJobListener,我认为当 TestJob2 成功结束时,您可以获取 TestJob3 并在其数据映射中设置一个标志。当 TestJob2 出现异常时,TestJob3 仍会执行,但您只需检查您的标志以查看它是否需要继续执行。
子类 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);
}
}