fix: broadcast offline presence as soon as the last session drops

Logout left contacts seeing the user online until the me topic idle timeout
fired presUsersOfInterest(off), and even that frame was silently dropped
for p2p routes by handlePresence's xoriginal check. MarkUserOffline now
returns the remaining session count and cleanUp notifies users of interest
immediately once it hits zero; p2p presence is delivered straight to the
contact's me topic, mirroring presSingleUserOffline. Zentao #22.
This commit is contained in:
Austin
2026-09-18 17:42:18 +08:00
parent f4cedc7d75
commit 753a04ed12
4 changed files with 53 additions and 11 deletions
+32
View File
@@ -278,6 +278,7 @@ func (t *Topic) presUsersOfInterest(what, ua string) {
// Publish user's update to his/her users of interest on their 'me' topic while user's 'me' topic is offline
// Case A: user is being deleted, "gone".
// Case B: user's last session just disconnected, "off".
func presUsersOfInterestOffline(tenantID types.TenantID, uid types.Uid, subs []types.Subscription, what string) {
// Push update to subscriptions
for i := range subs {
@@ -286,6 +287,37 @@ func presUsersOfInterestOffline(tenantID types.TenantID, uid types.Uid, subs []t
continue
}
if types.GetTopicCat(subs[i].Topic) == types.TopicCatP2P {
// A presence request routed to the p2p topic would be silently
// dropped: the topic is loaded under its canonical p2p name while
// the request carries Topic="me" (notifyOnOrSkip), so the
// xoriginal check in handlePresence rejects it. Deliver to the
// contact's 'me' topic directly instead, the same way
// presSingleUserOffline does.
uid1, uid2, err := types.ParseP2P(subs[i].Topic)
if err != nil {
continue
}
contact := uid1
if contact == uid {
contact = uid2
}
if contact == uid || contact.IsZero() {
continue
}
routeUserServerMessage(contact, &ServerComMessage{
TenantID: tenantID,
Pres: &MsgServerPres{
Topic: notifyOn,
What: what,
Src: subs[i].Topic,
WantReply: false,
},
RcptTo: contact.UserId(),
})
continue
}
globals.hub.routeSrv <- &ServerComMessage{
TenantID: tenantID,
Pres: &MsgServerPres{