| .cursor | ||
| api/proto | ||
| cmd | ||
| configs | ||
| deploy | ||
| docs | ||
| examples/android | ||
| internal | ||
| migrations | ||
| .dockerignore | ||
| .gitignore | ||
| .golangci.yaml | ||
| AGENTS.md | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| Makefile | ||
| README.md | ||
spark-server
Spark IM modular monolith. Architecture: docs/architecture-v3.md.
- Go 1.26
- Gin HTTP on
127.0.0.1:8080. JSON envelope{"code","msg","request_id","data"}. Docs:GET /docs(API),/docs/enums,/docs/errors. Spec:GET /openapi.yaml. - Probes:
GET /healthzliveness;GET /readyzreadiness (HTTP 503 when MySQL/Redis/task pool/accepting are not ready).env: prod(orSPARK_ENV=prod) rejects empty MySQL DSN, empty Redis, and the default JWT secret. - Logs: zap to console and/or rotating file (
log.console/log.file). GORM SQL goes through the same zap.request_idis server-generated and returned in the response body (also asX-Request-ID). - gnet TCP on loopback (local
127.0.0.1:8090; ECS Docker127.0.0.1:9090because host:9000is rustfs). gnet v2.10 has no built-in TLS; Nginx terminates IM TLS and forwards PROXY+plaintext. Sample:deploy/nginx/.make deploywrites image/config/logs under/data/spark-server/. - TCP Frame body is JSON
{code,msg,request_id,data}. AUTH body:{"token","device_id","app_version","language"}. - Public entry is Nginx
:443only (SNI split)
make start
make migrate
make lint
make start runs cmd/server against configs/config.yaml (override with make start CONFIG=path/to.yaml). make run builds bin/spark-server first, then starts that binary.
Agent conventions live in .cursor/rules and .cursor/skills/spark-im-v3. Lint conventions live in .golangci.yaml.