fix: align group management APIs

This commit is contained in:
richjohnrambo
2026-09-13 16:03:55 +08:00
parent f1279ac607
commit a9afc6ff6a
34 changed files with 1381 additions and 639 deletions
+38 -61
View File
@@ -2,80 +2,57 @@ package main
import (
"encoding/json"
"strconv"
"strings"
"time"
"github.com/tinode/chat/server/logs"
"github.com/tinode/chat/server/store"
"github.com/tinode/chat/server/store/types"
)
// dispatchIMGroupEvents delivers committed outbox events to online topic
// sessions. Events remain pending when the hub is unavailable or its queue is
// full, so the next successful group mutation retries them.
func dispatchIMGroupEvents(tenantID types.TenantID) {
if tenantID.IsZero() || globals.hub == nil || store.GroupBusiness == nil {
func publishIMGroupRealtimeEvent(tenantID types.TenantID, topic string, actor types.Uid, eventType string, payload any) {
topic = strings.TrimSpace(topic)
eventType = strings.TrimSpace(eventType)
if tenantID.IsZero() || topic == "" || eventType == "" {
return
}
now := time.Now().UTC().Round(time.Millisecond)
events, err := store.GroupBusiness.ListPendingEvents(tenantID, 100, now)
encoded, err := json.Marshal(payload)
if err != nil {
logs.Warn.Printf("group outbox: list tenant=%d: %v", tenantID, err)
return
logs.Warn.Printf("group realtime: encode event topic=%s event=%s: %v", topic, eventType, err)
encoded = []byte(`{}`)
}
for _, event := range events {
members, memberErr := store.Topics.GetUsers(tenantID, event.Topic, &types.QueryOpt{Limit: 1000})
if memberErr != nil {
logs.Warn.Printf("group outbox: list members event=%s: %v", event.EventID, memberErr)
return
}
for _, member := range members {
uid := types.ParseUid(member.User)
if uid.IsZero() {
if decoded, parseErr := strconv.ParseInt(member.User, 10, 64); parseErr == nil && decoded > 0 {
uid = store.EncodeUid(decoded)
}
}
if uid.IsZero() || uid == event.ActorUserID {
continue
}
if err = createIMSystemNotification(tenantID, uid,
stableIMEventID(event.EventID, uid.UserId(), "notification"), event.EventType,
"群聊动态", event.EventType, types.KVMap{"topic": event.Topic}); err != nil {
logs.Warn.Printf("group outbox: create notification event=%s user=%s: %v", event.EventID, uid.UserId(), err)
return
}
}
payload := json.RawMessage(event.Payload)
if len(payload) == 0 {
payload = json.RawMessage(`{}`)
}
from := ""
if !event.ActorUserID.IsZero() {
from = event.ActorUserID.UserId()
}
message := &ServerComMessage{
TenantID: tenantID,
RcptTo: event.Topic,
AsUser: from,
Timestamp: event.CreatedAt,
Info: &MsgServerInfo{
Topic: event.Topic,
From: from,
What: "group",
Event: event.EventType,
Payload: payload,
},
}
from := ""
if !actor.IsZero() {
from = actor.UserId()
}
message := &ServerComMessage{
TenantID: tenantID,
RcptTo: topic,
AsUser: from,
Timestamp: time.Now().UTC().Round(time.Millisecond),
Info: &MsgServerInfo{
Topic: topic,
From: from,
What: "group",
Event: eventType,
Payload: json.RawMessage(encoded),
},
}
if globals.hub != nil {
select {
case globals.hub.routeSrv <- message:
if err = store.GroupBusiness.MarkEventDelivered(tenantID, event.EventID, now); err != nil {
logs.Warn.Printf("group outbox: mark delivered event=%s: %v", event.EventID, err)
return
}
default:
logs.Warn.Printf("group outbox: hub queue full event=%s", event.EventID)
return
logs.Warn.Printf("group realtime: hub queue full topic=%s event=%s", topic, eventType)
}
}
publishRealtimeTopicMessage(topic, message)
}
func userIDs(uids []types.Uid) []string {
ids := make([]string, 0, len(uids))
for _, uid := range uids {
if !uid.IsZero() {
ids = append(ids, uid.UserId())
}
}
return ids
}