Post · Business Logic

Nghiệp vụ — Post

Trang này mô tả đầy đủ các quy tắc, điều kiện, lỗi và side effects của module post.

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

1
src/modules/post/post.routes.ts

Request vào route. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.

2
src/modules/post/controller/post.controller.ts

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ó.

3
src/modules/post/service/post.service.ts

Controller gọi service. Bước này chuyển dữ liệu sang lớp tiếp theo theo pattern hiện có.

4
src/modules/post/dto/post.dto.ts

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.

5
src/modules/post/repository/post.repository.ts

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ó.

6
src/modules/post/repository/like.repository.ts

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 IDTên ruleĐiều kiện kích hoạtHành độngVí dụ minh họaFile kiểm tra
BR-POST-001Content bắt buộc 1..5000 ký tựCreate/updateZod reject request sai formatPost rỗng không vào servicepost.dto.ts
BR-POST-002Mention tối đa 5 và không trùng userCreate/reply/quoteDTO + service kiểm tra duplicate và user tồn tạiMention trùng bị từ chốipost.dto.ts + post.service.ts
BR-POST-003Visibility/replyPermission chuẩn hóa enumCreate/updateSai enum trả BadRequestpublic được normalize thành PUBLICpost.dto.ts
BR-POST-004Update/delete chỉ owner được làmPATCH/DELETESo sánh post.userId với req.user.subUser A không sửa post Bpost.service.ts
BR-POST-005Like ghi nóng ở Redis trướcPOST likeSet Redis + list likes_add/likes_remove, worker sync DB sauClient thấy count nhanh hơn DBpost.service.ts + like.worker.ts
BR-POST-006Report không cho tự reportPOST reportTarget owner là reporter thì ForbiddenKhông tự report post của mìnhpost.service.ts
BR-POST-007Post report và circle report không dùng lẫn typePOST reportNon-circle dùng POST, circle post dùng CIRCLESai type bị BadRequestpost.service.ts
Các rule trên được rút từ route/service/DTO/worker đã đọc. Nếu một rule ghi [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

FieldKiểuRequiredRuleLỗi nếu vi phạmVí dụ hợp lệVí dụ không hợp lệ
AuthorizationheaderCó với route protectedBearer access token nếu cần401Bearer eyJ...missing
paramsstringTùy endpointKhông rỗng theo DTO route400publicId/code
query.takenumberKhôngint dương, thường max 100 nếu DTO có400201000
bodyobjectTùy endpointTheo DTO tương ứng400{"content":"Hello"}{} thiếu field

Business Validation

Điều kiện kiểm traKhi nào chạyLỗi trả vềLý do rule này tồn tại
Content bắt buộc 1..5000 ký tựCreate/updateZod reject request sai formatNgăn dữ liệu sai đi sâu vào DB hoặc worker.
Mention tối đa 5 và không trùng userCreate/reply/quoteDTO + service kiểm tra duplicate và user tồn tạiNgăn dữ liệu sai đi sâu vào DB hoặc worker.
Visibility/replyPermission chuẩn hóa enumCreate/updateSai enum trả BadRequestNgăn dữ liệu sai đi sâu vào DB hoặc worker.
Update/delete chỉ owner được làmPATCH/DELETESo sánh post.userId với req.user.subNgăn dữ liệu sai đi sâu vào DB hoặc worker.
Like ghi nóng ở Redis trướcPOST likeSet Redis + list likes_add/likes_remove, worker sync DB sauNgăn dữ liệu sai đi sâu vào DB hoặc worker.

Edge Cases — Trường hợp ngoại lệ

!
Edge case 1

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.

!
Edge case 2

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.

!
Edge case 3

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.

!
Edge case 4

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.

!
Edge case 5

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ỗiNguyên nhânHTTP StatusError CodeMessage trả vềCách recover
UnauthorizedThiếu/sai token ở route protected401UNAUTHORIZEDToken invalidLogin lại hoặc refresh token.
Validation failedZod schema không pass400VALIDATION_FAILEDValidation failedClient sửa field sai.
Resource not foundRepository không tìm thấy record404NOT_FOUNDResource not foundRefresh dữ liệu.
ForbiddenUser không có quyền hoặc role không đúng403FORBIDDENForbiddenẨn action trong UI.
External dependency failRedis/DB/provider lỗi500INTERNAL_SERVER_ERRORInternal server errorOn-call kiểm tra provider/log.
Lỗi cần alert ngay: DB/Redis/worker/provider ngoài fail liên tục, vì các flow chính có thể trả 500 hoặc mất side effect như search, email, notification.

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.

POSTREPLYREPOSTQUOTEisDeleted/isHiddstarteventeventeventeventinvalid/reject
Node là trạng thái domain hoặc trạng thái job; mũi tên xanh là transition hợp lệ.
Từ trạng tháiHành động/EventĐến trạng tháiAi được phépĐiều kiện thêm
POSTcreate/enqueueREPLYSystem hoặc user theo routeTheo rule service
REPLYprocess/updateREPOSTSystem hoặc user theo routeTheo rule service
REPOSTprocess/updateQUOTESystem hoặc user theo routeTheo rule service
QUOTEprocess/updateisDeleted/isHidden/isDisinformationSystem hoặc user theo routeTheo rule service

Side Effects — Tác dụng phụ

Hành độngKhi nào xảy raĐồng bộ hay bất đồng bộNếu thất bại thì sao?
DB read/writeKhi service cần dữ liệu bền vữngĐồng bộRequest fail nếu DB fail.
Cache/queue/realtimeNếu module gọi Redis/Pusher/jobsTùy flowCó thể delay hoặc fail riêng.
External APINếu module gọi service ngoàiBấ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ỏiTrả 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.