我正在构建一个.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代码中的基础IJobCancellationToken
和JobCancellationToken
对象的情况下,我看不到实现此目的的简便方法。目前我所拥有的是基础结构中
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。这是一个漂亮的软件包,可以使用...
自Hangfire 1.7起,您不再需要依赖IJobCancellationToken
。您可以直接使用标准.NET CancellationToken
。