得到終極回收算法之前過程,分享一下所經歷的過程
圖中B是多步發散並行活動,Z和K是並行聚合活動
經縝密思考總結如下規則:
我們先從最簡模型的單步退回着手分析:
單步退回:
規則1:B退回A
A的發散類型是:異或SplitXOR,執行:完成B,創建A活動實例。(這種情況占多數)
A的發散類型是SplitOR或SplitAnd,執行完成B,以A是基准尋找所有由A活動實例所產生的后繼路徑產生的正在進行中的活動實例。進行回收,創建A活動實例。
規則2:C3退回C2(並行區內向退回),執行:同理規則1。
規則3:C退回B(並行區內向區邊退回,執行:同理規則1。
規則4:Z退回C3(並行結束邊向並行區域內退回),我認為這是不合理的,因為Z退回了C3后Z需要等候D的到達才能聚合完成,而Z退回C3只產生C3的活動實例,所以這時候Z就永遠不會聚合了,導致流程死掉。所以聚合活動不可單步退回上一步。
跨步或任意退回:
規則5:C退回A,回收總規則:退回到哪一活動,就以那一活動為基准向后尋找所有由這一活動定義產生出去的活動實例為超點的所有后繼活動實例,取消正在進行中的活動實例。注意:防止死循環
引發命案:
假如是I退回A,根據回收總規則而會進行A活動后的所有活動實例進行回收,I在K0與K的並行區域內,此時K3路徑來向的活動實例並沒有被回收,這情況發生在I活動實例是由K2產生的。如果I實例是由H產生的而不存在命案。但如果是則K2產生的,命案就發生了。由此我們思考到總規則2:
總規則2:退回時只能退回到曾經走過的歷史軌跡。那么I退回A一定是曾經從A發出來的路徑,則從A開始向后面的所有活動實例回收不會有錯。
好像有了總規則2問題就解決了,看似解決了,還依然存在命案問題,原因是如果A走到I,然后I退回提單,提單向K1路徑下發直到I,那此時A來向路徑和K1來向路徑都是曾經走過的路徑,此時退回A命案問題還是和原來一樣。
由此又想到了總規則3.
總規則3:再加上以以I活動實例為基准點向所有前繼活動描述回收。但這樣只有K2前面的會被回收,K2后面的不會被回收。好像問題總是存在,不過能應用到這種情況的需求已經是相當少的了,沒有完美的解決方法,只有更好的解決方法,不妨就先到此為止。不考慮K2后面不會被回收的情況了。視為到此是邊界了。多數情況下即使有這樣的需求也可以通過流程的設計和需求協商解決。其實上圖中存在很多不合理的流程路徑設計。比如從A出發走到J,J向K聚合時就是一個不合理情況,因為K要等K3和J,而K3壓根沒有產生過實例,所以流程會死掉。
退回的定義
退回,在有的應用中叫“回退”。退回是中國特色的一種方式,經常也是隱性的,比如申請經費可能由於資料不足被退回來補充資料,像這樣的例子有非常多,也很常見。
退回是工作流參與者對自己“待辦任務”(實際是對工作項)的一種操作,即參與者主動回退待辦任務列表中的任務到已經執行過的人工節點。
回退的情況實際上是非常復雜的,有串行上的退回,也有並行內的退回,並行區內退回到並行區外,從分支退回到主干等,從主干退回到分支內,多重聚合的退回等。退回過程中會發生很多事情,也會可能導致重走路徑時產生重復路徑。
隱匿退回方式的支持力度也往往成為評價一個工作流引擎是否具有中國特色和引擎強弱的能重要批價指標。
下面我們依次來看看種情況的退回模型以及F2在這方面強大的支持力度的算法實現。
如下圖所示,有任務A到任務B 屬於正常發送,但從任務B到任務A,則出現兩種情況:
(1)遷移退回:正常發送,如圖中B—A黑色線;(遷移的退回嚴格上沒有退回的意義存在,只是一種表象,與正常向后續節點遷移沒有區別,所以遷移式的退回不是本節討論的重點)
(2)被退回:(也稱隱匿退回,流程圖中不存在線)可能因為某些特殊原因,被任務B退回,要求任務A重新辦理,如圖中B—A紅色線。雖然都是從B到A,代表的意義卻完全不同。(本章所討論的退回模型都是討論這種情況)
隱式退回類型有以下四種類型
1 僅可退回到提單
2 僅可退回到上一步
3 僅可退回到上一步或提單
4 退回任意歷史步驟
串型退回模型分析
這種情況最為簡單,后續節點可以回退到前續任意人工步驟節點。回退后,節點重走。
(實際中沒有退回線,這里是為了使用圖表述說明清晰特意標上了線,本文中后面也是如此)
異或分支退回模型分析
這種情況也相對簡單,實際執行的分支上的節點可以回退到前續任意人工節點(不區分主支和分支)。同樣,主支上的節點也可以回退到任意實際執行的分支上的節點。
可能的問題:多次回退后的回退節點選擇。例如:第一次流程經過節點2、節點3到達節點5,節點5可以回退到節點1、節點2和節點3的任意一個,此時節點5回退到節點1,節點1重走,這一次流程改為經過節點4到達節點5,節點5回退時如何選擇回退節點?F2有退回回收器,當節點5退回到節點1時,會回收至節點1曾經走過的路徑,這樣此時節點5只允許回退到節點4和節點1,不允許回退到節點2和節點3。(因為節點2節點3的歷史路徑已被回收)
並發(或多重發散)退回模型分析
圖示使用F2純Web\JS流程設計器拖拉拽設計而成。
這個流程圖相對有點復雜,我們看來來F2所支持的回退情況:
1、 退回1
C2退回C,顯然這是並行分支間的退回,相對簡單。也沒有什么好說的。
2、 退回2
C3退回B,這是並行分支間退回到並行發散開始節點,此時需要回收D路徑上的分支,並取消這分支上所有產生的任務,對於C路徑上已走過的任務需要進行實例遷移的回收。
這種模式很多工作流引擎都不支持,多數引擎只能支持分支內部的退回即“退回1”所講的情況,至於分支內退回到並發開始或者並發節點之前的節點多數不支持,原因實際上的實現比較復雜遠遠比上面的圖示例子要復雜多了。
對於F2來說,只要調用回收器就能智能回收其因退回需要回收的路徑及任務,F2有站良好的軌跡跟蹤。當C3退回B時不單單要回收B=》C=》C2,還要回收B=》 D,還有B=》E=》F, F后面還有很多等等。
從E出來后面可能還更復雜,因為這些我們沒有全部能畫出來,但實際要支持C3退回B就必須支持因退回而對其它分支產生的影響。所以回收器是必須准確進行回收。
有這退回的支持,也表示后面幾種復雜的退回模型也將得到支持。后面會詳細說明回收器的回收算法,本人經過N多種情況的精心思考,在此也感謝園子里“路過秋天”的提示,讓原來很復雜的算法變得簡單很多。才有這這退回回收器的終極利器。
3、 退回3
C退回A,這是從並行聚合環節退回到並行開始節點之前,與退回2的情況類似。
4、 退回4
Z退回A,這是從並行分支退回到並行開始節點之前,與退回2的情況類似,只是要多回收一個路徑A到B這節路徑也得回收。
5、 退回7
O退回B,這是從並行聚合之后的節點退回到並行開始節點,最終也是要進行歷史軌跡路徑的回收,交由回收器回收。
6、 退回6
O退回C3,這是從並行聚合之后的節點退回到並行分支間節點,這種退回實際是不合理的,因為這會導致聚合節點Z會永遠等不來D,導致流程卡死。所以這種退回不合法,故也不支持。
終極利器-工作流引擎退回回收分支算法
算法內容:從節點9(假設其個節點)退回到節點1(假設其個節點)的退回時,從節點9尋找軌跡前繼,如果是異或節點而直接回收,然后繼續尋找前續實例,凡遇到並行發散或多重發散而以此並行或多重發散節點向后續活動實例回收軌跡實例,回收完之后繼續向前,直到節點1或者提單節點為止。
算法舉例說明:
如上圖中,退回算法是適合於任何節點退回到另一個節點的,我們找個復雜一些節點退回,比如從O退回A,那么回收器的執行過程是:
首先以O活動實例為開始向前尋找走過的實例軌跡,回收Z=》O遷移實例,判斷Z的節點類型,此時Z為異或發散類型,而直接回收Z活動實例,再從Z向前找到
C3=>C2=>C=>B和D=>B那么這些活動都會被直接回收,因為C C2 C3 D都是異或發散類型,所以不會有多個后續實例存在,進行直接回收,這里當來到B時,發現B是並行發散類型,這時回收器會轉向從B開始向后搜索,會搜索到B=>E=>F=>H=>I=>A=>B(搜索到自己會結束,避免死循環),這里搜索器會智能發現B=>C2=>C3=>Z和B=>D=>Z已經被回收過了所以不處理。此時回收掉了B=>E=>F=>H=>I=>A=>B,最后回收B活動實例,然后繼續找B的前繼找到了A,此時回收A=》B的遷移實例,最后判斷已經是A目標要退回的環節了,回收結束退出。
應用上面的算法依此類推,無論多復雜的情況這算法都能解決因退回而引起需要撤消取消的其它路徑的問題。還可以解決更多的問題,如下面的引申應用。
另外因聚合完畢的回收:
此算法做一些終止開關判斷就可應用到多重聚合時的回收,比如Z是多重聚合,條件是只要有一條分支到達就聚合完成,那么舉例B同時發給了C和 D那當D先到這Z時,C路徑上的還停留在C2,那么這時會因D的到達需要回收C=》=》C2。假設C2又是一個發散節點也不成問題,回收器會自動回收因C2產生出去的實例活動節點。直到尋找到一個並行或多重發散節點為止。
另外因結束完畢的回收:
假設有路徑從A=>B=>E=>F=>H=>I=>J=>結束由J走向結束時,因為結束發生引擎O路徑來向的活動軌跡需要回收,應用回收器進行回收,此時發現有一段重疊的軌跡,即A=》B,那么這段路徑不應該被回收。而B到O之間的段的軌跡實例需要被回收。
關於業務補償
業務補償是一個很重要的概念,在回退的情況下需要相應的回退部分業務操作。
這里由引擎提供統一的接口,返回回退路徑,由客戶自定義代碼進行匹配處理。
關於實現
很多工作流引擎通過流程定義時繪出回退遷移線來顯式的支持回退,即使用遷移的方式來作為回退,實際這種不叫回退,只是用遷移發向前發送,
只是這種發送是之前的環節而已,這種實現在業務復雜的情況下會造成流程圖的異常煩瑣(將有非常多的雜線),
但是比較清晰,實現比較容易與向后續環節遷移沒有區別。 隱式實現相比而言優點更多,也更符合中國特色和中國人的思維習慣,
也顯得引擎對回退的支持力度更強大。
這也是評價一個工作流引擎是否靈活強大的重要指標。