通知系统使用GetStream的实现

sil*_*rne 4 getstream-io

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

基本上,相关模型为:

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

在GS中,有以下供稿:

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

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

1)Admin创建Entity

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

  • 订阅他notification:$userId-$orgIdAdminEntity:$entityId

2)User加入Organization

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

  • 订阅他notification:$userId-$orgIdOrg:$orgId

3)User购买Entity

  • 将活动推送AdminEntity:$entityId至此事件。

  • 订阅他notification:$userId-$orgIdUserEntity:$entityId

等等。

所描述模型的问题在于,在第一种情况下User,作为的创建者,Entity还将通过与其他成员一起Org:$orgId创建的通知来接收通知。第二种情况也是一样。EntityOrganization

这是通知系统的有害行为。

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

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

  • 摆脱像所有共享的饲料OrgAdminEntityUserEntity

  • 直接notification:$userId-org$id通过add_to_many电话推送活动,以提供有关用户在组织中的角色,与实体的关系等信息。

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

ian*_*las 6

我认为您的结构可能比您最初设计的要简单,并且更接近您在文章底部提到的内容。我还建议您通读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)
Run Code Online (Sandbox Code Playgroud)

此时,添加到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)
Run Code Online (Sandbox Code Playgroud)

如果Ian是新注册,则可以将活动发送给Acme的通知供稿,如下所示:

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

以后检索此通知feed时,它将所有动词分组在一起,然后分解通知活动,因此,如果您选择,您的UI可以报告不同的动向。

现在让我们将Silverthorne将该实体添加到GetStream:#Silverthorne将活动添加到Acme Inc的实体供稿#我们将“ cc”该活动“ cc”到聚合供稿acme_org_feed-> addActivity({'actor':'user:12','动词”:“发布”,“对象”:“实体:63”,“收件人”:['usercontent:12'],...您要跟踪的其他任何元数据})

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

  • 它将活动存储在orgAcme(org:56)的固定供稿中
  • 它将副本保存到Ian的时间轴中,因为user:74遵循org:56
  • 它还会将usercontent:12“ To”字段中的副本保存到Silverthorne的feed();这是完全可选的
  • 它将副本保存到Acme(org_aggregated:56)的汇总Feed中,因为该汇总Feed遵循固定Feed

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

  • 如果伊恩(Ian)应该看到他遵循的所有时间表,那么您将获取timeline:74提要,该提要将具有实体#63的副本
  • 如果Ian应该看到他关注的所有组织的列表,则可以获取ian_feed->followed()Ian关注的每个供稿的列表
  • 对于Ian遵循的每一个提要,您都可以获取该组织为Ian汇总的提要以查看摘要(即,fetch org_aggregated:56和Ian可以查看one new entity added in the past day是否是您汇总内容的方式)

这里的关键是,伊恩不会遵循饲料中才能看到的内容,您的应用程序可以拉任何饲料显示屏的任何用户。

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

希望这有助于澄清问题,并为您提供更多详细信息。如果您需要进一步的帮助或想法,请通过电子邮件与我们的支持团队联系。

最后一点,我认为我不会做的$userId-$orgId……我们的某些SDK(例如Rails和Django)会自动尝试“丰富”数据库中的这些值,因此您需要其他逻辑来尝试以便稍后拆分这些值。我们建议将UUID用作无冲突的标识符,但这完全由您控制。如果一个用户确实可以属于多个组织,则可以让该用户“关注”组织的供稿。