盒子
盒子
文章目录
  1. 模型设计
    1. Notify
    2. UserNotify
    3. Subscription
    4. SubscriptionConfig
  2. 配置文件 NotifyConfig
  3. 服务层 NotifyService
    1. NotifyService拥有以下方法:
    2. 各方法的处理逻辑如下:
  • 时序图
    1. 提醒的订阅、创建、拉取
    2. 公告的创建、拉取
    3. 信息的创建
  • 消息系统设计与实现「下篇」

    #模型设计

    #Notify

    1
    2
    3
    4
    5
    6
    7
    8
    id			: {type: 'integer', primaryKey: true},		// 主键
    content : {type: 'text'}, // 消息的内容
    type : {type: 'integer', required: true, enum: [1, 2, 3]}, // 消息的类型,1: 公告 Announce,2: 提醒 Remind,3:信息 Message
    target : {type: 'integer'}, // 目标的ID
    targetType : {type: 'string'}, // 目标的类型
    action : {type: 'string'}, // 提醒信息的动作类型
    sender : {type: 'integer'}, // 发送者的ID
    createdAt : {type: 'datetime', required: true}

    Save Remind
    消息表,我们需要targettargetType字段,来记录该条提醒所关联的对象。而action字段,则记录该条提醒所关联的动作。
    比如消息:「小明喜欢了文章」
    则:

    1
    2
    3
    target = 123,  // 文章ID
    targetType = 'post', // 指明target所属类型是文章
    sender = 123456 // 小明ID

    Save Announce and Message
    当然,Notify还支持存储公告和信息。它们会用到content字段,而不会用到targettargetTypeaction字段。

    #UserNotify

    1
    2
    3
    4
    5
    id			: {type: 'integer', primaryKey: true},		// 主键
    isRead : {type: 'boolean', required: true},
    user : {type: 'integer', required: true}, // 用户消息所属者
    notify : {type: 'integer', required: true} // 关联的Notify
    createdAt : {type: 'datetime', required: true}

    我们用UserNotify来存储用户的消息队列,它关联一则提醒(Notify)的具体内容。
    UserNotify的创建,主要通过两个途径:

    1. 遍历订阅(Subscription)表拉取公告(Announce)和提醒(Remind)的时候创建
    2. 新建信息(Message)之后,立刻创建。

    #Subscription

    1
    2
    3
    4
    5
    target      : {type: 'integer', required: true},    // 目标的ID
    targetType : {type: 'string', required: true}, // 目标的类型
    action : {type: 'string'}, // 订阅动作,如: comment/like/post/update etc.
    user : {type: 'integer'},
    createdAt : {type: 'datetime', required: true}

    订阅,是从Notify表拉取消息到UserNotify的前提,用户首先订阅了某一个目标的某一个动作,在此之后产生这个目标的这个动作的消息,才会被通知到该用户。
    如:「小明关注了产品A的评论」,数据表现为:

    1
    2
    3
    4
    target: 123,  // 产品A的ID
    targetType: 'product',
    action: 'comment',
    user: 123 // 小明的ID

    这样,产品A下产生的每一条评论,都会产生通知给小明了。

    #SubscriptionConfig

    1
    2
    action: {type: 'json', required: true},   // 用户的设置
    user: {type: 'integer'}

    不同用户可能会有不一样的订阅习惯,在这个表中,用户可以统一针对某种动作进行是否订阅的设置。而默认是使用系统提供的默认配置:

    1
    2
    3
    4
    defaultSubscriptionConfig: {
    'comment' : true, // 评论
    'like' : true, // 喜欢
    }

    在这套模型中,targetTypeaction是可以根据需求来扩展的,例如我们还可以增加多几个动作的提醒:hate被踩、update被更新…诸如此类。

    #配置文件 NotifyConfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 提醒关联的目标类型
    targetType: {
    PRODUCT : 'product', // 产品
    POST : 'post' // 文章
    },

    // 提醒关联的动作
    action: {
    COMMENT : 'comment', // 评论
    LIKE : 'like', // 喜欢
    },

    // 订阅原因对应订阅事件
    reasonAction: {
    'create_product' : ['comment', 'like']
    'like_product' : ['comment'],
    'like_post' : ['comment'],
    },

    // 默认订阅配置
    defaultSubscriptionConfig: {
    'comment' : true, // 评论
    'like' : true, // 喜欢
    }

    #服务层 NotifyService

    #NotifyService拥有以下方法:

    • createAnnounce(content, sender)
    • createRemind(target, targetType, action, sender, content)
    • createMessage(content, sender, receiver)
    • pullAnnounce(user)
    • pullRemind(user)
    • subscribe(user, target, targetType, reason)
    • cancelSubscription(user, target ,targetType)
    • getSubscriptionConfig(userID)
    • updateSubscriptionConfig(userID)
    • getUserNotify(userID)
    • read(user, notifyIDs)

    #各方法的处理逻辑如下:

    createAnnounce(content, sender)

    1. 往Notify表中插入一条公告记录

    createRemind(target, targetType, action, sender, content)

    1. 往Notify表中插入一条提醒记录

    createMessage(content, sender, receiver)

    1. 往Notify表中插入一条信息记录
    2. 往UserNotify表中插入一条记录,并关联新建的Notify

    pullAnnounce(user)

    1. 从UserNotify中获取最近的一条公告信息的创建时间: lastTime
    2. lastTime作为过滤条件,查询Notify的公告信息
    3. 新建UserNotify并关联查询出来的公告信息

    pullRemind(user)

    1. 查询用户的订阅表,得到用户的一系列订阅记录
    2. 通过每一条的订阅记录的targettargetTypeactioncreatedAt去查询Notify表,获取订阅的Notify记录。(注意订阅时间必须早于提醒创建时间)
    3. 查询用户的配置文件SubscriptionConfig,如果没有则使用默认的配置DefaultSubscriptionConfig
    4. 使用订阅配置,过滤查询出来的Notify
    5. 使用过滤好的Notify作为关联新建UserNotify

    subscribe(user, target, targetType, reason)

    1. 通过reason,查询NotifyConfig,获取对应的动作组:actions
    2. 遍历动作组,每一个动作新建一则Subscription记录

    cancelSubscription(user, target ,targetType)

    1. 删除usertargettargetType对应的一则或多则记录

    getSubscriptionConfig(userID)

    1. 查询SubscriptionConfig表,获取用户的订阅配置

    updateSubscriptionConfig(userID)

    1. 更新用户的SubscriptionConfig记录

    getUserNotify(userID)

    1. 获取用户的消息列表

    read(user, notifyIDs)

    1. 更新指定的notify,把isRead属性设置为true

    #时序图

    #提醒的订阅、创建、拉取

    我们可以在产品创建之后,调用NotifyService.subscribe方法,
    然后在产品被评论之后调用NotifyService.createRemind方法,
    再就是用户登录系统或者其他的某一个时刻调用NotifyService.pullRemind方法,
    最后在用户查询消息队列的时候调用NotifyService.getUserNotify方法。

    #公告的创建、拉取

    在管理员发送了一则公告的时候,调用NotifyService.createAnnounce方法,
    然后在用户登录系统或者其他的某一个时刻调用NotifyService.pullAnnounce方法,
    最后在用户查询消息队列的时候调用NotifyService.getUserNotify方法。

    #信息的创建


    信息的创建,只需要直接调用NotifyService.createMessage方法就可以了,
    在下一次用户查询消息队列的时候,就会查询这条信息。

    支持一下
    扫一扫,支持JerryC
    • 微信扫一扫
    • 支付宝扫一扫