IT教程 ·

给Hangfire的webjob增添callback和动态推断返回效果功能设计

 

背景引见

一般营业中须要用到定时实行功用,我用hangfire搭建了一个调理效劳,这个调理效劳是自力于营业逻辑的

也就是说只需我有了这个调理效劳后,只需供应给我的接口 我就可以调理它(比方在xx点xx分运转,或许每隔xx分运转,或许每周一8点运转等等)。

但是有一个问题,对方的接口是挪用胜利照样失利完整取决于对方的接口设想!

有的接口被设想成 要求的StatusCode 是200的是代表接口胜利,非200的代表接口失利。

有的接口被设想成返回的json构造有一个特定的字段来代表接口挪用胜利照样失利,比方:success字段。比方返回的构造也许这模样: {"success":false,"data":"xxxx"}

等等,这些都是case by case ,差别的写接口的人定的划定规矩大概不一样,经由过程webjob的挪用体式格局怎样动态的考证胜利照样失利呢?

如上面提到动态的考证效果,我分了2种状况处置惩罚:要么看Response返回的statuscode,要么是看返回的效果内里的指定字段来推断!

 

1. 依据Response返回的statuscode

statuscode很好做,我在设想Hangfire.HttpJob这个扩大插件时是可以在外部设置一个考证托付

默许的返回的statuscode 小于 400 则以为http要求是胜利的,不然失利

 

 

2. 返回的效果内里的指定字段来推断

我采纳EL表达式来完成的,EL表达式将要求的返回体设置为json变量,然后在表达式中可以直接以属性的体式格局到值,表达式返回布尔范例。

针对差别的接口,我可以设置一个自力的表达式来举行推断!

 

首先在job增加的时刻设置el表达式!如下图

给Hangfire的webjob增添callback和动态推断返回效果功能设计 IT教程 第1张

 

 

 

怎样写EL表达式:(很简单,返回的构造体是什么字段就可以用什么字段)

接口的返回体是一个string。我先将这个String转成json范例(dynamic)

然后是采纳Spring.EL表达式完成的。 CallbackEL表达式的返回范例是布尔范例

返回体在表达式内里是有下面2个变量:

  • #resultBody 是返回体的 string
  • #result 是返回体的 json体(依据上面转的,假如上面黑白json花样的那就不能运用这个变量了)

比方说我挪用的httpjob 返回体是

{"Success":false,"Info":"test"}

那末我可以这么写

"CallbackEL": "#result.Success"

也可以这么写

"CallbackEL": "#result.Info.Equals('ok')"

 

表达式怎样运转的?

Spring.EL是我从Spring.Net内里剥离出来的一个组件,可以从nuget内里援用,支撑net45和netstandard2.0

          //搜检是不是有设置EL表达式
                if (!string.IsNullOrEmpty(item.CallbackEL))
                {
                    var elResult = InvokeSpringElCondition(item.CallbackEL, result, context, new Dictionary<string, object> { { "resultBody", result } });
                    if (!elResult)
                    {
                        throw new HttpStatusCodeException(item.CallbackEL, result);
                    }
                    RunWithTry(() => context.WriteLine($"【{Strings.CallbackELExcuteResult}:Ok 】" + item.CallbackEL));
                }

 

       /// <summary>
        /// 用EL表达式动态推断是不是实行胜利
        /// </summary>
        /// <returns></returns>
        private static bool InvokeSpringElCondition(string placeholder,string result, PerformContext context,Dictionary<string, object> param)
        {
            try
            {
                try
                {
                    param["result"] = JsonConvert.DeserializeObject<ExpandoObject>(result);
                }
                catch (Exception)
                {
                    //ignore
                }

                var parameterValue = ExpressionEvaluator.GetValue(null, placeholder, param);
               
                return (bool)parameterValue;
            }
            catch (Exception e)
            {
                context.WriteLine($"【{Strings.CallbackELExcuteError}】" + placeholder);
                context.WriteLine(e);
                return false;
            }
        }

 


挪用对象 ExpressionEvaluator 传 Dictionary<string, object> param 作为参数,运用#参数来援用。假如你的参数是string 那末可以写c#中string的一切要领比方 StarsWith,EndsWith,Equals 等等
假如你的参数范例是一个dynamic,那你就可以直接像运用js的对象属性一样

Callback功用设想

举例:

我们挪用了A接口,假如A接口胜利我们想把A接口的返回值作为要求参数再去挪用B接口。

假如A接口失利在挪用C接口关照毛病!

 

参考ajax的callback设想

 

如上图 可以自行增加 Success 或许 Fail 作为回调

假如定义了Success 那末父job实行胜利没有报错则运转 Success回调

假如定义了Fail 那末父job实行失利 则运转 Fail回调

Success 内里还可以定义 Success 和 Fail

Fail 内里还可以定义 Success 和 Fail 如下图:

 

回调的Json参数

字段 申明
Url 要求Url
Method Post,Get
Data Post时可以填,支撑占位符(详细请看下面的引见)
ContentType application/json
Timeout 超时(毫秒)
BasicUserName basicauth用户名
BasicPassword basicauth暗码
AgentClass 基于jobAgent开发的httpjob须要填
Headers key:value 的jsonstring "{"key":,"value"}"

回调实行的逻辑

注重:回调不是作为新的的HangfireHttpJob实行的,是依附在最顶级的父Job的!

举例:

 

假如:JobA -》 Fail B -> Success BB

JobA自身实行毛病的话则会走重试逻辑(假如开启重试的话),重试到顶后 进入 Fail B, Fail B 实行胜利 则进入 Success BB。假如Success BB 实行胜利,那末 JobA 则以为是胜利的,不然以为失利!

假如:JobA -》 Fail B -> Fail BB

JobA自身实行毛病的话则会走重试逻辑(假如开启重试的话),重试到顶后 进入 Fail B, Fail B 实行失利 则进入 Fail BB 。Fail BB 实行失利,那末 JobA 以为失利!

Fail B 实行胜利 进入 Success C, Success C,实行胜利 以为 JobA 以为胜利,不然 Job A 以为失利!

总结:假如回调 则会根据设置的回调一起走下去,看末了一个回调是不是胜利。假如胜利 则以为悉数链路实行胜利,不然以为失利!

回调的代码完成是一个递归的体式格局挪用

给Hangfire的webjob增添callback和动态推断返回效果功能设计 IT教程 第2张

 

 

 

为了完成回调可以把上一个运转的效果最为参数,开发了占位符(placeholder)功用

也为了更好的扩大占位符功用,

首先要引见下 dashbord内里的 全局设置 功用 如下图:

  • 全局设置 :存储在当前目录下的 hangfire_global.json 文件(可以在StartUp代码修正HangfireHttpJobOptions.GlobalSettingJsonFilePath值指定其他地方

这个功用为了引见反复的设置,可以集合设置一些参数,然后给各个job去运用!

 

 

占位符功用采纳Spring.EL表达式完成的。

字符串中placeholder替代逻辑

  • 第一步:把字符串中的 ${xxx} 的xxx悉数替代成 全局设置内里的值
  • 第二步:把字符串中的 #{yyy} 的yyy悉数根据SpringEL表达式逻辑运转后的值举行替代

比方:上图中你在全局设置了一个参数叫test

Data:"你好呀:${test}"

在运转时会被替代成 =》    你好呀:1

比方:运用父job的返回值传给 callback

 

假如运转失利传给callback是报错信息

比方:运用时候替代

可以直接在 #{} 要领内里用DateTime这个变量 这个变量和c#一样的功用

比方

  • #{DateTime.Now} 代表运转时的当前时候+时分秒
  • #{DateTime.Today} 代表运转时的当天
  • #{DateTime.Today.AddDays(-1)} 代表运转时的昨天
  • #{DateTime.Today.AddDays(1)} 代表运转时的来日诰日

 

总结:

已异常灵活了,基于hangfire的中心调理功用,加上webjob的挪用体式格局,很轻易的把营业逻辑分离出来!

不论营业接口怎样写,基于EL表达式都可以正确的推断出来实行胜利照样失利,依据回调功用很轻易的实行链式挪用和毛病关照!

 

参与评论