Hangfire - 多租户,ASP.NET 核心 - 解析正确的租户

Hangfire - Multi tenant, ASP.NET Core - Resolving the correct tenant

我有一个 SaaS 项目需要使用 Hangfire。我们已经实施了识别租户的要求。

建筑

问题

我正在尝试将 TenantId 标记为作业,从 TenantCurrentService(这是一个 Scoped 服务)检索。

当作业执行后,我们需要从作业中检索 TenantId 并将其存储在 HangfireContext 中,这样 TenantCurrentService 就知道从 Hangfire 检索到的 TenantId。从那里,我们的应用程序层将能够从我们的 DbContextFactory

连接到正确的数据库

当前状态

关于这件事有什么好的文章/或者你们可以提供的任何提示吗?

首先,您需要能够在 TenantCurrentService 中设置 TenantId。 然后,您可以依靠过滤器:

客户端(您排队作业的地方)

public class ClientTenantFilter : IClientFilter
{
        public void OnCreating(CreatingContext filterContext)
        {
           if (filterContext == null) throw new ArgumentNullException(nameof(filterContext));

            filterContext.SetJobParameter("TenantId", TenantCurrentService.TenantId);
        }
}

和服务器端(作业出队的地方)。

public class ServerTenantFilter : IServerFilter
{
    public void OnPerforming(PerformingContext filterContext)
    {
      if (filterContext == null) throw new ArgumentNullException(nameof(filterContext));

      var tenantId = filterContext.GetJobParameter<string>("TenantId");
      TenantCurrentService.TenantId = tenantId;
    }
}

当您通过 IJobFilterProvider:

配置服务器时,可以声明服务器过滤器
        var options = new BackgroundJobServerOptions
        {
            Queues = ...,
            FilterProvider = new ServerFilterProvider()
        };
        app.UseHangfireServer(storage, options, ...);

其中 ServerFilterProvider 是:

public class ServerFilterProvider : IJobFilterProvider
{
    public IEnumerable<JobFilter> GetFilters(Job job)
    {
        return new JobFilter[]
                   {
                       new JobFilter(new CaptureCultureAttribute(), JobFilterScope.Global, null),
                       new JobFilter(new ServerTenantFilter (), JobFilterScope.Global,  null),
                   };
    }
}

可以在实例化 BackgroundJobClient 时声明客户端过滤器

var client = new BackgroundJobClient(storage, new BackgroundJobFactory(new ClientFilterProvider());

其中 ClientFilterProvider 的行为与 ServerFilterProvider 相同,提供客户端过滤器

一个困难可能是在过滤器中提供 TenantCurrentService。我想这应该可以通过在 FilterProviders 中注入工厂并将其链接到过滤器来实现。

希望对您有所帮助。