Replies: 1 comment
-
I have a similar setup like this: public static class Startup
{
// Call this in app startup before `webAppBuilder.Build()`
internal static IServiceCollection AddBackgroundJobs(this IServiceCollection services, IConfiguration config)
{
...
services.AddTransient<RecurringJobInitializer>();
services.AddTransient<TenantRecurringJobInitializer>();
}
// Call this in app startup right before `await app.RunAsync()`
public static async Task InitializeRecurringJobsAsync(this IServiceProvider services, CancellationToken ct = default)
{
// Create a new scope to retrieve scoped services
using var scope = services.CreateScope();
await scope.ServiceProvider.GetRequiredService<RecurringJobInitializer>()
.InitializeRecurringJobsAsync(ct);
}
}
internal class RecurringJobInitializer(TenantDbContext tenantDbContext, IServiceProvider serviceProvider)
{
private readonly TenantDbContext _tenantDbContext = tenantDbContext;
private readonly IServiceProvider _serviceProvider = serviceProvider;
public async Task InitializeRecurringJobsAsync(CancellationToken ct)
{
foreach (var tenant in await _tenantDbContext.TenantInfo.ToListAsync(ct))
{
InitializeRecurringJobsForTenant(tenant);
}
}
private void InitializeRecurringJobsForTenant(FSHTenantInfo tenant)
{
// create a new scope
using var scope = _serviceProvider.CreateScope();
// set current tenant
_serviceProvider.GetRequiredService<IMultiTenantContextSetter>()
.MultiTenantContext = new MultiTenantContext<FSHTenantInfo>() { TenantInfo = tenant };
// run the initialization in the new scope
scope.ServiceProvider.GetRequiredService<TenantRecurringJobInitializer>()
.Initialize();
}
}
internal class TenantRecurringJobInitializer(ICurrentTenant currentTenant, IBackgroundJobService backgroundJobs, ILogger<TenantRecurringJobInitializer> logger)
{
private readonly ICurrentTenant _currentTenant = currentTenant;
private readonly IBackgroundJobService _backgroundJobs = backgroundJobs;
private readonly ILogger<TenantRecurringJobInitializer> _logger = logger;
public void Initialize()
{
_logger.LogDebug("Initializing recurring jobs for {TenantId}", _currentTenant.Id);
// Clear CommandRunData every day at 10:00
_backgroundJobs.AddOrUpdate(
$"{_currentTenant.Identifier}-CleanCommandRunData",
new ClearCommandRunDataCommand(null, "Schedule"),
"0 10 * * *",
timeZone: TimeZoneInfo.Local);
_logger.LogDebug("Recurring jobs initialized");
}
} I did put everything in infrastructure for now... but you could do something similar like ICustomSeeder and CustomSeederRunner (under Persistence\Initialization) and make an ICustomRecurringJobInitializer interface and a CustomRecurringJobInitializerRunner. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi There
I'm struggling with the following.
I have a Hangfire Job which runs every day to recalucalte the working time of the Employees. I register the Background Job via the IJobService with the Reccuring() Methode.
The Issue is that this does not set the MultiTenantContext of the Finbuckle Multitenancy, so there is a Tenant Error during the execution of the Background Jobs.
I can think of the ways to go about it.
Register the Recurring Background Job for each Tenant, kind of like the InitializeDatabasesAsync() is looping through the tenants. In this case the Application Layout does not need to know abount the Multitenancy. The Infrastructure Layout does need some way to get all the Reccuring Jobs defined in the Application Layer.
Register one Reccuring Job for all the Tenants and then handle the Tenants during the Execution of the Job. In this Case all the MultiTenantContext needs to be set manually since there is no HttpContext which sets the MultiTenantContext like when you make a API Request. In this case I would use the setTenantMismatchMode(TenantMismatchModeCore.Ignore) and also the IgnoreQueryFilters() in the Arialis Spec to filter the Entities by the TenantId and ignore the global tenant filter.
I think Option 1 is the cleaner way, but i'm not sure how to register the Background Jobs in the Infrastructure Project while having the Business Logik in the Application Logic.
Or is there another prefered way to handle Reccuring Background Jobs which are registered during start up?
I'm using the Boilerplate with .NET 6.
Thanks for your Help!
Beta Was this translation helpful? Give feedback.
All reactions