Hangfire 嵌套批处理错误
Error with Hangfire Nested Batches
我们已经在我们的几个系统上成功使用 Hangfire 一段时间了,并且已经成功地使用 Hangfire 批处理功能来并行执行任务,但是我们在尝试在一个系统上使用它时遇到了一些问题顺序作业。
使用如下简单的批处理效果很好:
BatchJob.Attach(masterBatch, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var preparationJobId = batch.ContinueWith<IPrepareProcessJob>(lockJobId,
job => job.PrepareData(businessUnit, workingJobData, JobCancellationToken.Null));
var statisticsJobId = batch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, workingJobData, JobCancellationToken.Null));
var processFileId = batch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(workingJobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
batch.ContinueWith<IProcessJob>(processFileId, job => job.ReleaseLock(businessUnit));
});
但是,无论三个处理作业发生什么情况,我们都希望始终 运行 最终解锁作业,因此我们尝试在中间三个作业周围引入嵌套批处理,如下所示:
BatchJob.Attach(masterBatch, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var mainBatchId = batch.AwaitJob(lockJobId, mainBatch =>
{
var preparationJobId = mainBatch.Enqueue<IPrepareProcessJob>(
job => job.PrepareData(businessUnit, jobData, JobCancellationToken.Null));
var statisticsJobId = mainBatch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, jobData, JobCancellationToken.Null));
mainBatch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(jobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
});
batch.AwaitBatch<IProcessJob>(mainBatchId, job => job.ReleaseLock(businessUnit));
});
这会产生错误:
Can't create a continuation for batch 'a5955434-294e-4568-9b64-c167feeb95da' because it doesn't exist.
正在调查 Hangfire 尝试附加最终释放锁时产生的错误。有人对我们可能做错了什么有任何建议吗?
我们又花了几个小时试图弄清楚这个问题,我们仍然无法让带有嵌套批处理的版本在不抛出错误的情况下工作,但是通过一些重新安排,我们可以在没有错误的情况下获得所需的功能嵌套:
BatchJob.Attach(mainBatchId, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var preparationJobId = batch.ContinueWith<IPrepareProcessJob>(lockJobId,
job => job.PrepareData(businessUnit, workingJobData, JobCancellationToken.Null));
var statisticsJobId = batch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, workingJobData, JobCancellationToken.Null));
batch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(workingJobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
});
// Catch-all unlock
BatchJob.AwaitBatch(mainBatchId,
batch => batch.Enqueue<IProcessJob>(job => job.ReleaseLock(businessUnit)),
$"Unlock for {reportName}", BatchContinuationOptions.OnAnyFinishedState);
我们已经在我们的几个系统上成功使用 Hangfire 一段时间了,并且已经成功地使用 Hangfire 批处理功能来并行执行任务,但是我们在尝试在一个系统上使用它时遇到了一些问题顺序作业。
使用如下简单的批处理效果很好:
BatchJob.Attach(masterBatch, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var preparationJobId = batch.ContinueWith<IPrepareProcessJob>(lockJobId,
job => job.PrepareData(businessUnit, workingJobData, JobCancellationToken.Null));
var statisticsJobId = batch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, workingJobData, JobCancellationToken.Null));
var processFileId = batch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(workingJobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
batch.ContinueWith<IProcessJob>(processFileId, job => job.ReleaseLock(businessUnit));
});
但是,无论三个处理作业发生什么情况,我们都希望始终 运行 最终解锁作业,因此我们尝试在中间三个作业周围引入嵌套批处理,如下所示:
BatchJob.Attach(masterBatch, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var mainBatchId = batch.AwaitJob(lockJobId, mainBatch =>
{
var preparationJobId = mainBatch.Enqueue<IPrepareProcessJob>(
job => job.PrepareData(businessUnit, jobData, JobCancellationToken.Null));
var statisticsJobId = mainBatch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, jobData, JobCancellationToken.Null));
mainBatch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(jobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
});
batch.AwaitBatch<IProcessJob>(mainBatchId, job => job.ReleaseLock(businessUnit));
});
这会产生错误:
Can't create a continuation for batch 'a5955434-294e-4568-9b64-c167feeb95da' because it doesn't exist.
正在调查 Hangfire 尝试附加最终释放锁时产生的错误。有人对我们可能做错了什么有任何建议吗?
我们又花了几个小时试图弄清楚这个问题,我们仍然无法让带有嵌套批处理的版本在不抛出错误的情况下工作,但是通过一些重新安排,我们可以在没有错误的情况下获得所需的功能嵌套:
BatchJob.Attach(mainBatchId, batch =>
{
var lockJobId = batch.Enqueue<IProcessJob>(job => job.ObtainLock(businessUnit));
var preparationJobId = batch.ContinueWith<IPrepareProcessJob>(lockJobId,
job => job.PrepareData(businessUnit, workingJobData, JobCancellationToken.Null));
var statisticsJobId = batch.ContinueWith<IPrepareProcessJob>(preparationJobId,
job => job.AddStatistics(businessUnit, workingJobData, JobCancellationToken.Null));
batch.ContinueWith<IProcessJob>(statisticsJobId,
job => job.ProcessFile(workingJobData, notifierInstructions, businessUnit,
JobCancellationToken.Null));
});
// Catch-all unlock
BatchJob.AwaitBatch(mainBatchId,
batch => batch.Enqueue<IProcessJob>(job => job.ReleaseLock(businessUnit)),
$"Unlock for {reportName}", BatchContinuationOptions.OnAnyFinishedState);