Checkpoint: Capstone service ngân hàng
Quiz
- Trong kiến trúc ba layer của service ngân hàng (handler, service, repository), layer nào là nơi duy nhất được phép nói chuyện với database?
- Service
- Repository
- AppState
- Handler
- Vì sao AppState trong axum phải implement Clone và bên trong thường bọc Arc?
- Vì Arc bắt buộc để dùng được extractor Json
- Vì nếu không Clone thì router không compile được route /health
- Vì Arc giúp serialize state thành JSON tự động
- Vì axum clone state cho mỗi request, nên cần clone rẻ qua Arc
- Đoạn code sau trong handler chuyển tiền vi phạm layer ở điểm nào rõ nhất?
async fn transfer(State(s): State<AppState>, Json(req): Json<TransferReq>) -> StatusCode {
let from = s.db.query("SELECT * FROM accounts WHERE id = $1", &[&req.from]).await;
if from.balance < req.amount { return StatusCode::BAD_REQUEST; }
StatusCode::OK
}
- Handler gọi thẳng database và chứa business rule kiểm tra số dư, đồng thời trả StatusCode trơn
- Handler dùng extractor Json thay vì tự parse body
- Handler nhận State<AppState> thay vì tự tạo AppState
- Handler trả về StatusCode thay vì String
- Vì sao phải claim idempotency key bên trong cùng transaction với việc trừ tiền, thay vì ghi key trước khi gọi pool.begin()?
- Vì nếu ghi key ngoài transaction, giao dịch rollback sẽ để lại key khiến retry bị coi là duplicate và tiền không bao giờ chuyển
- Vì ghi ngoài transaction khiến request_hash không được lưu
- Vì ghi ngoài transaction làm key bị trùng giữa các request song song
- Vì PostgreSQL không cho INSERT ngoài transaction
- Câu UPDATE nào chống overdraft đúng cách khi nhiều request chuyển tiền chạy song song?
- UPDATE accounts SET balance_minor = balance_minor - $1 WHERE id = $2 AND balance_minor >= $1, rồi kiểm tra rows_affected
- SELECT balance_minor ... FOR UPDATE, kiểm tra, rồi UPDATE trong cùng transaction
- UPDATE accounts SET balance_minor = balance_minor - $1 WHERE id = $2, rồi kiểm tra số dư sau khi trừ
- SELECT balance_minor FROM accounts WHERE id = $1, kiểm tra trong code, rồi UPDATE
- Khi một Transaction của sqlx bị drop mà chưa gọi commit, chuyện gì xảy ra?
- Chương trình panic
- Transaction được commit một nửa
- Connection bị treo vĩnh viễn trong pool
- sqlx tự rollback transaction đó
- Build trên CI không có DATABASE_URL nhưng vẫn dùng macro sqlx::query!. Cách xử lý chuẩn là gì?
- Đổi hết query! sang query() để không cần kiểm tra kiểu
- Trỏ CI vào database production để macro kiểm tra kiểu
- Đặt DATABASE_URL rỗng trong CI
- Chạy cargo sqlx prepare ở local, commit thư mục .sqlx và đặt SQLX_OFFLINE=true trên CI
- Để chống trừ tiền hai lần khi client retry, mỗi request chuyển tiền phải mang theo một ____ duy nhất, được claim trong cùng transaction với việc trừ tiền.
- Thuộc tính ____ tạo database riêng cho từng integration test và chạy migrations trước khi test bắt đầu.
- Hãy tự đánh giá mức độ hoàn thiện của capstone service ngân hàng của bạn dựa trên các tiêu chí nghiệm thu của module.
Sign in to submit answers.