2015-04-05 65 views
0

我試圖寫一個簡單的投票踢選項添加到我現有的服務器。Erlang的tcp服務器投票踢

我有一個消息路由器使用gen_server,這存儲所有連接的客戶端使用init([]) -> {ok, dict:new()}。路由器與也是gen_server的tcp服務器分開,但處理tcp請求,然後將其中繼到路由器。

由於「事物」正在單獨處理/存儲,我想存儲用戶被踢,選民列表以及是否成功。因此,這需要至少在路由器內以一種全球性的方式,並且理想地與客戶端字典分開。

關於最佳/理想方法的任何想法?
我相信我可以創建另一個gen_server「路由器」,它可以存儲人們踢入一個記錄結構{kick,{Votes,Passed}}}但我不知道這是否理想。

+0

嘗試使用[ets](http://www.erlang.org/doc/man/ets.html)表 – igor 2015-04-05 13:24:28

+0

@kitty我還沒有使用過ets表。我簡要地閱讀了他們,並沒有完全理解他們。我對Erlang語言相當陌生,所以有很多我不知道的功能。如果你能解釋一下如何以這種方式使用ets表? – SharkBytes 2015-04-06 07:08:38

回答

0

你想要「用戶ID,選民列表和結果」。讓我們來看看如何看起來像一個元組:

{User :: user_id(), [Voters :: user_id()], Outcome :: boolean()} 

不那麼難。這些元組列表 - 也不難。這些的字典是有點複雜,因爲你風了(實際上,如果這是一個proplist變種,使用上述類型):

{User, {[Voters], Outcome}} 

這是一個有點不太高興來處理。例如,你可能想要按結果進行過濾,但是現在它已經隱藏在一個元組中,而一個扁平元組列表允許簡單的過濾(真正的過濾器,或者只是守護列表理解,或者其他)或者使用lists:keysearch/3。這使得複雜的搜索更加尷尬,特別是如果你想知道某個特定投票人投了多少次投票來踢人。

基本問題當然可以通過使用ETS變得更容易,因爲它具有用於以比使用keysearch/3的元組列表更快的方式處理元組的功能(並且,假設您有成千上萬的例子那些元組清單是不夠的 - 但一如既往,首先嚐試這種方式,你可能發現元組列表完全足夠!)。另一方面,如果搜索案例變得更加複雜一些,或者案例需要持久存儲並仍然受益於內存中的操作,或者您需要多個索引等,那麼您應該真的轉向Mnesia。

除此之外......你是在處理嵌套數據,雖然它實際上是的時間就好 90%的時間,其他10%你風要麼重塑關係型數據(但糟糕的是,有更少的實際效用和更慢),或者只是苦於通過一堆巴洛克式的程序代碼來實現一種效果,只需使用像Postgres這樣的東西就可以免費獲得一些效果(我碰巧非常熟悉這個數據庫,所以我認爲它是一個「輕量級解決方案」 - 我理解這不是每個人的情況)。

作爲參考,數據,時分解看起來像這樣(假設用戶ID是用於示例的目的電子郵件地址):

table user 
    attributes 
    id  EmailAddress 
    conditions 
    pk id 

table kick 
    attributes 
    id  UUID 
    user  EmailAddress 
    outcome Boolean 
    conditions 
    pk id 
    fk user 

table vote 
    attributes 
    kick  UUID 
    user  EmailAddress 
    conditions 
    pk (kick user) 
    fk kick 
    fk user 

雖然很明顯的的User[Voter]部件上面描述的元組引用了用戶記錄,但爲什麼試圖拉取某個用戶使用元組投遞的所有選票列表並不那麼明顯,這是一個令人討厭的過程。當我們查看已分解的數據時,我們意識到這是三張表,我們真的希望如果您有這個需求,我們可以在vote上自行運行一個查詢。但是如果你不要有這個要求,那麼不用擔心它,只是在ETS或Mnesia中使用元組! :-)這種數據在Erlang中非常小。