快速實現業務需求:不重複扣費

docstore是一種創新的文檔資料庫,幫助開發者更快地完成複雜的業務需求。這個例子里,我們來看這樣的一個需求:

  • 根據單號進行扣費
  • 對於重複的單號,不重複扣費

實現代碼在這裡:v2pro/quokka

docstore.Entity("Account", `nstruct Doc {nt1: i64 amountnt2: string account_typen}n`).Command("create", `nfunction handle(doc, req) {ntdoc.amount = req.amount;ntdoc.account_type = req.account_type;ntreturn {};n}n`, `nstruct Request {nt1: i64 amountnt2: string account_typen}nstruct Response {n}n`).Command("charge", `nfunction handle(doc, req) {ntif (doc.account_type == vip) {nttif (doc.amount - req.charge < -10) {ntttthrow vip account can not below -10;ntt}nt} else {nttif (doc.amount - req.charge < 0) {ntttthrow normal account can not below 0;ntt}nt}ntdoc.amount -= req.charge;ntreturn {remaining_amount: doc.amount};n}n`, `nstruct Request {nt1: i64 chargen}nstruct Response {nt1: i64 remaining_amountn}n`)n

struct Doc 定義的是文檔自身的格式,用的是thrift IDL定義語言。然後定義了兩個操作,create(開戶)和charge(扣費)。每個操作都定義自己的Request和Response的格式。實際的業務邏輯是用javascript寫的。

調用這個docstore的代碼是這樣的:

func Test_charge_idempotence(t *testing.T) {ntshould := require.New(t)ntexecAndExpectSuccess(t, "http://127.0.0.1:9865/docstore/Account/create",ntt"EntityId", "123", "CommandRequest", runtime.NewObject("amount", 100, "account_type", "vip"))ntresp := execAndExpectSuccess(t, "http://127.0.0.1:9865/docstore/Account/charge",ntt"EntityId", "123", "CommandId", "xcvf", "CommandRequest", runtime.NewObject("charge", 10))ntshould.Equal(90, jsoniter.Get(resp, "data", "remaining_amount").ToInt())ntresp = execAndExpectSuccess(t, "http://127.0.0.1:9865/docstore/Account/charge",ntt"EntityId", "123", "CommandId", "xcvf", "CommandRequest", runtime.NewObject("charge", 10))ntshould.Equal(90, jsoniter.Get(resp, "data", "remaining_amount").ToInt())n}n

實際也就是執行 HTTP POST,去調用 javascript 定義的 handler。

通過這個及其簡單的例子,我們可以看到docstore的一些優點:

  • 業務邏輯不用考慮並發,底層框架保證了所有的command對於一個entity來說是串列執行的。
  • 只需要寫javascript的handler,以及定義schema。然後自動就有http的數據介面。避免了crud數據服務的重複開發。
  • 框架支持了CommandId,只要CommandId相同,保證了不會重複被執行,而且返回之前的返回值。也就是原生支持了冪等性。

參見:創新的主存儲方案

參見:我們需要什麼樣的資料庫


推薦閱讀:

C++中的sort函數使用自定義比較函數的具體運行過程是怎麼樣的呢?
想學習 C#,案頭有兩本書(CLR via C# 和 C# in Depth),不知學習順序是怎麼樣的?
寫貪吃蛇,俄羅斯方塊,這些小遊戲對初學C的真必要嗎?
演算法之字元串模式匹配

TAG:编程 | Go语言 | 领域驱动设计DDD |