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 } }