64 lines
2.1 KiB
Markdown
64 lines
2.1 KiB
Markdown
---
|
|
name: spark-im-v3
|
|
description: >-
|
|
Implements Spark IM modular monolith per architecture V3. Use when writing or
|
|
reviewing spark-server Go code, TCP/gnet, Gin HTTP, messages, deliver queue,
|
|
inbox ZSET, Nginx 443 SNI, PROXY protocol, or SEND_ACK. Trigger terms: IM,
|
|
MsgId, TaskPool, deliver:queue, SYNC_INBOX, gnet, RealIP.
|
|
---
|
|
|
|
# Spark IM V3
|
|
|
|
Read [invariants.md](invariants.md) before changing send/sync/transport. Full design: `docs/architecture-v3.md`. Lint: `.golangci.yaml`.
|
|
|
|
## Layout
|
|
|
|
```text
|
|
cmd/server process entry
|
|
internal/bootstrap config, lifecycle
|
|
internal/transport/http Gin, loopback :8080
|
|
internal/transport/tcp gnet EventLoop + TaskPool + Frame
|
|
internal/module/* Application services (HTTP and TCP share these)
|
|
internal/infrastructure mysql, redis, id, logger, push
|
|
```
|
|
|
|
Module files: `service.go` + entity types + `repository.go` interface. No extra DDD layer.
|
|
|
|
## Send path (must keep this order)
|
|
|
|
1. TaskPool (not EventLoop)
|
|
2. Permission (friend / block / group mute) — fail before INSERT
|
|
3. Snowflake MsgId (or client MsgId within ±5m)
|
|
4. MySQL txn: `messages` + `conversations.last_msg_id`
|
|
5. `DeliverQueue.Push` (reliable list)
|
|
6. `SEND_ACK`
|
|
|
|
If step 5 fails, do not ACK. Client retries the same `client_msg_id`.
|
|
|
|
## EventLoop vs pools
|
|
|
|
| Pool | Owns |
|
|
|------|------|
|
|
| gnet EventLoop | PROXY, TLS, Frame, heartbeat, PUSH_ACK, Submit |
|
|
| TaskPool | AUTH, SEND, SYNC, READ, RECALL, MySQL |
|
|
| Deliver Worker | ZSET inbox, Session.Send, mailbox on push fail, PushNotifier |
|
|
|
|
## Commands
|
|
|
|
`AUTH HEARTBEAT GENERATE_MSG_ID SEND_MESSAGE SEND_ACK MESSAGE PUSH_ACK READ RECALL SYNC_INBOX SYNC_MESSAGES KICK`
|
|
|
|
Media: HTTP upload credential, message content is object key only. Frame max 64KB. Compress body over 512B.
|
|
|
|
## When adding a feature
|
|
|
|
- HTTP writes must enqueue deliver jobs for online devices.
|
|
- List/unread go to Redis ZSET, not MySQL row-per-member.
|
|
- New goroutine I/O does not belong in `OnTraffic`.
|
|
- Run `make lint` (funlen 100).
|
|
|
|
## Additional resources
|
|
|
|
- [invariants.md](invariants.md)
|
|
- [send-path.md](send-path.md)
|
|
- `docs/architecture-v3.md`
|