feat: update app errors

This commit is contained in:
2025-12-29 14:54:05 +08:00
parent 8fa3d18a9c
commit 8c4bc55f45
9 changed files with 86 additions and 55 deletions

View File

@@ -15,6 +15,8 @@ This file condenses `backend/docs/dev/http_api.md` + `backend/docs/dev/model.md`
- DO regenerate code after changes (routes/docs/models).
- MUST: in `backend/app/services`, prefer the generated GORM-Gen DAO (`backend/database/models/*`) for DB access; treat raw `*gorm.DB` usage as a last resort.
- MUST: When building queries in services, improve readability by using the assignment: `tbl, query := models.<Table>Query.QueryContext(ctx)`. Then use `tbl` for field references (e.g., `tbl.ID.Eq(...)`) and `query` for chaining methods.
- MUST: in `services`, when an error occurs (e.g., DB error, third-party API error), NEVER return a generic `errorx.ErrXxx` alone if there is an underlying `err`. ALWAYS use `errorx.ErrXxx.WithCause(err)` to wrap the original error. This ensures the centralized Logger captures the full context (file, line, root cause) while the client receives a friendly message and a unique Error ID for tracking.
- MUST: all chainable methods on `AppError` (`WithCause`, `WithMsg`, `WithData`, etc.) are thread-safe and return a new instance (clone). Use them freely to add context to global error variables.
- MUST: service-layer transactions MUST use `models.Q.Transaction(func(tx *models.Query) error { ... })`; DO NOT use raw `*_db.Transaction(...)` / `db.Transaction(...)` in services unless Gen cannot express the required operation.
- MUST: after adding/removing/renaming any files under `backend/app/services/`, run `atomctl gen service --path ./app/services` to regenerate `backend/app/services/services.gen.go`; DO NOT edit `services.gen.go` manually.
- DO add `// @provider` above every controller/service `struct` declaration.
@@ -248,7 +250,7 @@ In this case:
- `backend/app/events/subscribers/<snake_case>.go`subscriber实现 `contracts.EventHandler`,负责 `Topic()` + `Handler(...)`
- 生成后:按项目约定运行一次 `atomctl gen provider`(用于刷新 DI/provider 生成文件)。
### Topic 约定
### Topic约定
- 统一在 `backend/app/events/topics.go` 维护 topic 常量,避免散落在各处形成“字符串协议”。
- topic 字符串建议使用稳定前缀(例如 `event:`),并使用 `snake_case` 命名。
@@ -297,7 +299,7 @@ Common types:
- `Kind` 建议与业务枚举/事件类型对齐,便于 SQL/报表按 `kind` 过滤。
- `Data` 写入对应 payload 的 JSONpayload 可以是多个不同 struct
- 读取时:
- 先 `snap := model.Snapshot.Data()`,再 `switch snap.Kind` 选择对应 payload 结构去 `json.Unmarshal(snap.Data, &payload)`。
- 先 `snap := model.Snapshot.Data()`,再 `switch snap.Kind` 选择对应 payload结构去 `json.Unmarshal(snap.Data, &payload)`。
- 兼容历史数据(旧 JSON 没有 kind/data`UnmarshalJSON` 可以将其标记为 `legacy` 并把原始 JSON 放入 `Data`,避免线上存量读取失败。
---
@@ -462,4 +464,4 @@ func (s *XxxTestSuite) Test_Method() {
So(got, ShouldBeNil)
})
}
```
```