Bối cảnh nghiệp vụ
Module này xử lý vòng đời bài viết: tạo post, reply, quote, repost, like, hide, report, update, delete, feed và semantic search.
Ví dụ thực tế: client gọi endpoint của post, server kiểm tra token nếu route yêu cầu, validate dữ liệu, gọi service đúng domain, rồi ghi DB/cache hoặc enqueue job theo đúng nhánh trong code.
Luồng chính — Happy Path
Request vào route. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.
Middleware auth/validate chạy. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.
Controller gọi service. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.
Service áp dụng rule nghiệp vụ. Đây là bước quan trọng nhất vì service quyết định request có được ghi dữ liệu, enqueue job hoặc bị trả lỗi.
Repository/worker/provider thực thi. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.
Response trả về client. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.
Business Rules — Quy tắc nghiệp vụ
| Rule ID | Tên rule | Điều kiện kích hoạt | Hành động | Ví dụ minh họa | File kiểm tra |
|---|---|---|---|---|---|
| BR-POST-001 | Content bắt buộc 1..5000 ký tự | Create/update | Zod reject request sai format | Post rỗng không vào service | post.dto.ts |
| BR-POST-002 | Mention tối đa 5 và không trùng user | Create/reply/quote | DTO + service kiểm tra duplicate và user tồn tại | Mention trùng bị từ chối | post.dto.ts + post.service.ts |
| BR-POST-003 | Visibility/replyPermission chuẩn hóa enum | Create/update | Sai enum trả BadRequest | public được normalize thành PUBLIC | post.dto.ts |
| BR-POST-004 | Update/delete chỉ owner được làm | PATCH/DELETE | So sánh post.userId với req.user.sub | User A không sửa post B | post.service.ts |
| BR-POST-005 | Like ghi nóng ở Redis trước | POST like | Set Redis + list likes_add/likes_remove, worker sync DB sau | Client thấy count nhanh hơn DB | post.service.ts + like.worker.ts |
| BR-POST-006 | Report không cho tự report | POST report | Target owner là reporter thì Forbidden | Không tự report post của mình | post.service.ts |
| BR-POST-007 | Post report và circle report không dùng lẫn type | POST report | Non-circle dùng POST, circle post dùng CIRCLE | Sai type bị BadRequest | post.service.ts |
[CẦN XÁC NHẬN], phần code hiện tại là stub, TODO hoặc trả dữ liệu mock.Validations — Kiểm tra dữ liệu đầu vào
Input Validation
| Field | Kiểu | Required | Rule | Lỗi nếu vi phạm | Ví dụ hợp lệ | Ví dụ không hợp lệ |
|---|---|---|---|---|---|---|
| Authorization | header | Có với route protected | Bearer access token nếu cần | 401 | Bearer eyJ... | missing |
| params | string | Tùy endpoint | Không rỗng theo DTO route | 400 | publicId/code | |
| query.take | number | Không | int dương, thường max 100 nếu DTO có | 400 | 20 | 1000 |
| body | object | Tùy endpoint | Theo DTO tương ứng | 400 | {"content":"Hello"} | {} thiếu field |
Business Validation
| Điều kiện kiểm tra | Khi nào chạy | Lỗi trả về | Lý do rule này tồn tại |
|---|---|---|---|
| Content bắt buộc 1..5000 ký tự | Create/update | Zod reject request sai format | Ngăn dữ liệu sai đi sâu vào DB hoặc worker. |
| Mention tối đa 5 và không trùng user | Create/reply/quote | DTO + service kiểm tra duplicate và user tồn tại | Ngăn dữ liệu sai đi sâu vào DB hoặc worker. |
| Visibility/replyPermission chuẩn hóa enum | Create/update | Sai enum trả BadRequest | Ngăn dữ liệu sai đi sâu vào DB hoặc worker. |
| Update/delete chỉ owner được làm | PATCH/DELETE | So sánh post.userId với req.user.sub | Ngăn dữ liệu sai đi sâu vào DB hoặc worker. |
| Like ghi nóng ở Redis trước | POST like | Set Redis + list likes_add/likes_remove, worker sync DB sau | Ngăn dữ liệu sai đi sâu vào DB hoặc worker. |
Edge Cases — Trường hợp ngoại lệ
Like count trả theo Redis sCard, DB đồng bộ sau.
Nếu không hiểu điểm này, QA có thể viết thiếu case hoặc frontend có thể hiển thị trạng thái sai.
Visibility FRIEND được document nhưng read filtering chưa enforce đầy đủ.
Nếu không hiểu điểm này, QA có thể viết thiếu case hoặc frontend có thể hiển thị trạng thái sai.
save() là no-op.
Nếu không hiểu điểm này, QA có thể viết thiếu case hoặc frontend có thể hiển thị trạng thái sai.
Report AI worker có thể tự hide hoặc đánh dấu disinformation.
Nếu không hiểu điểm này, QA có thể viết thiếu case hoặc frontend có thể hiển thị trạng thái sai.
Post list cache dùng version key.
Nếu không hiểu điểm này, QA có thể viết thiếu case hoặc frontend có thể hiển thị trạng thái sai.
Error Handling — Xử lý lỗi
| Tình huống lỗi | Nguyên nhân | HTTP Status | Error Code | Message trả về | Cách recover |
|---|---|---|---|---|---|
| Unauthorized | Thiếu/sai token ở route protected | 401 | UNAUTHORIZED | Token invalid | Login lại hoặc refresh token. |
| Validation failed | Zod schema không pass | 400 | VALIDATION_FAILED | Validation failed | Client sửa field sai. |
| Resource not found | Repository không tìm thấy record | 404 | NOT_FOUND | Resource not found | Refresh dữ liệu. |
| Forbidden | User không có quyền hoặc role không đúng | 403 | FORBIDDEN | Forbidden | Ẩn action trong UI. |
| External dependency fail | Redis/DB/provider lỗi | 500 | INTERNAL_SERVER_ERROR | Internal server error | On-call kiểm tra provider/log. |
State Machine / Vòng đời
Một entity/job trong module này có thể đi qua các trạng thái sau: POST, REPLY, REPOST, QUOTE, isDeleted/isHidden/isDisinformation.
| Từ trạng thái | Hành động/Event | Đến trạng thái | Ai được phép | Điều kiện thêm |
|---|---|---|---|---|
| POST | create/enqueue | REPLY | System hoặc user theo route | Theo rule service |
| REPLY | process/update | REPOST | System hoặc user theo route | Theo rule service |
| REPOST | process/update | QUOTE | System hoặc user theo route | Theo rule service |
| QUOTE | process/update | isDeleted/isHidden/isDisinformation | System hoặc user theo route | Theo rule service |
Side Effects — Tác dụng phụ
| Hành động | Khi nào xảy ra | Đồng bộ hay bất đồng bộ | Nếu thất bại thì sao? |
|---|---|---|---|
| DB read/write | Khi service cần dữ liệu bền vững | Đồng bộ | Request fail nếu DB fail. |
| Cache/queue/realtime | Nếu module gọi Redis/Pusher/jobs | Tùy flow | Có thể delay hoặc fail riêng. |
| External API | Nếu module gọi service ngoài | Bất đồng bộ hoặc đồng bộ | Phụ thuộc cấu hình provider. |
FAQ — Câu hỏi thường gặp
| Câu hỏi | Trả lời |
|---|---|
| Tôi bắt đầu đọc module post từ đâu? | Bắt đầu ở src/modules/post/post.routes.ts, sau đó đi sang controller và service. |
| Lỗi validation nằm ở đâu? | Ở DTO Zod và middleware validate(). Route nào không gọi validate() thì không có lớp check này. |
| Side effect có chạy trong cùng request không? | Tùy flow. Nếu có producer/worker thì side effect chạy bất đồng bộ sau response. |
| Có chỗ nào chưa hoàn chỉnh không? | Xem phần Gotchas và các dòng [CẦN XÁC NHẬN]. |
| QA nên test gì trước? | Happy path, thiếu token, sai DTO, resource không tồn tại, và side effect fail/defer. |