给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表达式!如下图
怎样写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 以为失利!
总结:假如回调 则会根据设置的回调一起走下去,看末了一个回调是不是胜利。假如胜利 则以为悉数链路实行胜利,不然以为失利!
回调的代码完成是一个递归的体式格局挪用
为了完成回调可以把上一个运转的效果最为参数,开发了占位符(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表达式都可以正确的推断出来实行胜利照样失利,依据回调功用很轻易的实行链式挪用和毛病关照!