Erlang tcp服务器投票踢

时间:2015-04-05 01:19:11

标签: dictionary tcp erlang gen-server

我正在尝试编写一个简单的投票选项来添加到我现有的服务器。

我有一个使用gen_server的消息路由器,它使用init([]) -> {ok, dict:new()}存储所有连接的客户端。路由器与tcp服务器是分开的,tcp服务器也是gen_server,但处理tcp请求,然后中继到路由器。

由于“事物”正在被单独处理/存储,我想存储要被踢的用户,选民列表以及是否成功。所以这需要在路由器中至少在全局范围内,并且理想地与客户端字典分开。

关于最佳/理想方法的任何想法?
我相信我可以创建另一个gen_server“路由器”,它可以存储人们进入记录结构{kick,{Votes,Passed}}但我不知道这是否理想。

1 个答案:

答案 0 :(得分:0)

您想要“用户ID,选民列表和结果”。让我们看看它看起来像一个元组:

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

不是那么难。这些元组的列表 - 也不难。这些的字典有点复杂,因为你结束了(基本上,如果这是一个支持列表,使用上面的类型):

{User, {[Voters], Outcome}}

处理这个问题有点不高兴。例如,您可能希望按结果进行过滤,但现在现在将其隐藏在元组内的元组内,而平面元组列表允许简单过滤(实际过滤器,或仅保护列表理解,或其他)或使用lists:keysearch/3。这使得复杂的搜索变得更加尴尬,特别是如果你想知道一个特定的选民投票给某人多少次。

使用ETS肯定可以使基本问题变得更容易,因为它具有完全处理元组的工具,比使用keysearch/3的元组列表快得多(并且,假设您有成千上万的数字)这样的情况下,元组列表是不合适的 - 但是一如既往,首先尝试一下,你可能发现元组列表是完全足够的!)。另一方面,如果搜索案例变得更复杂,或者案例需要持久存储并且仍然受益于内存操作,或者您需要多个索引等,那么您应该真正转向Mnesia。

除此之外......你正在处理嵌套数据,虽然实际上只有90%的时间,但是其他10%的时间你要重新发明关系数据(但更糟糕的是,实际效用越来越少,而且速度越来越慢)或者只是通过一堆巴洛克式的程序代码来实现一种效果,只需使用像Postgres这样的东西就可以免费获得很少的痛苦(我碰巧对此非常熟悉DB,所以对我来说这是一个“轻量级解决方案” - 我理解这并不是每个人的情况。)

作为参考,您的数据在分解时看起来像这样(假设用户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中非常小。