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.71k forks source link

Change storage at runtime #2388

Open Sonic198 opened 7 months ago

Sonic198 commented 7 months ago

Hello,

I'm trying to change storage at runtime. My intention is to remove a need of restarting application when user/password needs to be updated. I'm monitoring connection string in my appsettings.json file and whenever change occurs then IOptionsMonito.OnChange method is called, inside which I'm calling GlobalConfiguration.Configuration.UseMongoStorage(...). For testing purposes I was switching between databases (mongodb://localhost:27017/db --> mongodb://localhost:27017/db1) to see if that case would be also working. But even though hangfire collections are created in new DB it seem like hangfire server is still connecting to old DB as well as dashboard.

Is it even possible to change storage at runtime?

Here is my setup:

public static IServiceCollection AddHangfire(
    this IServiceCollection services,
    IConfiguration configuration)
{
    ParameterCheckHelper.NullCheck(() => services, () => configuration);

    services.AddSingleton<ITimeZoneResolver, TimeZoneResolver>();
    services.AddHangfireServer(x =>
    {
        x.WorkerCount = 1;
        x.Queues = "default";
    });

    services.AddHangfire((sp, config) =>
    {
        var storageOptions = new MongoStorageOptions
        {
            MigrationOptions = new MongoMigrationOptions
            {
                MigrationStrategy = new DropMongoMigrationStrategy(),
                BackupStrategy = new NoneMongoBackupStrategy()
            },
            CheckConnection = false
        };

        var mongoDB = sp.GetRequiredService<IMongoClientManager>();
        var connectionStringsMonitor = sp.GetRequiredService<IOptionsMonitor<ConnectionStrings>>();
        connectionStringsMonitor.OnChange(_ =>
        {
            //whenever conn str change occurs then new IMongoClient and IMongoDatabase is referenced from  IMongoClientManager
            GlobalConfiguration.Configuration.UseMongoStorage(mongoDB.Client, mongoDB.Database.DatabaseNamespace.DatabaseName, storageOptions);                
        });

        config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
            .UseSimpleAssemblyNameTypeSerializer()
            .UseRecommendedSerializerSettings()
            .UseMongoStorage(
                mongoDB.Client,
                mongoDB.Database.DatabaseNamespace.DatabaseName,
                storageOptions);

        config.UseSerilogLogProvider();
        config.UseFilter(new PreserveOriginalQueueAttribute());
    });

    GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 1 });

    return services;
}

...

public static IApplicationBuilder UseHangfire(this WebApplication app)
{
    ParameterCheckHelper.NullCheck(() => app);

    app.UseHangfireDashboard(
        "/hangfire",
        new DashboardOptions
        {
            IsReadOnlyFunc = _ => true,
            AppPath = "/swagger",
            TimeZoneResolver = app.Services.GetRequiredService<ITimeZoneResolver>(),
            Authorization = [new AllowAllAuthorizationFilter()]
        });

    return app;
}