feat: improve group member events and push delivery

This commit is contained in:
richjohnrambo
2026-09-18 01:00:41 +08:00
parent 0e2f4e73d1
commit c6e7f6b923
13 changed files with 521 additions and 19 deletions
+56
View File
@@ -91,6 +91,8 @@ func (t *Topic) pushForData(fromUid types.Uid, data *MsgServerData, msgMarkedAsR
// Number of attached sessions the data message will be delivered to.
// Push notifications sent to users with non-zero online sessions will be marked silent.
Delivered: online,
Silent: t.cat == types.TopicCatGrp &&
boolFromAny(groupPrivateMap(pud.private)["mute_notifications"]),
// Unread counts are incremented for all recipients,
// and for sender only if the message wasnt't marked 'read' by the sender
ShouldIncrementUnreadCountInCache: uid != fromUid || !msgMarkedAsReadBySender,
@@ -104,6 +106,60 @@ func (t *Topic) pushForData(fromUid types.Uid, data *MsgServerData, msgMarkedAsR
return nil
}
// sendPushForStoredGroupMessage handles server-generated group messages which
// bypass Topic.handlePubBroadcast but must still update per-user unread counts
// and notify offline devices.
func sendPushForStoredGroupMessage(tenantID types.TenantID, msg *types.Message) {
if msg == nil || globals.usersUpdate == nil || types.GetTopicCat(msg.Topic) != types.TopicCatGrp || store.Topics == nil {
return
}
subs, err := store.Topics.GetSubs(tenantID, msg.Topic, nil)
if err != nil {
logs.Warn.Printf("group system push: load recipients topic=%s: %v", msg.Topic, err)
return
}
receipt := &push.Receipt{
TenantID: tenantID,
To: make(map[types.Uid]push.Recipient, len(subs)),
Payload: push.Payload{
What: push.ActMsg, Topic: msg.Topic, Timestamp: msg.CreatedAt, SeqId: msg.SeqId,
Content: msg.Content,
},
}
if mime, ok := msg.Head["mime"].(string); ok {
receipt.Payload.ContentType = mime
}
for _, sub := range subs {
uid := types.ParseUid(sub.User)
mode := sub.ModeWant & sub.ModeGiven
if uid.IsZero() || !mode.IsPresencer() || !mode.IsReader() {
continue
}
delivered := 0
if globals.sessionStore != nil {
globals.sessionStore.Range(func(_ string, sess *Session) bool {
if sess != nil && !sess.isCluster() && !sess.isProxy() && sess.tenantID == tenantID && sess.uid == uid {
delivered++
}
return true
})
}
if presence, presenceErr := store.GetUserPresence(tenantID, uid); presenceErr != nil {
logs.Warn.Printf("group system push: read presence topic=%s uid=%s: %v", msg.Topic, uid.UserId(), presenceErr)
} else if presence != nil && presence.Online && presence.SessionCount > delivered {
delivered = presence.SessionCount
}
receipt.To[uid] = push.Recipient{
Delivered: delivered,
Silent: boolFromAny(groupPrivateMap(sub.Private)["mute_notifications"]),
ShouldIncrementUnreadCountInCache: true,
}
}
if len(receipt.To) > 0 {
sendPush(receipt)
}
}
func (t *Topic) preparePushForSubReceipt(fromUid types.Uid, now time.Time) *push.Receipt {
// P2P push payloads use the canonical p2p... topic. usr... is accepted only
// as an input alias.