關於狀態機工做流的編程方法

還沒想好怎麼寫,先起了個古怪的名字。好吧,這篇文章純屬拔草之做,只講一種大概的解決方案。
不過,咱們大概得先解決掉兩個概念:一個是狀態機,一個是工做流。
什麼是狀態機?大概來講,就是我這裏有一堆的狀態,我在進行一項工做的時候,有一系列的狀態;我要從一個狀態轉移到另外一個狀態。舉個最簡單的栗子:好比一個燈泡,有「開着」和「關着」兩種狀態。我對這個燈泡的操做是扳動開關,燈「開着」的時候,我按關燈,就到「關着」的狀態;若是我再按開燈,就到了「開着」的狀態。用狀態轉移圖來表示大概是這樣的:
什麼是工做流?所謂工做流,就是有必定的步驟和順序,須要按順序進行的工做。假設在工做中,咱們有一個研究課題,須要公司給予必定經費上的支持,可是公司也無法保證這個研究的可行性、是否符合公司的戰略目標、是否合法、是否在公司的財務預算以內等等一系列問題,須要A、B、C、D四我的審批,A審批經過後交給B,B經過交給C,C經過交給D,D經過纔算徹底經過。若是有其中某一個不經過的,就要從頭再來過。
那麼狀態機工做流就比較好理解了,就是把狀態機和工做流結合在一塊兒。還用上面那個審批的栗子,咱們能夠畫出這樣一個狀態轉移圖:
OK,那麼常規思路怎麼作呢?
 
def approve():
    if A經過:
        if B經過:
            if C經過:
                if D經過:
                    return 經過
    return 不經過

 

用腳後跟想一想也知道,這樣是行不通的。若是A審批經過,B不在線,不能立刻經過怎麼辦?開個線程阻塞掉?若是C審批完了,服務器忽然宕機怎麼辦?前面的審批全都要重來一遍?咱們這個審批流程已是很是簡單明確了,若是狀態機再複雜一些……
對不起,代碼不是這麼堆的。
 
那麼,個人思路是這樣的:
既然最重要的是狀態轉移,那咱們不妨把工做流中的每一個狀態保存起來,做爲一個步驟。咱們能夠在數據庫中單獨增長一個表示狀態的字段。好比,當狀態爲1的時候,表示「須要A審批」,狀態爲2的時候,表示「須要B審批」等等。表示審批的函數固然也很簡單:
 
def approve():
    if agree:
        status += 1
    else:
        status = 0
    return status

 

接下來的工做,可能要看具體屬於哪一類型的工做流。
若是是審批這種,固然再簡單不過了,須要B審批了,咱們就把數據庫中狀態爲2的那些數據拿出來就行了。
有些類型不是靠前端展現的,而是後端執行的一系列動做,這樣會複雜一些。若是對時間的要求不是特別高,能夠用定時任務來處理。好比,咱們把ABCD四個審批者換成ABCD四個環節,那麼,咱們每隔一段時間,選取數據庫中還沒有完成的任務,狀態爲1的任務進行A環節,狀態爲2的任務進行B環節,等等。
定時任務嘛,若是很簡單,能夠用schedule庫,複雜一點的任務仍是推薦celery——由於celery會給任務分配單獨的任務隊列和線程,操做起來比schedule要方便得多。並且須要定好大概得時間,以避免任務太多,產生堆積。schedule我在以前的博文中介紹過,celery相對比較複雜,我如今也只會用其中的一部分。網上有比較完整的celery使用方法的文章,官網的介紹也是比較全面的,須要用到什麼去查就行了。
相關文章
相關標籤/搜索