0

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

我有一个使用 gen_server 的消息路由器,它使用init([]) -> {ok, dict:new()}. 路由器独立于 tcp 服务器,它也是一个 gen_server,但处理 tcp 请求,然后将这些请求中继到路由器。

由于“事物”是单独处理/存储的,我想存储要被踢的用户、选民名单以及它是否成功。因此,这至少需要在路由器内以某种方式是全局的,并且最好与客户端字典分开。

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

4

1 回答 1

0

您需要“用户 ID、选民名单和结果”。让我们看看它看起来是一个元组:

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

没那么难。这些元组的列表——也不难。其中的 dict 有点复杂,因为你最终会得到(基本上,如果这是一个 proplist,使用上面的类型):

{User, {[Voters], Outcome}}

处理起来有点不高兴。例如,您可能希望按结果过滤,但现在它被隐藏在元组内的元组中,而平面元组列表允许简单过滤(真正的过滤器,或者只是保护列表理解,或其他)或使用lists:keysearch/3. 这使复杂的搜索变得更加尴尬,尤其是如果您想知道特定选民投票踢某人的次数。

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

除此之外......你正在处理嵌套数据,虽然这实际上在 90% 的情况下都很好,但另外 10% 的时间你最终要么重新发明关系数据(但更糟糕的是,实际效用较少,速度较慢( “——我知道这不是每个人都这样)。

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

于 2015-04-06T12:26:15.033 回答