Hangfire Discussion

Change SQL connection string while Dashboard is running

sql-server
dashboard
Tags: #<Tag:0x00007f85034b44e0> #<Tag:0x00007f85034b4300>

#1

I am using a system that rotates SQL logins. I have middleware setup to do this. This is an MVC .net core 2.1 project that only exists to use the Dashboard. There is a separate Hangfire service project that executes background jobs. When the SQL login changes, I’ve tried to update the connection string with both or either of these:

JobStorage.Current = new SqlServerStorage(connectionStr);
and
GlobalConfiguration.Configuration.UseSqlServerStorage(connectionString);

The dashboard still retains the initial connection string using during startup. Am I missing something here? Is there a way to do this without shutting down the Dashboard service or Hangfire?

Thanks


#2

Do you know these connection strings at startup time? If so, you should be able to add multiple dashboards to different routes with different storage using the overload here.
I’m fairly certain I’ve been able to call this signature of UseHangfireDashboard with a different path and storage before. Hopefully this will eventually become a full-fledge feature one day.


#3

Thanks for responding.

I do not know them at startup. I’m using Hashicoop Vault to rotate Sql logins, so the server and database name do not change, just the login, which will expire at some point.


#4

I figured out a solution. I created a new JobStorage class that holds a SqlServerStorage JobStorage. It returns everything the SqlServerStorage class returns but gives me the ability to replace it with a new one if my sql credentials change. This works great for my MVC site that only exists to show the dashboard. I have need to do some testing to see how this reacts if I update the connection string credentials while background tasks are running.

public class SqlServerStorageRotating : Hangfire.JobStorage
{
	private SqlServerStorage _sqlServerStorage;
	private readonly SqlServerStorageOptions _options;
	public SqlServerStorageRotating(string nameOrConnectionString)
	{
		_options = new SqlServerStorageOptions();
		_sqlServerStorage = new SqlServerStorage(nameOrConnectionString, _options);
	}
	public SqlServerStorageRotating(string nameOrConnectionString, SqlServerStorageOptions options)
	{
		_options = options;
		_sqlServerStorage = new SqlServerStorage(nameOrConnectionString, _options);
	}

	public void UpdateConnectionString(string nameOrConnectionString)
	{
		_sqlServerStorage = new SqlServerStorage(nameOrConnectionString, _options);
	}
	public PersistentJobQueueProviderCollection QueueProviders
	{
		get { return _sqlServerStorage.QueueProviders; }
	}

	public override IMonitoringApi GetMonitoringApi()
	{
		return _sqlServerStorage.GetMonitoringApi();
	}

	public override IStorageConnection GetConnection()
	{
		return _sqlServerStorage.GetConnection();
	}

#pragma warning disable 618
	public override IEnumerable<IServerComponent> GetComponents()
	{
		return _sqlServerStorage.GetComponents();
	}
#pragma warning restore 618

	public override IEnumerable<IStateHandler> GetStateHandlers()
	{
		return _sqlServerStorage.GetStateHandlers();
	}

	public override void WriteOptionsToLog(ILog logger)
	{
		_sqlServerStorage.WriteOptionsToLog(logger);
	}
}