HangfireIO / Hangfire

An easy way to perform background job processing in .NET and .NET Core applications. No Windows Service or separate process required
https://www.hangfire.io
Other
9.43k stars 1.7k forks source link

Type Loading Exception in Recurring Job #2469

Open devbaran opened 2 days ago

devbaran commented 2 days ago

I'm experiencing a TypeLoadException with a recurring job in Hangfire. The job works fine when triggered manually, but after some time, it fails in the recurring jobs tab with a type loading error.

System.InvalidOperationException: Recurring job can't be scheduled, see inner exception for details.
 ---> Hangfire.Common.JobLoadException: Could not load the job. See inner exception for the details.
 ---> System.TypeLoadException: Could not load type 'xMessagingAPI.Hangfire.Abstract.Jobs.ICalculateTotalSpendingsJob' from assembly 'xMessagingAPI.Hangfire, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
   at System.Reflection.RuntimeAssembly.<GetType>g____PInvoke|26_0(QCallAssembly assembly, UInt16* name, Int32 throwOnError, Int32 ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext)

Job Registration

services.AddScoped<ICalculateTotalSpendingsJob, CalculateTotalSpendingsJob>();
RecurringJob.AddOrUpdate<ICalculateTotalSpendingsJob>("calculate-total-spendings", x => x.RunAsync(), Cron.Minutely );

Hangfire Registration

        services.AddHangfire((provider, configuration) =>
        {
            configuration.UseRedisStorage(redis, redisStrogeOptions)
                .WithJobExpirationTimeout(TimeSpan.FromDays(30))
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings();
        });
        JobStorage.Current = new RedisStorage(redis, redisStrogeOptions);

        services.AddHangfireServer(configuration =>
        {
            configuration.WorkerCount = 1;
            configuration.Queues = new[]
            {
                "calculate-spendings", "sync-spendings-with-x", "set-new-balance", "sync-balances-from-x", "spend"
            };
        });

Interface Definition

public interface ICalculateTotalSpendingsJob
{
    [AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Fail)]
    [Queue("calculate-spendings")]
    [JobDisplayName("Calculate Spendings Job")]
    [DisableConcurrentExecution(60)]
    public Task RunAsync();
}

Implementation

public class CalculateTotalSpendingsJob : ICalculateTotalSpendingsJob
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly IMessageReadRepository _messageReadRepository;
    private readonly IMessageWriteRepository _messageWriteRepository;
    private readonly IUserService _userService;
    private readonly IJobQueueService _jobQueueService;
    private readonly IBalanceService _balanceService;

    public CalculateTotalSpendingsJob(IUnitOfWork unitOfWork, 
        IMessageWriteRepository messageWriteRepository, 
        IMessageReadRepository messageReadRepository, 
        IUserService userService, 
        IJobQueueService jobQueueService, 
        IBalanceService balanceService)
    {
        _unitOfWork = unitOfWork;
        _messageWriteRepository = messageWriteRepository;
        _messageReadRepository = messageReadRepository;
        _userService = userService;
        _jobQueueService = jobQueueService;
        _balanceService = balanceService;
    }

    public async Task RunAsync()
    {
        Console.WriteLine("OK-calculate");
        return;
    }
}

Expected Behavior:

Actual Behavior:

Things I've Already Tried:

Environment

775728212 commented 2 days ago

同样的问题 本地没有问题 生产 iis有这个问题