Hangfire ContinueWithJob 卡在等待状态,尽管父作业已经成功

Hangfire ContinueWithJob is stuck in awaiting state, though parent job has succeeded

我通过 ContinueJobWith<MyHandler>(parentJobId, x => x.DoWork()) 一个接一个地执行了一些作业。

但是,第二个作业没有得到处理,始终处于 Awaiting 状态:

作业本身是这样的:

为什么会发生这种情况以及在哪里检查结果?

            builder.RegisterType<BackgroundJobStateChanger>()
                   .As<IBackgroundJobStateChanger>()
                   .InstancePerLifetimeScope();

这没什么区别。

作业是这样执行的:

var parentJobId = _backgroundJobClient.Schedule<Handler>(h => h.ConvertCertToTraining(certId, command.SetUpOneToOneRelationship), TimeSpan.FromSeconds(1));
var filesCopyJObId = _backgroundJobClient.ContinueJobWith<Handler>(parentJobId, h => h.CopyAttachedFiles());
_backgroundJobClient.ContinueJobWith<Handler>(filesCopyJObId, h => h.NotifyUser(command.CertificationToBeConvertedIds, _principal.GetEmail()));

所有参数都是intboolstring。如果我手动将等待的作业排入队列,它们将毫无问题地执行。

我添加了 Hangfire 日志记录,但看不到任何问题:服务器启动、停止、作业更改状态,但看不到任何明显的错误。

我还应该考虑哪些其他事项或 where/how 我应该对此进行调试?

从表面上看,ID 为 216348 的第一个作业已成功完成,但 ID 为 216349 的第二个作业正在等待 216347 的父 ID。根据 Hangfire 文档和经验,parentID 应该是您在执行第二个作业之前等待完成的作业。

根据 Hangfire documentation on ContinueJobWith,“在其父作业 完成后执行继续 ”。从您的屏幕截图中,不清楚 JobID 是怎么回事:216347。此作业 216347 完成后,ID 为 216349 的作业应启动。如果您希望 216349216348 完成后开始,请检查您的代码并确保将正确的 ParentID 传递给第二个作业。


Update

基于on this thread,将ContinuationsSupportAttribute 添加到配置Hangfire 服务的GlobalJobFilters.Filter。这应该使您的 Hangfire 实例知道继续作业。

GlobalJobFilters.Filters.Add(new ContinuationsSupportAttribute());

在调查过程中,发现我们将 JobFilterProviderCollection 替换为我们自己的 collection:

    var filterProviderCollection = new JobFilterProviderCollection
    {
        new MyFilterProvider(...)
    };
    var backgroundJobClient = new BackgroundJobClient(JobStorage.Current, filterProviderCollection);

MyFilterProvider 看起来像这样:

    public IEnumerable<JobFilter> GetFilters(Job job)
    {
        return new JobFilter[]
        {
             new JobFilter(new HangfireTenantFilter(_tenantDetail, _principal), JobFilterScope.Global,  null),
             new JobFilter(new HangfireFunctionalityFilter(_functionalityFilter), JobFilterScope.Global, null),
        };
    }

事实证明,在 Continuation 上工作的代码只从这个过滤器 collection 中获取过滤器,ContinuationsSupportAttribute 没有在正确的时间在那里执行。因此 re-adding 来自 GlobalJobFilters.Filters 的默认 Hangfire 过滤器修复了这种情况:

    public IEnumerable<JobFilter> GetFilters(Job job)
    {
        var customFilters = new List<JobFilter>()
        {
             new JobFilter(new HangfireTenantFilter(_tenantDetail, _principal), JobFilterScope.Global,  null),
             new JobFilter(new HangfireFunctionalityFilter(_functionalityFilter), JobFilterScope.Global, null),
        };
        customFilters.AddRange(GlobalJobFilters.Filters);

        return customFilters;
    }