2015-04-05 45 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中非常小。