群阅后即焚

pull/3727/head
hawklin2017 2 weeks ago
parent 35152a2832
commit 6f5575f583

@ -189,7 +189,7 @@ func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkCon
for i := oldHasReadSeq + 1; i <= req.HasReadSeq; i++ {
groupSeqs = append(groupSeqs, i)
}
m.recordGroupBurnReadCount(ctx, conversation, groupSeqs)
m.recordGroupBurnReadCount(ctx, conversation, req.UserID, groupSeqs)
}
m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID,
req.UserID, seqs, hasReadSeq)
@ -276,9 +276,9 @@ func (m *msgServer) recordBurnDeadlines(ctx context.Context, conv *conversation.
}
// recordGroupBurnReadCount 在群聊阅读时记录「阅后即焚」进度。
// 每次已读触发 $inc read_count首次写入时记录 member_count 与 burn_end_time
// 每次已读触发 $inc read_count首次写入时记录 member_count、burn_end_time、send_id发送者
// 仅在群的 MsgBurnDuration > 0 时生效;失败只记日志,不影响主流程。
func (m *msgServer) recordGroupBurnReadCount(ctx context.Context, conv *conversation.Conversation, seqs []int64) {
func (m *msgServer) recordGroupBurnReadCount(ctx context.Context, conv *conversation.Conversation, readerUserID string, seqs []int64) {
if len(seqs) == 0 || m.groupMsgBurnRecordDB == nil {
return
}
@ -290,10 +290,22 @@ func (m *msgServer) recordGroupBurnReadCount(ctx context.Context, conv *conversa
if groupInfo.MsgBurnDuration <= 0 {
return
}
seqSenderID := make(map[int64]string, len(seqs))
_, _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, readerUserID, conv.ConversationID, seqs)
if err != nil {
log.ZWarn(ctx, "recordGroupBurnReadCount GetMsgBySeqs failed", err,
"groupID", conv.GroupID, "conversationID", conv.ConversationID, "readerUserID", readerUserID, "seqs", seqs)
} else {
for _, md := range msgs {
if md != nil && md.Seq > 0 {
seqSenderID[md.Seq] = md.SendID
}
}
}
now := time.Now().UnixMilli()
burnEndTimeMs := now + int64(groupInfo.MsgBurnDuration)*1000
memberCount := int32(groupInfo.MemberCount)
if err := m.groupMsgBurnRecordDB.UpsertOnRead(ctx, conv.GroupID, seqs, memberCount, burnEndTimeMs); err != nil {
if err := m.groupMsgBurnRecordDB.UpsertOnRead(ctx, conv.GroupID, seqs, seqSenderID, memberCount, burnEndTimeMs); err != nil {
log.ZError(ctx, "recordGroupBurnReadCount UpsertOnRead failed", err,
"groupID", conv.GroupID, "seqs", seqs)
}

@ -34,9 +34,9 @@ type ExpiredGroupBurn struct {
// 消费conversation 服务 ClearGroupBurnExpiredMsgs cron 入口。
type GroupMsgBurnRecord interface {
// UpsertOnRead 批量原子更新阅读记录:
// - 若 (group_id, seq) 不存在:插入 {member_count, burn_end_time, create_time, read_count=1}
// - 若已存在:仅对 read_count 执行 $inc不覆盖首次写入的 burn_end_time
UpsertOnRead(ctx context.Context, groupID string, seqs []int64, memberCount int32, burnEndTimeMs int64) error
// - 若 (group_id, seq) 不存在:插入 {member_count, burn_end_time, create_time, send_id, read_count=1}send_id 来自 seqSenderID[seq],可为空。
// - 若已存在:仅对 read_count 执行 $inc不覆盖首次写入的 burn_end_time、send_id
UpsertOnRead(ctx context.Context, groupID string, seqs []int64, seqSenderID map[int64]string, memberCount int32, burnEndTimeMs int64) error
// FindExpired 查询满足以下条件的记录并按 group_id 聚合:
// burn_end_time <= nowMs AND read_count >= member_count

@ -52,15 +52,19 @@ type groupMsgBurnRecordMgo struct {
}
// UpsertOnRead 对每条 seq 执行 upsert
// - 首次插入($setOnInsert写入 member_count、burn_end_time、create_timeread_count 初始化为 1。
// - 首次插入($setOnInsert写入 member_count、burn_end_time、create_time、send_idread_count 初始化为 1。
// - 已存在时仅对 read_count 执行 $inc 1。
func (m *groupMsgBurnRecordMgo) UpsertOnRead(ctx context.Context, groupID string, seqs []int64, memberCount int32, burnEndTimeMs int64) error {
func (m *groupMsgBurnRecordMgo) UpsertOnRead(ctx context.Context, groupID string, seqs []int64, seqSenderID map[int64]string, memberCount int32, burnEndTimeMs int64) error {
if len(seqs) == 0 {
return nil
}
now := time.Now().UnixMilli()
models := make([]mongo.WriteModel, 0, len(seqs))
for _, seq := range seqs {
senderID := ""
if seqSenderID != nil {
senderID = seqSenderID[seq]
}
filter := bson.M{
"group_id": groupID,
"seq": seq,
@ -70,6 +74,7 @@ func (m *groupMsgBurnRecordMgo) UpsertOnRead(ctx context.Context, groupID string
"$setOnInsert": bson.M{
"group_id": groupID,
"seq": seq,
"send_id": senderID,
"member_count": memberCount,
"burn_end_time": burnEndTimeMs,
"create_time": now,

@ -26,6 +26,8 @@ type GroupMsgBurnRecord struct {
GroupID string `bson:"group_id"`
// Seq 消息序列号
Seq int64 `bson:"seq"`
// SendID 发送该条群消息的用户 ID首次有成员已读时写入$setOnInsert
SendID string `bson:"send_id"`
// ReadCount 已阅读该消息的成员数量(原子累加)
ReadCount int32 `bson:"read_count"`
// MemberCount 创建记录时的群成员总数;用于判断是否全员已读

Loading…
Cancel
Save