之前碰到一個(gè)需要實(shí)現(xiàn)工作流的需求,簡(jiǎn)單來(lái)說(shuō)就是一個(gè)事件辜妓,可以通過(guò)多人多權(quán)限進(jìn)行事件狀態(tài)的轉(zhuǎn)化矾克,這里我以django-river為例說(shuō)明。
在一個(gè)小team捏鱼,有 leader 和 coder执庐,現(xiàn)在有工作流狀態(tài)open,in-progress穷躁,resolved耕肩,re-open,closed五中狀態(tài)问潭,狀態(tài)流向?yàn)閛pen -> in-progress,in-progress -> resolved婚被,resolved -> re-open狡忙,resolved -> closed,re-open -> in-progress五種址芯,如下圖
我們進(jìn)行權(quán)限的分析灾茁,open -> in-progress,in-progress -> resolved谷炸,re-open -> in-progress 為 coder 的權(quán)限北专,resolved -> closed,resolved -> re-open 為leader 的權(quán)限旬陡,在事件的各個(gè)狀態(tài)中可由擁有該權(quán)限的人修改該事情的狀態(tài)直到結(jié)束拓颓,在簡(jiǎn)單研究了源碼后大致了解其工作流程,加上該項(xiàng)目幾近一年未更新且bug較多描孟,于是自己有了些想法特地記錄下來(lái)驶睦,當(dāng)然最后也沒(méi)有實(shí)現(xiàn):)
首先是權(quán)限一個(gè)model砰左,事件流一個(gè)model,接下來(lái)就是用戶操作該事件時(shí)判斷是否有權(quán)限场航,傳統(tǒng)做法我想應(yīng)該是一個(gè)記錄用戶權(quán)限的model缠导,當(dāng)需要判斷的時(shí)候則從model中查詢即可。
在我自己的yy中溉痢,考慮到一種情況是權(quán)限可能不會(huì)很多(通常情況下項(xiàng)目的權(quán)限也不會(huì)很多僻造,當(dāng)然是以自己接觸到的這個(gè)項(xiàng)目需求考慮的),小于20種孩饼,如果用戶很多則這張用戶權(quán)限表會(huì)比較大髓削,查詢會(huì)有一定時(shí)間消耗(后來(lái)覺(jué)得此文最后要講述的方法沒(méi)必要也是基于對(duì)mysql查性能的不了解),所以結(jié)合自己對(duì)位運(yùn)算的了解yy了如下的方法:
給用戶一個(gè)權(quán)限的值捣辆,沒(méi)錯(cuò)是值蔬螟,這個(gè)值初始化為0。
將不多(前提是不多)的權(quán)限用狀態(tài)壓縮汽畴,如有權(quán)限a旧巾,b,c則壓縮成001忍些,010鲁猩,100,即1罢坝,2廓握,4這3個(gè)值,所以這是我強(qiáng)調(diào)權(quán)限種類(lèi)不多的原因嘁酿,當(dāng)權(quán)限超過(guò)30種就會(huì)爆int? :)
接下來(lái)就是騷操作的開(kāi)始隙券,假設(shè)用戶的權(quán)限值為x,需要增刪查的權(quán)限為y:
- 增? x = x | y
- 刪 x = x ^ y
- 查 x & y
這樣就不必維護(hù)一張可能會(huì)比較大的表闹司,同時(shí)查詢的時(shí)間復(fù)雜度O(1)
最后沒(méi)有用這種方法基于幾個(gè)考慮:
1.感覺(jué)有點(diǎn)騷怕背鍋
2.對(duì)于mysql查個(gè)幾十萬(wàn)條的數(shù)據(jù)表應(yīng)該也沒(méi)什么壓力
3.最重要的一點(diǎn)娱仔,這個(gè)項(xiàng)目后來(lái)我沒(méi)接手做別人負(fù)責(zé)了:)