spark-server/internal/module/deliver/logic/fanout.go
2026-09-18 14:50:41 +08:00

87 lines
2.2 KiB
Go

package logic
import (
"context"
"spark-server/internal/module/deliver/entity"
inboxlogic "spark-server/internal/module/inbox/logic"
syncentity "spark-server/internal/module/sync/entity"
"spark-server/internal/transport/tcp/protocol"
"spark-server/internal/transport/tcp/session"
)
type Mailbox interface {
Put(ctx context.Context, userID int64, eventType syncentity.EventType, conversationID int64, payload []byte) error
}
// InboxFanout updates Redis dialog ZSET then pushes to online sessions.
func InboxFanout(sessions session.Manager, inbox inboxlogic.Store, mailbox Mailbox) Handler {
push := SessionFanout(sessions)
return func(ctx context.Context, job *entity.Job) error {
if err := applyInbox(ctx, inbox, job); err != nil {
return err
}
if err := applyMailbox(ctx, mailbox, job); err != nil {
return err
}
return push(ctx, job)
}
}
func applyInbox(ctx context.Context, inbox inboxlogic.Store, job *entity.Job) error {
if inbox == nil || job == nil || job.ConversationID == 0 {
return nil
}
if len(job.Preview) > 0 {
if err := inbox.SetPreview(ctx, job.ConversationID, job.Preview); err != nil {
return err
}
}
if job.Cmd != 0 && job.Cmd != protocol.CmdMessage {
return nil
}
score := job.MsgID
for _, uid := range job.ToUserIDs {
if uid == job.FromUserID {
if err := inbox.TouchRead(ctx, uid, job.ConversationID, score); err != nil {
return err
}
continue
}
if err := inbox.TouchUnread(ctx, uid, job.ConversationID, score); err != nil {
return err
}
if err := inbox.IncrUnread(ctx, uid, job.ConversationID, 1); err != nil {
return err
}
}
return nil
}
func applyMailbox(ctx context.Context, mailbox Mailbox, job *entity.Job) error {
if mailbox == nil || job == nil || job.NotMailbox {
return nil
}
ev := mailboxEventType(job.Cmd)
if ev == 0 {
return nil
}
for _, uid := range job.ToUserIDs {
if err := mailbox.Put(ctx, uid, ev, job.ConversationID, job.Payload); err != nil {
return err
}
}
return nil
}
func mailboxEventType(cmd uint16) syncentity.EventType {
switch cmd {
case protocol.CmdRecallMessage:
return syncentity.EventRecall
case protocol.CmdDeleteMessage:
return syncentity.EventDelete
default:
return 0
}
}