* Consolidate tenant task lifecycle logic into `TenantTaskManager` and remove obsolete task event handlers (`RunStartupTasks`, `RunBackgroundTasks`, `StartRecurringTasks`). Introduce `TopologicalTaskSorter` for dependency-based task execution. * Handles multiple tasks of the same type Updates the topological task sorter to handle multiple tasks of the same type. Previously, the sorter assumed a one-to-one mapping between task types and task instances, which caused issues when multiple tasks of the same type were present. Now, it groups tasks by type and adds them to the result in the correct order. * Add unit tests for `TopologicalTaskSorter` Introduce `Elsa.Common.UnitTests` project with comprehensive test coverage for `TopologicalTaskSorter`, including dependency resolution, circular dependency handling, and task ordering scenarios. Update `Elsa.sln` to include the new test project. * Update src/modules/Elsa.Common/Multitenancy/EventHandlers/TenantTaskManager.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Unwrap background task continuation in `TenantTaskManager` to ensure proper task execution tracking. * Update src/modules/Elsa.Common/Helpers/TopologicalTaskSorter.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Refactor `TryGet` method to prioritize memory register lookup and update `Output` constructor to use `MemoryBlockReference`. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
56 lines
2.2 KiB
C#
56 lines
2.2 KiB
C#
using Elsa.Common.Multitenancy;
|
|
using Elsa.Common.Multitenancy.EventHandlers;
|
|
using Elsa.Common.Multitenancy.HostedServices;
|
|
using Elsa.Common.RecurringTasks;
|
|
using Elsa.Features.Abstractions;
|
|
using Elsa.Features.Services;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
|
|
namespace Elsa.Common.Features;
|
|
|
|
public class MultitenancyFeature(IModule module) : FeatureBase(module)
|
|
{
|
|
private Func<IServiceProvider, ITenantsProvider> _tenantsProviderFactory = sp => sp.GetRequiredService<DefaultTenantsProvider>();
|
|
|
|
public MultitenancyFeature UseTenantsProvider<TTenantsProvider>() where TTenantsProvider : class, ITenantsProvider
|
|
{
|
|
Services.TryAddScoped<TTenantsProvider>();
|
|
return UseTenantsProvider(sp => sp.GetRequiredService<TTenantsProvider>());
|
|
}
|
|
|
|
public MultitenancyFeature UseTenantsProvider(Func<IServiceProvider, ITenantsProvider> tenantsProviderFactory)
|
|
{
|
|
_tenantsProviderFactory = tenantsProviderFactory;
|
|
return this;
|
|
}
|
|
|
|
public override void ConfigureHostedServices()
|
|
{
|
|
Module
|
|
.ConfigureHostedService<ActivateTenants>(-1)
|
|
;
|
|
}
|
|
|
|
public override void Apply()
|
|
{
|
|
Services
|
|
.AddSingleton<ITenantScopeFactory, DefaultTenantScopeFactory>()
|
|
.AddSingleton<ITenantAccessor, DefaultTenantAccessor>()
|
|
.AddSingleton<ITenantFinder, DefaultTenantFinder>()
|
|
.AddSingleton<ITenantService, DefaultTenantService>()
|
|
|
|
// TenantTaskManager handles all task lifecycle in the correct order
|
|
.AddSingleton<TenantTaskManager>()
|
|
.AddSingleton<ITenantActivatedEvent>(sp => sp.GetRequiredService<TenantTaskManager>())
|
|
.AddSingleton<ITenantDeactivatedEvent>(sp => sp.GetRequiredService<TenantTaskManager>())
|
|
|
|
.AddSingleton<RecurringTaskScheduleManager>()
|
|
.AddSingleton<TenantEventsManager>()
|
|
.AddScoped<DefaultTenantsProvider>()
|
|
.AddScoped<DefaultTenantResolver>()
|
|
.AddScoped<ITaskExecutor, TaskExecutor>()
|
|
.AddScoped<IBackgroundTaskStarter, TaskExecutor>()
|
|
.AddScoped(_tenantsProviderFactory);
|
|
}
|
|
} |