C# 重复作业异步调用WebApi,然后在回调方法中修改Hangfire作业的状态

C# 重复作业异步调用WebApi,然后在回调方法中修改Hangfire作业的状态,c#,callback,hangfire,C#,Callback,Hangfire,Hangfire 1.6.19 .net核心2.1 你好,, 当我在循环作业中调用WebApi时,由于调用超时,作业将失败,因此我使用异步方法进行调用,但这样,所有作业都成功执行,并且无法反映WebApi调用是否成功 所以我在异步请求的回调方法中判断。如果WebApi返回异常,则作业的状态将更改为失败 然而,我的修改导致Hangfire的失败工作列表无法正常工作。Hangfire是否提供了修改作业状态的内部方法,或者您是否有更好的解决方案 我的代码如下: [AutomaticRetry(

Hangfire 1.6.19 .net核心2.1

你好,, 当我在循环作业中调用WebApi时,由于调用超时,作业将失败,因此我使用异步方法进行调用,但这样,所有作业都成功执行,并且无法反映WebApi调用是否成功

所以我在异步请求的回调方法中判断。如果WebApi返回异常,则作业的状态将更改为失败

然而,我的修改导致Hangfire的失败工作列表无法正常工作。Hangfire是否提供了修改作业状态的内部方法,或者您是否有更好的解决方案

我的代码如下:

    [AutomaticRetry(Attempts = 0)]
    [DisplayName("InvokeApi,apiUrl:{0}")]
    public void InvokeApi(string apiUrl, PerformContext context)
    {
        var invocationData = InvocationData.Serialize(context.BackgroundJob.Job);
        int.TryParse(context?.BackgroundJob.Id, out var jobId);

        var client = new RestClient(apiUrl)
        {
            Timeout = -1,
            ReadWriteTimeout = -1
        };
        var request = new RestRequest(Method.GET)
        {
            Timeout = -1,
            ReadWriteTimeout = -1
        };

        client.ExecuteAsync(request, response =>
        {
            if (!response.IsSuccessful)
            {
                using (var dbContext = new HangfireContext())
                {
                    using (var transaction = dbContext.Database.BeginTransaction())
                    {
                        var state = dbContext.State.FirstOrDefault(x =>
                            x.JobId == jobId && x.Name == "Succeeded");
                        if (state != null)
                        {
                            state.Name = "Failed";
                            state.Reason = $"StatusDescription={response.StatusDescription},ErrorMessage={response.ErrorMessage ?? "null"}";
                        }

                        var job = dbContext.Job.FirstOrDefault(x => x.Id == jobId);
                        if (job != null)
                        {
                            job.StateName = "Failed";
                            job.InvocationData = Serialize(invocationData);
                        }

                        var counter =
                            dbContext.AggregatedCounter.FirstOrDefault(x => x.Key == "stats:succeeded");
                        if (counter != null) counter.Value = counter.Value - 1;

                        dbContext.SaveChanges();
                        transaction.Commit();
                    }
                }
            }
        });
    }

    public string Serialize(InvocationData invocationData)
    {
        var parameterTypes = JobHelper.FromJson<string[]>(invocationData.ParameterTypes);
        var arguments = JobHelper.FromJson<string[]>(invocationData.Arguments);

        return JobHelper.ToJson(new MyJobPayload
        {
            TypeName = invocationData.Type,
            MethodName = invocationData.Method,
            ParameterTypes = parameterTypes != null && parameterTypes.Length > 0 ? parameterTypes : null,
            Arguments = arguments != null && arguments.Length > 0 ? arguments : null
        });
    }


    public class MyJobPayload
    {
        [JsonProperty("type")]
        public string TypeName { get; set; }

        [JsonProperty("m")]
        public string MethodName { get; set; }

        [JsonProperty("p", NullValueHandling = NullValueHandling.Ignore)]
        public string[] ParameterTypes { get; set; }

        [JsonProperty("a", NullValueHandling = NullValueHandling.Ignore)]
        public string[] Arguments { get; set; }
    }
[自动重试(尝试次数=0)]
[DisplayName(“InvokeApi,apiUrl:{0}”)]
public void InvokeApi(字符串APIRL、PerformContext上下文)
{
var invocationData=invocationData.Serialize(context.BackgroundJob.Job);
int.TryParse(context?.BackgroundJob.Id,out var jobId);
var client=新的RestClient(apiUrl)
{
超时=-1,
ReadWriteTimeout=-1
};
var请求=新的重新请求(Method.GET)
{
超时=-1,
ReadWriteTimeout=-1
};
client.ExecuteAsync(请求、响应=>
{
如果(!response.issucessful)
{
使用(var dbContext=new hangfirecoxt())
{
使用(var transaction=dbContext.Database.BeginTransaction())
{
var state=dbContext.state.FirstOrDefault(x=>
x、 JobId==JobId&&x.Name==“成功”);
如果(状态!=null)
{
state.Name=“失败”;
state.Reason=$“StatusDescription={response.StatusDescription},ErrorMessage={response.ErrorMessage???“null”}”;
}
var job=dbContext.job.FirstOrDefault(x=>x.Id==jobId);
如果(作业!=null)
{
job.StateName=“失败”;
job.InvocationData=序列化(InvocationData);
}
变量计数器=
dbContext.AggregatedCounter.FirstOrDefault(x=>x.Key==“stats:successed”);
如果(counter!=null)counter.Value=counter.Value-1;
dbContext.SaveChanges();
Commit();
}
}
}
});
}
公共字符串序列化(调用数据调用数据)
{
var parameterTypes=JobHelper.FromJson(invocationData.parameterTypes);
var arguments=JobHelper.FromJson(invocationData.arguments);
返回JobHelper.ToJson(新的MyJobPayload
{
TypeName=invocationData.Type,
MethodName=invocationData.Method,
ParameterTypes=ParameterTypes!=null&&ParameterTypes.Length>0?ParameterTypes:null,
参数=参数!=null&&Arguments。长度>0?参数:null
});
}
公共类MyJobPayload
{
[JsonProperty(“类型”)]
公共字符串类型名{get;set;}
[JsonProperty(“m”)]
公共字符串MethodName{get;set;}
[JsonProperty(“p”,NullValueHandling=NullValueHandling.Ignore)]
公共字符串[]参数类型{get;set;}
[JsonProperty(“a”,NullValueHandling=NullValueHandling.Ignore)]
公共字符串[]参数{get;set;}
}

期待您的回复,谢谢

它终于成功了,但还有更好的方法吗

    [AutomaticRetry(Attempts = 0)]
    [DisplayName("InvokeApi,apiUrl:{0}")]
    public void InvokeApi(string apiUrl, PerformContext context)
    {
        var invocationData = InvocationData.Serialize(context.BackgroundJob.Job);
        int.TryParse(context?.BackgroundJob.Id, out var jobId);

        var dtBegin = DateTimeOffset.Now;
        var client = new RestClient(apiUrl)
        {
            Timeout = -1,
            ReadWriteTimeout = -1
        };
        var request = new RestRequest(Method.GET)
        {
            Timeout = -1,
            ReadWriteTimeout = -1
        };

        client.ExecuteAsync(request, response => {
            if (!response.IsSuccessful)
            {
                var responseMessage = $"TotalSeconds={DateTimeOffset.Now.Subtract(dtBegin).TotalSeconds},StatusDescription={response.StatusDescription},ErrorMessage={response.ErrorMessage ?? "null"}";

                try
                {
                    var strHangfireDataContext = EngineContext.Instance.ServiceProvider.GetService<ConnectionStringsConfiguration>().HangfireDataContext;
                    var optionsBuilder = new DbContextOptionsBuilder<HangfireContext>();
                    optionsBuilder.UseSqlServer(strHangfireDataContext);
                    using (var dbContext = new HangfireContext(optionsBuilder.Options))
                    {
                        using (var transaction = dbContext.Database.BeginTransaction())
                        {
                            var state = dbContext.State.FirstOrDefault(x =>
                                x.JobId == jobId && x.Name == "Succeeded");
                            if (state != null)
                            {
                                var failedState = new FailedState(new Exception(responseMessage));
                                state.Name = failedState.Name;
                                state.Reason = failedState.Reason;
                                state.Data = JobHelper.ToJson(failedState.SerializeData());
                            }

                            var job = dbContext.Job.FirstOrDefault(x => x.Id == jobId);
                            if (job != null)
                            {
                                job.StateName = "Failed";
                                job.InvocationData = JobHelper.ToJson(new
                                {
                                    Type = invocationData.Type,
                                    Method = invocationData.Method,
                                    ParameterTypes = invocationData.ParameterTypes,
                                    Arguments = invocationData.Arguments
                                });
                            }

                            var counter =
                                dbContext.AggregatedCounter.FirstOrDefault(x => x.Key == "stats:succeeded");
                            if (counter != null) counter.Value = counter.Value - 1;

                            dbContext.SaveChanges();
                            transaction.Commit();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError("Exception jobId:" + jobId + ";ex:" + ex.ToString());
                }
            }
        });
    }
[自动重试(尝试次数=0)]
[DisplayName(“InvokeApi,apiUrl:{0}”)]
public void InvokeApi(字符串APIRL、PerformContext上下文)
{
var invocationData=invocationData.Serialize(context.BackgroundJob.Job);
int.TryParse(context?.BackgroundJob.Id,out var jobId);
var dtBegin=DateTimeOffset.Now;
var client=新的RestClient(apiUrl)
{
超时=-1,
ReadWriteTimeout=-1
};
var请求=新的重新请求(Method.GET)
{
超时=-1,
ReadWriteTimeout=-1
};
client.ExecuteAsync(请求、响应=>{
如果(!response.issucessful)
{
var responseMessage=$“TotalSeconds={DateTimeOffset.Now.Subtract(dtBegin.TotalSeconds},StatusDescription={response.StatusDescription},ErrorMessage={response.ErrorMessage??“null”}”;
尝试
{
var strHangfireDataContext=EngineContext.Instance.ServiceProvider.GetService().HangfireDataContext;
var optionsBuilder=new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(strHangfireDataContext);
使用(var dbContext=new HangfireContext(optionsBuilder.Options))
{
使用(var transaction=dbContext.Database.BeginTransaction())
{
var state=dbContext.state.FirstOrDefault(x=>
x、 JobId==JobId&&x.Name==“成功”);
如果(状态!=null)
{
var failedState=新的failedState(新异常(响应消息));
state.Name=failedState.Name;
state.Reason=failedState.Reason;
state.Data=JobHelper.ToJson(failedState.SerializeData());
}
var job=dbContext.job.FirstOrDefault(x