我正在构建一个.net核心Web应用程序,该应用程序需要运行后台任务。为了避免使用外部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的情况下,是否存在一种更清洁,更好,更轻松的方法?
如果上述设置有效,我将在这个问题上发表评论。
答案 0 :(得分:0)
从Hangfire 1.7开始,您不再需要依赖.mkd.
。您可以直接使用标准的.NET IJobCancellationToken
。