[maliming] said: HangfireBackgroundWorkerManager
Hello maliming and thank you for you response I am using Abp 9.3.5 and the UI is Blazor WASM I tried to impalement your suggestion and overridden the HangfireBackgroundWorkerManager like this
namespace MyApp.BackgroundJobs;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IBackgroundWorkerManager),typeof(HangfireBackgroundWorkerManager))]
public class HangfireBackgroundWorkerManagerOverride : HangfireBackgroundWorkerManager, IBackgroundWorkerManager, ISingletonDependency
{
public HangfireBackgroundWorkerManagerOverride(IServiceProvider serviceProvider)
:base(serviceProvider)
{
}
public void Initialize()
{
BackgroundJobServer = ServiceProvider.GetRequiredService<AbpHangfireBackgroundJobServer>();
}
public async override Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default)
{
var abpHangfireOptions = ServiceProvider.GetRequiredService<IOptions<AbpHangfireOptions>>().Value;
var defaultQueuePrefix = abpHangfireOptions.DefaultQueuePrefix;
var defaultQueue = abpHangfireOptions.DefaultQueue;
switch (worker)
{
case IHangfireBackgroundWorker hangfireBackgroundWorker:
{
var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker);
RecurringJob.AddOrUpdate(
hangfireBackgroundWorker.RecurringJobId,
//hangfireBackgroundWorker.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + hangfireBackgroundWorker,
() => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken),
hangfireBackgroundWorker.CronExpression,
new RecurringJobOptions
{
TimeZone = hangfireBackgroundWorker.TimeZone
});
break;
}
case AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase:
{
int? period = null;
string? CronExpression = null;
if (worker is AsyncPeriodicBackgroundWorkerBase asyncPeriodicBackgroundWorkerBase)
{
period = asyncPeriodicBackgroundWorkerBase.Period;
CronExpression = asyncPeriodicBackgroundWorkerBase.CronExpression;
}
else if (worker is PeriodicBackgroundWorkerBase periodicBackgroundWorkerBase)
{
period = periodicBackgroundWorkerBase.Period;
CronExpression = periodicBackgroundWorkerBase.CronExpression;
}
if (period == null && CronExpression.IsNullOrWhiteSpace())
{
return;
}
var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker));
var workerAdapter = (Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker)!;
Expression<Func<Task>> methodCall = () => workerAdapter.DoWorkAsync(cancellationToken);
var recurringJobId = !workerAdapter.RecurringJobId.IsNullOrWhiteSpace() ? workerAdapter.RecurringJobId : GetRecurringJobId(worker, methodCall);
RecurringJob.AddOrUpdate(
recurringJobId,
//workerAdapter.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + workerAdapter,
methodCall,
CronExpression ?? GetCron(period!.Value),
new RecurringJobOptions
{
TimeZone = workerAdapter.TimeZone
});
break;
}
default:
await base.AddAsync(worker, cancellationToken);
break;
}
}
private readonly static MethodInfo? GetRecurringJobIdMethodInfo = typeof(RecurringJob).GetMethod("GetRecurringJobId", BindingFlags.NonPublic | BindingFlags.Static);
protected virtual string? GetRecurringJobId(IBackgroundWorker worker, Expression<Func<Task>> methodCall)
{
...
}
protected virtual string GetCron(int period)
{
...
}
}
commenting the Queue but HangfireBackgroundWorkerManagerOverride is never called and the error persists can you give me some guidance what I am doing wrong.
Thank you in advance
I am trying to use Hangfire as a Background Job manager with mysql:8.0 as persistence storage. I Use the nuget package "Hangfire.MySqlStorage" Version="2.0.3" to integrate with MySQL. I have the following configuration the the BlazorModule
private static void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddHangfire(config =>
{
config.UseStorage(
new MySqlStorage(
configuration.GetConnectionString("Default") ?? throw new InvalidOperationException("The [ConnectionString:Hangfire] is not configured."),
new MySqlStorageOptions()
)
);
});
context.Services.AddHangfireServer(o =>
{
//o.Queues = new[] { "default", "emails" }; // optional
o.ServerName = "vfsdbuploader-hf";
});
When I run the Process the tables are successfully created but the Process is terminated with the following Error
[13:18:26 FTL] Host terminated unexpectedly!
Volo.Abp.AbpInitializationException: An error occurred during the initialize Volo.Abp.Modularity.OnApplicationInitializationModuleLifecycleContributor phase of the module Volo.Abp.Identity.AbpIdentityProDomainModule, Volo.Abp.Identity.Pro.Domain, Version=9.3.5.0, Culture=neutral, PublicKeyToken=null: Current storage doesn't support specifying queues directly for a specific job. Please use the QueueAttribute instead.. See the inner exception for details.
---> System.NotSupportedException: Current storage doesn't support specifying queues directly for a specific job. Please use the QueueAttribute instead.
at Hangfire.RecurringJobManager.AddOrUpdate(String recurringJobId, Job job, String cronExpression, RecurringJobOptions options) in C:\projects\hangfire-525\src\Hangfire.Core\RecurringJobManager.cs:line 108
at Hangfire.RecurringJob.AddOrUpdate(String recurringJobId, String queue, Expression`1 methodCall, String cronExpression, RecurringJobOptions options) in C:\projects\hangfire-525\src\Hangfire.Core\RecurringJob.cs:line 568
at Volo.Abp.BackgroundWorkers.Hangfire.HangfireBackgroundWorkerManager.AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken)
at Volo.Abp.Identity.AbpIdentityProDomainModule.OnApplicationInitializationAsync(ApplicationInitializationContext context)
at Volo.Abp.Modularity.OnApplicationInitializationModuleLifecycleContributor.InitializeAsync(ApplicationInitializationContext context, IAbpModule module)
at Volo.Abp.Modularity.ModuleManager.InitializeModulesAsync(ApplicationInitializationContext context)
--- End of inner exception stack trace ---
at Volo.Abp.Modularity.ModuleManager.InitializeModulesAsync(ApplicationInitializationContext context)
at Volo.Abp.AbpApplicationBase.InitializeModulesAsync()
at Volo.Abp.AbpApplicationWithExternalServiceProvider.InitializeAsync(IServiceProvider serviceProvider)
at Microsoft.AspNetCore.Builder.AbpApplicationBuilderExtensions.InitializeApplicationAsync(IApplicationBuilder app)
at VfsDbUploader.Blazor.Program.Main(String[] args) in C:\Users\gpanagakis\Desktop\wc\vfs-db-uploader\src\VfsDbUploader.Blazor\Program.cs:line 66
I have no application specific Job or workers defined the problem is caused by internal ABP worker that are being initialized. When I run the same App using Redis as a Hangfire backend everything is initialized correctly and the following workers are started
[19:45:40 DBG] Started background worker: Volo.Abp.BackgroundJobs.BackgroundJobWorker
[19:45:40 DBG] Started background worker: Volo.Abp.Identity.Session.IdentitySessionCleanupBackgroundWorker
[19:45:40 DBG] Started background worker: Volo.Abp.OpenIddict.Tokens.TokenCleanupBackgroundWorker
[19:45:41 DBG] Started background worker: Volo.Abp.AuditLogging.ExpiredAuditLogDeleterWorker
[19:45:41 DBG] Started background worker: Volo.Abp.AuditLogging.ExcelFileDownload.ExcelFileCleanupWorker
I tried to use the suggestion "Please use the QueueAttribute " but the problem arises from ABP internal workers that are not under my control What is your suggestion to resolve the issue?
Thank you in advance