Handle Exceptions from inside Hangfire

最后都变了- 提交于 2020-12-13 05:03:51

问题


I have a scenario, I am scheduling a BackgroundJob to run after some random seconds on application start. After the job is performed then I am again scheduling the same BackgroundJob to run after some random seconds and it goes on and never stops.

What I want is if any exception occurs in Hangfire during this continuous process I want to shut-down my asp.net core app.

for example, while this process is happening I stop the SQL Server. So hangfire giving this exception that is obvious

System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)

System.ComponentModel.Win32Exception: The system cannot find the file specified
--- End of inner exception stack trace ---
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.Open() at Hangfire.SqlServer.SqlServerStorage.CreateAndOpenConnection() at Hangfire.SqlServer.SqlServerStorage.UseConnection[T](Func`2 func) at Hangfire.SqlServer.SqlServerConnection.RemoveTimedOutServers(TimeSpan timeOut) at Hangfire.Server.ServerWatchdog.Execute(BackgroundProcessContext context) at Hangfire.Server.AutomaticRetryProcess.Execute(BackgroundProcessContext context)

So I don't know where to handle this exception, so that I can stop my application if this exception occurs.


回答1:


I think you have two choices:

  1. try catch in your method you call with Hangfire
  2. Use a IElectStateFilter, especially if you want to have the same behaviour for any Hangfire job

First option is pretty straightforward:

public void MyMethod() {
    try {
        //your code
    }
    catch(Exception ex) { 
        //stop application here
    }
}

BackgroundJob.Enqueue(() => MyMethod());

Second option goes like this:

  1. Create an attribute class:

    public class MyFilterAttribute : JobFilterAttribute, IServerFilter, IElectStateFilter 
    {
        public void OnStateElection(ElectStateContext context)
        {
            var failedState = context.CandidateState as FailedState;
            if (failedState != null)
            {
                //job has failed, stop application here
            }
        }
    }
    
  2. Register the filter:

    GlobalConfiguration.Configuration.UseFilter(new MyFilterAttribute());
    
  3. Add the attribute to your method

    [MyFilter]
    public void MyMethod() {
        //your code
    }
    
  4. Call your code as usual:

    BackgroundJob.Enqueue(() => MyMethod());        
    

See documentation regarding filters.




回答2:


If you register a custom IJobFilterProvider, you must include the GlobalFilters.Filters in the result of the GetFilters method. For example:

public virtual IEnumerable GetFilters(Job job)
{
    var result = GlobalJobFilters.Filters.AsEnumerable()
                 .Concat(new JobFilter[] {
                     new JobFilter(new QueueAttribute(GetQueueName(job)), 
                                   JobFilterScope.Method, null)
                 });
    return result;
}

That worked for me!




回答3:


I have solved the problem by checking is storage is attached to hangfire or not.

        try
        {
            IStorageConnection connection = JobStorage.Current.GetConnection();
            return true;
        }
        catch
        {
            return false;
        }


来源:https://stackoverflow.com/questions/42924624/handle-exceptions-from-inside-hangfire

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!