基于Webpy實現服務器策略模型
現在我們來談一些(黑)科技,希望能給大家一些啟發和幫助。現在我有一個策略文件addition.policy:
acquire: first_str -> a apply: concat_with_time(a) -> a acquire: first_str -> b apply: concat_with_time(b) -> bawait: return_result apply: join_line(a, b) -> result yield: result</pre>
還有一個委托函數的Python源碼addition.delegate.py:
# addition.delegate.pyimport time
def concat_with_time(s): return s + time.ctime()
def join_line(s1, s2): return s1 + "\n" + s2 + "\n"</pre>
這是什么語法?但是我們大抵都能明白它想干什么:先后獲取兩個字符串,分別將它們和時間拼接在一起,然后在獲取return_result后回傳結果。然后呢?然后我們有一些Web接口,簡單地用web.py編寫main.py:
#!/usr/bin/env python import web from policy import resume class first_str_view: def GET(self): resume("addition", "first_str", value = web.input()["value"]) return "" class second_str_view: def GET(self): resume("addition", "second_str", value = web.input()["value"]) return "" class return_result_view: def GET(self): return resume("addition", "return_result") urls = [ '/first_str/?', first_str_view, '/second_str/?', second_str_view, '/return_result/?', return_result_view, ] if __name__ == "__main__": app = web.application(urls, globals()) app.run()就算沒用過web.py的人都大抵能明白這個結構是什么意思了,除了那個resume有點不知所謂之外,但是結合上面的那個addition.policy,好像看上去也挺合理,大概就是從acquire處斷開,然后得到輸入后繼續執行那個policy。如你所料:
$ ./main.py 9999 & [1] 19121 http://0.0.0.0:9999/ $ curl "http://localhost:9999/first_str?value=First+Record+" $ curl "http://localhost:9999/second_str?value=Second+Record+" $ curl "http://localhost:9999/return_result" First Record Sat Sep 5 15:59:25 2015 Second Record Sat Sep 5 15:59:28 2015這樣可以解決很多問題。比如在用戶更變郵箱的時候,用戶先提交新郵箱,然后還要等等他什么時候去郵箱里收驗證郵件,這樣更變郵箱的操作才完成。還有一些更麻煩的操作,整個流程下來,要收幾次輸入,然后才能真正地輸入成功存進數據庫。舉個例子,你可以簡單地寫一個策略文件,讓它控制整個流程,接口只需要跟用戶打交道就好了:
assert: is_authenticated() acquire: modify_email -> address execute: send_verification_mail(address) await: email_verified execute: save_user_info("email", address)不得不說這種模型有點像是協程(coroutine),但是不是用它來實現的,畢竟:一次請求完成了整個線程大大小小都結束了哪里還有協程啊對吧。這也不是WebSocket能解決的:比如收驗證郵件,都在第二個地方連接了,哪里還有Socket可言。這里針對的情況是,兩次連接之間的時間段是 斷開 的情況。
實現思路
主要是在模擬恢復執行的時候能較好地恢復原有上下文,在Python有exec的情況下,想辦法生成可配合執行Python代碼是一個不錯的選擇。恢復執行有這些步驟:
-
解析策略文件
</li> -
從持久存儲設備中反序列化變量
</li> -
找到斷點應該在哪里,按照這個位置:
-
載入模塊(如上面的time)
</li> -
載入上下文變量(如上面的a,b)
</li> </ul> </li> -
一直執行到下一個await點,退出執行
</li> </ul>/* 具體的實現明天看有沒有時間再更 */
附: 語法清單
digit := '0' | ... | '9' underscore := '_' symbol ::= letter | underscore { letter | underscore | digit } command ::= symbol variable ::= symbol string ::= '"' { [ 0x00 | ... | 0x21 | 0x23 | ... | 0x7f | '\n' | '\r' | '\"' | '\\' ] } '"' value ::= string | variable parameter ::= value parameter-list ::= '(' [ parameter-list ',' parameter | parameter ] ')' argument ::= symbol [ parameter-list ] argument-list ::= argument-list argument | argument command-line ::= command ':' argument-list [ '->' variable ] policy ::= policy \n command-line | command-line
原文 http://segmentfault.com/a/1190000003708486
-