一般業務中須要用到定時執行功能,我用hangfire搭建了一個調度服務,這個調度服務是獨立於業務邏輯的,具體能夠參考文章:https://github.com/yuzd/Hangfire.HttpJob/wikigit
也就是說只要我有了這個調度服務後,只要提供給個人接口 我就能夠調度它(好比在xx點xx分運行,或者每隔xx分運行,或者每週一8點運行等等)。github
可是有一個問題,對方的接口是調用成功仍是失敗徹底取決於對方的接口設計!web
有的接口被設計成 請求的StatusCode 是200的是表明接口成功,非200的表明接口失敗。ajax
有的接口被設計成返回的json結構有一個特定的字段來表明接口調用成功仍是失敗,例如:success字段。好比返回的結構大概這樣子: {"success":false,"data":"xxxx"}json
等等,這些都是case by case ,不一樣的寫接口的人定的規則可能不同,經過webjob的調用方式如何動態的驗證成功仍是失敗呢?c#
如上面提到動態的驗證結果,我分了2種狀況處理:要麼看Response返回的statuscode,要麼是看返回的結果裏面的指定字段來判斷!app
statuscode很好作,我在設計Hangfire.HttpJob這個擴展插件時是能夠在外部設置一個驗證委託lua
默認的返回的statuscode 小於 400 則認爲http請求是成功的,不然失敗spa
我採用EL表達式來實現的,EL表達式將請求的返回體設置爲json變量,而後在表達式中能夠直接以屬性的方式到值,表達式返回布爾類型。插件
針對不一樣的接口,我能夠設置一個獨立的表達式來進行判斷!
首先在job添加的時候設置el表達式!以下圖
如何寫EL表達式:(很簡單,返回的結構體是什麼字段就能夠用什麼字段)
接口的返回體是一個string。我先將這個String轉成json類型(dynamic)
而後是採用Spring.EL表達式實現的。 CallbackEL表達式的返回類型是布爾類型
返回體在表達式裏面是有下面2個變量:
好比說我調用的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的對象屬性同樣
舉例:
咱們調用了A接口,若是A接口成功咱們想把A接口的返回值做爲請求參數再去調用B接口。
若是A接口失敗在調用C接口通知錯誤!
參考ajax的callback設計
若是定義了Success 那麼父job執行成功沒有報錯則運行 Success回調
若是定義了Fail 那麼父job執行失敗 則運行 Fail回調
Success 裏面還能夠定義 Success 和 Fail
Fail 裏面還能夠定義 Success 和 Fail 以下圖:
字段 | 說明 |
---|---|
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, Fail B 執行成功 則進入 Success BB。若是Success BB 執行成功,那麼 JobA 則認爲是成功的,不然認爲失敗!
JobA自己執行錯誤的話則會走重試邏輯(若是開啓重試的話),重試到頂後 進入 Fail B, Fail B 執行失敗 則進入 Fail BB 。Fail BB 執行失敗,那麼 JobA 認爲失敗!
Fail B 執行成功 進入 Success C, Success C,執行成功 認爲 JobA 認爲成功,不然 Job A 認爲失敗!
也爲了更好的擴展佔位符功能,
首先要介紹下 dashbord裏面的 全局配置 功能 以下圖:
這個功能爲了介紹重複的配置,能夠集中配置一些參數,而後給各個job去使用!
佔位符功能採用Spring.EL表達式實現的。
字符串中placeholder替換邏輯
Data:"你好呀:${test}"
在運行時會被替換成 =》 你好呀:1
若是運行失敗傳給callback是報錯信息
能夠直接在 #{} 方法裏面用DateTime這個變量 這個變量和c#同樣的功能
好比