Open Closed

HANGFIRE WORKER/JOB REGISTRATION PROBLEMS ON ABP 8.2.0 #7551


User avatar
0
andrei.pislaru created

I wanted to upgrade our project to the new version (8.2.0 from 8.1) but then I encountered this problem when starting the application, the problem seems to be that the way jobs/workers id are registered is not correct anymore since of a limit to hangfire Ids i guess. The workers that causes the problem are the ones generated by ABP, specifically HangfirePeriodicBackgroundWorkerAdapter<BackgroundJobWorker>.DoWorkAsync and HangfirePeriodicBackgroundWorkerAdapter<TokenCleanupBackgroundWorker>.DoWorkAsync.

I had to override AddAsync of HangfireBackgroundWorkerManager ( still had to find a better way of handling ids ) also i hade to modify logic a bit since it was filled with obsolete methods of hangfire

//public override async Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default) //{ // switch (worker) // { // case IHangfireBackgroundWorker hangfireBackgroundWorker: // { // var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker);

// var jobId = string.IsNullOrEmpty(hangfireBackgroundWorker.RecurringJobId) ? hangfireBackgroundWorker.GetType().Name : hangfireBackgroundWorker.RecurringJobId; // var timezone = hangfireBackgroundWorker.TimeZone ?? TimeZoneInfo.Utc;

// RecurringJob.AddOrUpdate( // jobId, // hangfireBackgroundWorker.Queue, // () => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken), // hangfireBackgroundWorker.CronExpression, // new RecurringJobOptions // { // TimeZone = timezone // } // );

// break; // } // case AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase: // { // var timer = worker.GetType() // .GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);

// var period = worker is AsyncPeriodicBackgroundWorkerBase ? ((AbpAsyncTimer?)timer)?.Period : ((AbpTimer?)timer)?.Period;

// if (period == null) // { // return; // }

// var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker)); // var workerAdapter = (Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker)!;

// var jobId = string.IsNullOrEmpty(workerAdapter.RecurringJobId) ? workerAdapter.GetType().Name : workerAdapter.RecurringJobId; // var timezone = workerAdapter.TimeZone ?? TimeZoneInfo.Utc;

// RecurringJob.AddOrUpdate( // jobId, // workerAdapter.Queue, // () => workerAdapter.DoWorkAsync(cancellationToken), // GetCron(period.Value), // new RecurringJobOptions // { // TimeZone = timezone // } // ); // break; // } // default: // await base.AddAsync(worker, cancellationToken); // break; // }

//}

the below image shows the ids generated by abp ( they work in abp 8.1)

here are the versions i use for hangfire/background workers

  • ABP Framework version: v8.2.0
  • UI Type: Angular
  • Database System: EF Core (SQL Server )
  • Exception message and full stack trace:

[14:40:24 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=8.2.0.0, Culture=neutral, PublicKeyToken=null: String or binary data would be truncated in table 'sqldb-qq-dev.HangFire.Hash', column 'Key'. Truncated value: 'recurring-job:HangfirePeriodicBackgroundWorkerAdapter<IdentitySessionCleanupBackgroundWorker>.DoWork'.. See the inner exception for details. ---> Microsoft.Data.SqlClient.SqlException (0x80131904): String or binary data would be truncated in table 'sqldb-qq-dev.HangFire.Hash', column 'Key'. Truncated value: 'recurring-job:HangfirePeriodicBackgroundWorkerAdapter<IdentitySessionCleanupBackgroundWorker>.DoWork'. at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName) at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery() at Hangfire.SqlServer.SqlCommandBatch.ExecuteNonQuery() in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlCommandBatch.cs:line 122 at Hangfire.SqlServer.SqlServerWriteOnlyTransaction.<Commit>b__17_0(DbConnection connection, DbTransaction transaction) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerWriteOnlyTransaction.cs:line 100 at Hangfire.SqlServer.SqlServerStorage.<>c__DisplayClass41_0.<UseTransaction>b__0(DbConnection connection, DbTransaction transaction) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerStorage.cs:line 272 at Hangfire.SqlServer.SqlServerStorage.<>c__DisplayClass42_01.<UseTransaction>b__0(DbConnection connection) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerStorage.cs:line 319 at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](DbConnection dedicatedConnection, Func2 func) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerStorage.cs:line 257 at Hangfire.SqlServer.SqlServerStorage.UseTransaction[T](DbConnection dedicatedConnection, Func3 func, Nullable1 isolationLevel) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerStorage.cs:line 307 at Hangfire.SqlServer.SqlServerStorage.UseTransaction(DbConnection dedicatedConnection, Action2 action) in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerStorage.cs:line 270 at Hangfire.SqlServer.SqlServerWriteOnlyTransaction.Commit() in C:\projects\hangfire-525\src\Hangfire.SqlServer\SqlServerWriteOnlyTransaction.cs:line 69 at Hangfire.RecurringJobManager.AddOrUpdate(String recurringJobId, Job job, String cronExpression, RecurringJobOptions options) in C:\projects\hangfire-525\src\Hangfire.Core\RecurringJobManager.cs:line 148 at Hangfire.RecurringJobManagerExtensions.AddOrUpdate(IRecurringJobManager manager, String recurringJobId, Job job, String cronExpression, TimeZoneInfo timeZone, String queue) in C:\projects\hangfire-525\src\Hangfire.Core\RecurringJobManagerExtensions.cs:line 65 at Hangfire.RecurringJob.AddOrUpdate(Expression1 methodCall, String cronExpression, TimeZoneInfo timeZone, String queue) in C:\projects\hangfire-525\src\Hangfire.Core\RecurringJob.cs:line 379 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) ClientConnectionId:10a70a4f-4051-4c9b-bcde-e5e0c47734c6 Error Number:2628,State:1,Class:16 --- 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 Jeremias.QQ.Program.Main(String[] args) in C:\Users\AndreiIonutPislaru\source\repos\src\Jeremias.QQ.HttpApi.Host\Program.cs:line 64

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

3 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Fullstack Developer

    https://github.com/abpframework/abp/commits/b9ae57b38bbfe29837079be54bfab31b9949b55a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs

    The main logic has not changed in a year.

    This is not ABP problem, but Hangfire. you can try to change the field length

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    andrei.pislaru created

    https://github.com/abpframework/abp/commits/b9ae57b38bbfe29837079be54bfab31b9949b55a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs

    The main logic has not changed in a year.

    This is not ABP problem, but Hangfire. you can try to change the field length

    can you test with the versions i gave you in the screenshot?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    liangshiwei created
    Fullstack Developer

    Hi,

    I will fix it in the next patch version. You can try this

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IBackgroundWorkerManager), typeof(HangfireBackgroundWorkerManager))]
    public class MyHangfireBackgroundWorkerManager : HangfireBackgroundWorkerManager
    {
        public MyHangfireBackgroundWorkerManager(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    
        public override async Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default)
        {
            switch (worker)
            {
                case IHangfireBackgroundWorker hangfireBackgroundWorker:
                {
                    var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker);
                    if (hangfireBackgroundWorker.RecurringJobId.IsNullOrWhiteSpace())
                    {
                        RecurringJob.AddOrUpdate(
                            () => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken),
                            hangfireBackgroundWorker.CronExpression, hangfireBackgroundWorker.TimeZone,
                            hangfireBackgroundWorker.Queue);
                    }
                    else
                    {
                        RecurringJob.AddOrUpdate(hangfireBackgroundWorker.RecurringJobId,
                            () => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken),
                            hangfireBackgroundWorker.CronExpression, hangfireBackgroundWorker.TimeZone,
                            hangfireBackgroundWorker.Queue);
                    }
    
                    break;
                }
                case AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase:
                {
                    var timer = worker.GetType()
                        .GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);
    
                    var period = worker is AsyncPeriodicBackgroundWorkerBase
                        ? ((AbpAsyncTimer?)timer)?.Period
                        : ((AbpTimer?)timer)?.Period;
    
                    if (period == null)
                    {
                        return;
                    }
    
                    var unProxiedType = ProxyHelper.GetUnProxiedType(worker);
                    var adapterType =
                        typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(unProxiedType);
                    var workerAdapter = (Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker)!;
    
                    RecurringJob.AddOrUpdate(unProxiedType.Name, () => workerAdapter.DoWorkAsync(cancellationToken), GetCron(period.Value),
                        workerAdapter.TimeZone, workerAdapter.Queue);
    
                    break;
                }
                default:
                    await base.AddAsync(worker, cancellationToken);
                    break;
            }
        }
        
        protected override string GetCron(int period)
        {
            var time = TimeSpan.FromMilliseconds(period);
            string cron;
    
            if (time.TotalSeconds <= 59)
            {
                cron = $"*/{time.TotalSeconds} * * * * *";
            }
            else if (time.TotalMinutes <= 59)
            {
                cron = $"*/{time.TotalMinutes} * * * *";
            }
            else if (time.TotalHours <= 23)
            {
                cron = $"0 */{time.TotalHours} * * *";
            }
            else if(time.TotalDays <= 31)
            {
                cron = $"0 0 0 1/{time.TotalDays} * *";
            }
            else
            {
                throw new AbpException(
                    $"Cannot convert period: {period} to cron expression, use HangfireBackgroundWorkerBase to define worker");
            }
    
            return cron;
        }
    }
    
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 09, 2026, 11:56
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.