Add HTTP /v1 MVC, TCP send path, groups with server-side member-avatar collage, object-storage upload, and friends/favorites around the architecture-v3 layout. Co-authored-by: Cursor <cursoragent@cursor.com>
22 lines
1.2 KiB
Plaintext
22 lines
1.2 KiB
Plaintext
---
|
|
description: Message persist, deliver queue, and Redis inbox rules.
|
|
globs: internal/module/{message,deliver,inbox,sync,conversation}/**/*.go
|
|
alwaysApply: false
|
|
---
|
|
|
|
# Message / deliver / inbox
|
|
|
|
Send path: permission → INSERT `messages` + UPDATE `conversations.last_msg_id` → `DeliverQueue.Push` → `SEND_ACK`. No ACK if enqueue fails.
|
|
|
|
Idempotency: `UNIQUE(sender_id, conversation_id, client_msg_id)`. Conflicts return the original `MsgId`.
|
|
|
|
Queue: `RPUSH` / `BRPOPLPUSH` to `deliver:processing` / `LREM` ack. On boot `RequeueStale`. Dedup with `SETNX deliver:done:{msgId}`.
|
|
|
|
`DeliverJob` flags: `ExcludeDevice`, `NotPush`, `NotMailbox`. Sender device does not get `MESSAGE`; other devices of the sender must.
|
|
|
|
Inbox: Redis ZSET `im:dialog:unread|read:{uid}`, preview, unread hash. Mailbox MySQL is only missed push + control events (recall/kick/friend). Never write `NEW_MESSAGE` mailbox for a successful online push.
|
|
|
|
P2P conversation key is `(user_small, user_big)`. Sync messages with `id > last_msg_id`.
|
|
|
|
`messages.content` is a BLOB of serialized JSON bytes for a typed payload (text/image/voice/video/emoji/gif/file/location/system). Do not store a raw string. Media bytes stay in object storage; content holds the object key plus metadata.
|