问题描述
我有一个定期运行的石英作业,在执行过程中,我将通过HttpClient提交一个rest api请求。当前,如果其余api“调用”失败(例如错误的请求状态代码400),它将“重新发送”相同的api调用,例如2-4次。这种行为不是“正确的”,我只想记录rest api调用的结果,因为我不希望在原始触发时间之后执行postasync请求。
- 所以这基本上是“伪代码”,我只是通过石英作业创建了一堆报告,然后发送它们。
- 当createreport失败,以某种方式“重新发送”请求时会发生问题(我在等待后从createReport函数中登录,并且看到请求重新发送/响应再次收到)
- 我对此很陌生,所以我不确定重试机制是否已经被烘焙到异步等待中,或者石英本身。
class Job : IJob
{
public async Task Execute(IJobExecutionContext context)
{
var tasks = Enumerable.Range(0,count).Select(index => CreateReport(index));
try
{
await Task.WhenAll(tasks);
}
catch { }
}
public static async Task CreateReport(int index)
{
var response = await ReportApi.PostAsync($"api/createReport/...",null);
}
}
解决方法
在这种情况下,理想情况下,您将为模型建模更像消息传递。您可以有一个作业,但是可以为每个调用该作业的报表创建一个触发器,可以将“报告ID /用户ID /等”作为参数来触发作业数据映射。这样,一次只报告一份就可以解决问题。
现在,如果您的工作失败,则默认情况下将重试。您可以通过在逻辑周围进行try-catch来禁止这种情况,并在发生错误引发JobExecutionException
时允许通过其属性来设置逻辑条件,例如UnscheduleFiringTrigger
可以使它停止再次尝试-这是用于单发扳机,该扳机在施杜勒跑步过程中不会再触发。
通常,我会建议在外部资源(例如数据库)中进行状态管理(已生成报告)。然后在触发器中检查什么是正确的操作。也像注释中建议的那样,重试库可能允许进行更细粒度的操作。