从 Hangfire 内部处理异常

Handle Exceptions from inside Hangfire

我有一个场景,我在应用程序启动的随机秒数后将 BackgroundJob 安排到 运行。执行作业后,我再次将相同的 BackgroundJob 安排到 运行 随机几秒钟后,它继续并且永不停止。

我想要的是,如果在此连续过程中 Hangfire 发生任何异常,我想关闭我的 asp.net 核心应用程序。

例如,当这个过程发生时,我停止了 SQL 服务器。所以 hangfire 给出了这个明显的异常

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)

所以我不知道去哪里处理这个异常,这样如果出现这个异常我可以停止我的应用程序。

我想你有两个选择:

  1. try catch 在你用 Hangfire 调用的方法中
  2. 使用 IElectStateFilter,特别是如果您希望任何 Hangfire 作业具有相同的行为

第一个选项非常简单:

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

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

第二个选项是这样的:

  1. 创建属性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. 注册过滤器:

    GlobalConfiguration.Configuration.UseFilter(new MyFilterAttribute());
    
  3. 将属性添加到您的方法

    [MyFilter]
    public void MyMethod() {
        //your code
    }
    
  4. 照常调用您的代码:

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

有关过滤器的信息,请参阅 documentation

如果注册自定义 IJobFilterProvider,则必须在 GetFilters 方法的结果中包含 GlobalFilters.Filters。例如:

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;
}

这对我有用!

我已经通过检查存储是否附加到 hangfire 解决了问题。

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