如何包装Hangfire取消令牌?

问题描述 投票:2回答:1

我正在构建一个.net核心网络应用,该应用需要运行后台任务。为了避免使用外部cron触发器,我们决定使用Hangfire。这是一个漂亮的程序包,可以精确地执行所需的操作,然后就可以摆脱;-)

为了保持环境整洁,我试图遵循Bob叔叔的Clean架构原则,并尽可能将ApplicationCore与基础架构分开。由于Hangfire是一个实现细节,因此理想情况下,它应该位于基础结构项目中,并与数据库访问,消息队列等一起放在我的域可以使用的ApplicationCore中的一个接口上。

对于运行定期和后台作业的基本客户端,这非常简单,我最终将其作为Interface

namespace ApplicationCore.Interfaces
{
    using System;
    using System.Linq.Expressions;
    using System.Threading.Tasks;

    public interface IBackgroundJobClient
    {
        void AddOrUpdate<T>(
            string recurringJobId,
            Expression<Func<T, Task>> methodCall,
            string cronExpression);

         void RemoveIfExists(string recurringJobId);
    }
}

实现是这些使用RecurringJob的方法的简单包装器>

namespace Infrastructure.BackgroundJobs
{
    using System;
    using System.Linq.Expressions;
    using System.Threading.Tasks;
    using Hangfire;
    using IBackgroundJobClient = ApplicationCore.Interfaces.IBackgroundJobClient;

    public class HangfireBackgroundJobClient : IBackgroundJobClient
    {
        public void AddOrUpdate<T>(
            string recurringJobId,
            Expression<Func<T, Task>> methodCall,
            string cronExpression)
        {
            RecurringJob.AddOrUpdate<T>(recurringJobId, methodCall, cronExpression);
        }

        public void RemoveIfExists(string recurringJobId)
        {
            RecurringJob.RemoveIfExists(recurringJobId);
        }
    }

我所需要解决的问题是使用提供的cancelleToken设置RecurringJob。但是,在不暴露ApplicationCore代码中的基础IJobCancellationTokenJobCancellationToken对象的情况下,我看不到实现此目的的简便方法。

目前我所拥有的是基础结构中JobCancellationToken的包装。

namespace Infrastructure.BackgroundJobs
{
    public class BackgroundJobCancellationToken : JobCancellationToken
    {
        public BackgroundJobCancellationToken(bool canceled): base(canceled)
        {
        }
    }
}

我的ApplicationCore中的一个接口,它复制了Hangfire的一个接口。

namespace ApplicationCore.Interfaces
{
    using System.Threading;

    public interface IJobCancellationToken
    {
        CancellationToken ShutdownToken { get; }

        void ThrowIfCancellationRequested();
    }
}

然后由我想作为作业执行的方法使用,利用cancellationToken.ShutdownToken传递给其他需要cancelToken的方法。

public async Task GenerateSubmission(Guid SetupGuidId, IJobCancellationToken cancellationToken)
        {
            try
            {
                // Sort out the entities that we'll need
                var setup = await this.SetupRepository.GetByGuidIdAsync(SetupGuidId);

                var forecast = await this.GetCurrentForecastForSetup(setup, DateTime.UtcNow, cancellationToken.ShutdownToken);

                // Other Code

                }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

依次通过调用启用了其他位置

    public async Task<Setup> EnableSetup(Setup setup)
    {
        setup.Enable();

        this.jobClient
            .AddOrUpdate<IForecastService>(
                setup.GuidId.ToString(),
                f => f.GenerateSubmission(setup.GuidId, null),
                "45 */2 * * *");

        await this.setupRepository.UpdateAsync(setup);

        return setup;
    }

这应该通过DomainEvents和Handlers完成,但一次只执行一个步骤:-)

是否在我的ApplicationCore中没有直接依赖Hangfire的情况下实现了更干净,更好,更轻松的方法?

如果上述设置有效,我将在这个问题上发表评论。

我正在构建一个.net核心网络应用,该应用需要运行后台任务。为了避免使用外部cron触发器,我们决定使用Hangfire。这是一个漂亮的软件包,可以使用...

domain-driven-design hangfire clean-architecture cancellation-token
1个回答
0
投票

自Hangfire 1.7起,您不再需要依赖IJobCancellationToken。您可以直接使用标准.NET CancellationToken

© www.soinside.com 2019 - 2024. All rights reserved.