Feature: Đăng bài mới ·
Hỗ trợ: text + ảnh + video + hashtag + @mention ·
Module: PostService
4
Loại bài đăng
post · reply · quote · repost
5
Trường dữ liệu
content · media · topic · mentions · visibility
5000
Ký tự tối đa
content max length
5
Mention tối đa
@user / bài viết
User Perspective
Bước 1
Người dùng mở màn hình tạo bài viết mới, nhập nội dung văn bản (bắt buộc, tối thiểu 1 ký tự).
Bước 2
Có thể đính kèm ảnh hoặc video (hệ thống upload trước qua module Upload, nhận lại id, key, url).
Bước 3
Gõ #hashtag — hệ thống lưu thành topic của bài viết (1 topic / bài).
Bước 4
Gõ @username — hệ thống kiểm tra user tồn tại, lưu vào bảng PostMention (tối đa 5 người).
Bước 5
Chọn quyền trả lời (Mọi người / Chỉ người theo dõi / Không ai) và chế độ hiển thị (Public / Friends Only / Private).
Bước 6
Nhấn "Đăng" → bài viết xuất hiện trên trang cá nhân và News Feed.
Luồng xử lý tạo bài
Mũi tên liền = luồng đồng bộ. Bước Pinecone chạy async sau transaction, không ảnh hưởng response.
Step-by-Step Detail
#
Bước
Mô tả nghiệp vụ (dễ hiểu)
Trạng thái
01
Validate dữ liệu đầu vào
Zod schema
Hệ thống kiểm tra: nội dung bắt buộc (1–5000 ký tự), media là mảng object có id/key/url, mentions tối đa 5 người, visibility và replyPermission phải đúng enum.
done
02
Xác thực người dùng
resolveUser
Tìm user trong DB theo userId từ JWT token. Nếu không tồn tại → trả lỗi 404. Nếu có → chụp "ảnh nhanh" thông tin user (tên, avatar, trạng thái xác minh) để lưu cùng bài viết.
done
03
Kiểm tra @mention
validateMentions
Nếu bài viết có @mention ai đó: kiểm tra ≤5 người, không trùng lặp, mỗi userId phải tồn tại thật trong hệ thống. Nếu sai → trả lỗi 400.
done
04
Tạo bài + gắn metadata
createInTransaction
Trong 1 giao dịch an toàn (transaction): tạo bản ghi bài viết → gắn topic (hashtag) + mention vào các bảng phụ. Nếu bất kỳ bước nào lỗi → rollback toàn bộ, bài không được tạo.
done
05
Index AI Search
addToPineconeQueue
Đẩy nội dung bài vào hàng đợi để AI tạo vector embedding (Pinecone). Giúp tìm kiếm bài viết theo ngữ nghĩa sau này. Chạy ngầm, không ảnh hưởng tốc độ phản hồi.
done
06
Upload media trước
Upload module
Ảnh/video phải được upload trước qua endpoint riêng (POST /upload), nhận lại id + url, rồi truyền vào khi tạo bài. Bài viết chỉ lưu liên kết, không xử lý file.
done
Implementation Progress
✅ Đã xong
Tạo bài text thuần — POST /posts
Đính kèm media (ảnh/video) qua mảng media[]
Validate DTO đầy đủ (Zod schema + custom refine)
@mention user (validate + lưu PostMention)
Hashtag/Topic (lưu TopicPost, normalize topic)
Visibility + ReplyPermission enum
Pinecone queue (AI search index)
Transaction an toàn (create + meta cùng tx)
⏳ Cần bổ sung
Hashtag tách riêng bảng (hiện chỉ lưu 1 topic/bài)
Thông báo realtime cho người được @mention
Giới hạn số lượng media (ảnh/video) tối đa
Preview link tự động (OG meta scraping)
Design Notes
UserSnapshot
Lưu bản sao thông tin user vào bài viết (denormalized). Khi user đổi tên/avatar, bài viết cũ vẫn hiển thị đúng thông tin lúc đăng.
Transaction
Tạo bài + gắn mention + gắn topic trong 1 transaction. Đảm bảo "tất cả hoặc không gì" — không bao giờ có bài viết thiếu metadata.
Media
Media upload tách riêng module — bài viết chỉ connect bằng id. Tránh coupling và cho phép upload trước khi soạn bài.
Pinecone
Chỉ bài gốc (type=POST) mới được index Pinecone. Reply/quote/repost sẽ được tìm thông qua bài gốc.