【问题标题】:Notifications system implementation with GetStream使用 GetStream 实现通知系统
【发布时间】:2017-01-12 07:36:10
【问题描述】:

我正在尝试使用 GS 实现通知系统

基本上,相关模型有:

  • Organizations(组织);
  • User,组织成员。用户可以在组织中拥有管理权限;
  • Entity 管理员用户可以创建,普通用户可以购买,实体也属于组织。

在 GS 中有以下提要:

  • notification:$userId-$orgId ---- 重复使用默认提要,特定组织中用户的个人通知提要
  • Org:$orgId ---- 所有组织成员的共享提要
  • AdminEntity:$entityId ---- 管理员用户对实体的用户操作通知
  • UserEntity:$entityId ---- 普通用户在实体上的管理员/系统操作通知

让我简单解释一下提要之间的基本关系:

1) Admin 创建 Entity:

  • Org:$orgId推送有关此事件的活动。活动将有user:$userId 作为Actorentity:$entityId 作为Object

  • 将他的notification:$userId-$orgId订阅到AdminEntity:$entityId

2)User 加入Organization

  • 将有关此事件的活动推送到Org:$orgId

  • 将他的notification:$userId-$orgId 订阅到Org:$orgId

3)User购买Entity

  • 将有关此事件的活动推送到AdminEntity:$entityId

  • 将他的notification:$userId-$orgId订阅到UserEntity:$entityId

等等。

所描述模型的问题是,在第一种情况下,Entity 的创建者 User 也将通过 Org:$orgId 收到通知,通知他已经创建了 Entity 以及其他 Organization 成员。与第二种情况相同。

这是通知系统的不良行为。

理想情况下,我们不应通知User 他自己在“共享”供稿中的活动,例如Org:$orgId。问题是 - 如何实现这一目标?也许 GS 提要应该以不同的方式组织,或者可以通过 Aggregation Format 语法来完成?

已编辑:如我所见,可能的解决方案是:

  • 删除所有共享提要,例如OrgAdminEntityUserEntity

  • 通过add_to_many 调用将有关用户在组织中的角色、与实体的关系等相关的活动直接推送到notification:$userId-org$id 提要。

我不确定这是否是与 GS 一起使用的惯用解决方案。

【问题讨论】:

    标签: getstream-io


    【解决方案1】:

    我认为您的结构可能比您最初设计的更简单,并且更接近您在帖子底部提到的内容。我还建议您通读 http://blog.getstream.io/best-practices-for-instagram-style-feeds/,这听起来与您在这里想要做的相似。

    关于我们的 Feed 类型的简化细分:

    • 通知供稿适用于内容的创建者(“15 人喜欢您的帖子”)。
    • 汇总供稿适用于关注者(“添加了 12 个帖子”)。
    • 平面提要是添加核心活动(在您的情况下为“实体”?)的好地方,但您也可以使用活动模型上的“收件人”字段将这些活动的其他副本保存到其他聚合和通知提要,类似于抄送电子邮件

    任何 Feed 类型都可以跟在 Flat Feed 之后,但我们通常建议只有 Flat Feed 和聚合 Feed 跟在其他 Flat Feed 之后。通知提要通常是独立的,我将在下面进行描述。

    让我们做以下假设:

    • 有一个名为“Silverthorne”的管理员用户,ID 为12
    • 组织 ID 56 是“Acme Inc”
    • Ian 是 ID 为74 的普通用户
    • Silverthorne 准备了一些实体内容,当它们保存到您自己的数据库时,其 ID 为 63

    让我们创建一个名为org 的平面供稿,用于进行实体活动,并创建一个名为org_aggregated 的聚合供稿用于聚合数据,一个名为notifications 的通知供稿,一个名为timeline 的用户平面供稿。如果您的用户可以看到其他用户(而不是组织)创作的所有内容的提要,那么我建议您使用另一个名为 usercontent 的平面提要。

    如果 Silverthorne 将此活动发布到 GetStream,活动参与者将是 "user:12",动词可能是 "post",对象将是 "entity:63"

    要对此进行伪编码,因为我不知道您使用的是哪个 SDK,所以类似于:

    # acme inc gets created as an organization, and so its aggregated feed
    # should follow the org's flat feed
    acme_org_feed = getstreamClient->feed('org', '56')
    acme_org_agg_feed = getstreamClient->feed('org_aggregated', '56')
    acme_org_agg_feed->follow(acme_org_feed)
    

    此时,添加到 Acme 的 org 固定提要中的每个实体也将被聚合。您可以在 GetStream 仪表板上设置这些内容的汇总方式。

    现在,让 Ian 关注 Acme:

    # ian is a member of Acme Inc, so follow their entity feed
    ian_feed = getstreamClient->feed('timeline', '74')
    ian_feed->follow(acme_org_feed)
    

    如果 Ian 是新注册的,您可以像这样向 Acme 的通知提要发送活动:

    acme_notif_feed = getstreamClient->feed('org_notification', '56')
    acme_notif_feed->addActivity({
      'actor': 'user:74',
      'verb': 'registration',
      'object': 'user:74'
    })
    

    当您稍后检索此通知提要时,它会将所有动词组合在一起,然后分解通知活动,因此您的 UI 可以根据您的选择以不同的方式报告这些活动。

    现在让 Silverthorne 将该实体添加到 GetStream: # Silverthorne 向 Acme Inc 的实体提要添加一个活动 # 我们会将活动“抄送”到聚合的提要 acme_org_feed->addActivity({ “演员”:“用户:12”, '动词':'发布', '对象':'实体:63', 'to': ['usercontent:12'], ...您要跟踪的任何其他元数据 })

    保存后,GetStream 将执行以下操作:

    • 它将活动存储在 Acme 的 org 固定提要 (org:56) 中
    • 它会将副本保存到 Ian 的时间线中,因为 user:74 遵循 org:56 的平面提要
    • 它还会从“收件人”字段将副本保存到 Silverthorne 的提要 (usercontent:12);这完全是可选的
    • 它将副本保存到 Acme (org_aggregated:56) 的聚合提要中,因为聚合提要遵循固定提要

    当 Ian 登录时,您的应用现在可以显示几个可能的供稿和选项,这完全取决于您的应用:

    • 如果 Ian 应该看到他关注的所有内容的时间线,您将获取 timeline:74 提要,其中将包含实体 #63 的副本
    • 如果 Ian 应该看到他关注的所有组织的列表,您可以获取 ian_feed->followed() 以获取 Ian 关注的每个提要的列表
    • 对于 Ian 关注的每个提要,您可以获取该组织的聚合提要以供 Ian 查看摘要(即,获取 org_aggregated:56 并且 Ian 可以看到 one new entity added in the past day,如果这是您聚合内容的方式)

    这里的关键是,Ian 没有为了查看内容而关注提要,您的应用可以拉取任何提要以显示给任何用户。

    如果 Ian 要“分享”或“喜欢”Silverthorne 发布的那个实体,您需要在“org_notification:56”提要中添加一个新活动,其中“user:74”作为 Actor,“entity:63”是宾语,动词是你想要的任何字符串(最多 20 个字符)。如果您希望您的应用查看其他用户如何与组织的帖子进行交互,您可以获取 org_notification:56 并且所有用户都可以看到“Ian 喜欢的实体 63”,或者您的 UI 需要呈现它。

    希望这有助于澄清事情并为您提供一些额外的细节。如果您需要进一步的帮助或想法,请通过电子邮件联系我们的支持团队。

    最后一点,我不认为我会这样做 $userId-$orgId ...我们的一些 SDK(即 Rails 和 Django)会自动尝试“丰富”您数据库中的这些值,所以您d 需要额外的逻辑来尝试稍后拆分这些值。我们建议使用 UUID 作为无冲突标识符,但这完全由您来控制。如果一个用户真的可以是多个组织的一部分,您可以让该用户“关注”该组织的提要。

    【讨论】:

    • 伊恩回答得很好!不过,我想澄清一下。在最后的第 3 段中,您谈到了“喜欢”和“分享”通知。如果“user:74”喜欢“entity:63”,“org_notification:56”如何更新?我的理解是我们必须这样告诉“org_notification:56”。伪码acme_notif_feed->addActivity({ actor: "user:74", verb: "like", object: "entity:63" })
    • 对于每个其他用户,您只需获取 org_notification:56 提要以查看是否有通知要显示,这会告诉您“Ian 喜欢了帖子”或“Besart 分享了帖子” 等等。老实说,自从我在 Stream 工作或使用它的 API 以来已经有好几年了,所以我对它有点生疏了。 :)
    猜你喜欢
    • 2016-06-19
    • 2014-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 2015-12-19
    • 2018-04-27
    • 2014-08-20
    相关资源
    最近更新 更多