160 lines
9.7 KiB
Markdown
160 lines
9.7 KiB
Markdown
# ADR-011 — Chính sách resilience chung khi đối tác thanh toán/vận chuyển bên ngoài lỗi (timeout/retry/fallback)
|
|
|
|
*Tên file: `adr/ADR-011_chinh-sach-resilience-doi-tac-ngoai.md`*
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Status** | `Proposed` |
|
|
| **Date** | 2026-09-15 |
|
|
| **Người quyết** | SA + Tech Lead (tích hợp — `decision-radar.md §5`) |
|
|
| **Người đề xuất** | SA (qua skill `sa-2-architecture`, hoạt động `adr`) |
|
|
| **Điểm radar** | **~6/10** |
|
|
| **Supersedes** | — |
|
|
| **Superseded by** | — |
|
|
| **Liên quan** | `ASR-013` · `CON-04` · `ARISK-03` · `ARISK-04` · `CMP-10`, `CMP-11` |
|
|
|
|
> ⚠️ **ADR bất biến sau khi `Accepted`.** Muốn đổi quyết định thì viết ADR mới có
|
|
> `Supersedes: ADR-011` và đổi trạng thái bản cũ thành `Superseded by`.
|
|
|
|
---
|
|
|
|
## 1. Bối cảnh
|
|
|
|
Hệ thống phải tích hợp đúng 4 đối tác đã chốt: VNPay, Momo (thanh toán), GHN, GHTK (vận chuyển,
|
|
có fallback chéo) — `CON-04`. Không đối tác nào có sandbox/hợp đồng thật tại thời điểm này
|
|
(`CTX §4.2`). `ASR-013` yêu cầu một chính sách resilience **chung** cho cả 4 đối tác (timeout,
|
|
retry, idempotent) thay vì mỗi đội tự chọn một kiểu khác nhau — đây là quyết định "thiết lập tiền
|
|
lệ" theo `decision-radar.md §4` (ngoại lệ để nhỏ thành ADR): áp dụng cho mọi tích hợp đối tác
|
|
ngoài tương lai, không chỉ 4 đối tác hiện tại.
|
|
|
|
**Ràng buộc đang chi phối:**
|
|
|
|
| Nguồn | Nội dung |
|
|
|---|---|
|
|
| `ASR-013` | Chính sách timeout/retry/idempotent nhất quán cho VNPay/Momo/GHN/GHTK; GHN/GHTK cần fallback chéo |
|
|
| `CON-04` | 4 đối tác đã chốt danh tính, chưa có sandbox/hợp đồng thật |
|
|
| `ARISK-03` | VNPay/Momo — webhook chưa xác minh khả thi gần thời gian thực |
|
|
| `ARISK-04` | GHN/GHTK — cơ chế fallback chéo chưa kiểm chứng hoạt động đúng giữa 2 API khác nhau |
|
|
|
|
**Cái đã biết chắc / cái còn là giả định:**
|
|
|
|
| Điều | 🟢 Đã kiểm chứng / 🔴 Giả định | Bằng chứng |
|
|
|---|---|---|
|
|
| Danh tính 4 đối tác đã chốt (không phải chờ chọn) | 🟢 Đã kiểm chứng | `CON-04` |
|
|
| Timeout đề xuất VNPay/Momo 10s, GHN/GHTK 8s | 🔴 Giả định — kế thừa từ `SAD.md §3.4`, chưa kiểm chứng sandbox thật | `CTX §4.2` |
|
|
| Fallback GHN↔GHTK hoạt động đúng khi chuyển đổi API giữa chừng | 🔴 Giả định | `ARISK-04`, chưa có tài liệu API/sandbox thật |
|
|
|
|
## 2. Phương án đã cân nhắc
|
|
|
|
### PA-1 — Mỗi đội tự thiết kế timeout/retry riêng cho từng đối tác (không có chính sách chung)
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Mô tả** | Không có ADR/chuẩn chung — mỗi dev tích hợp VNPay/Momo/GHN/GHTK tự quyết định timeout/retry theo kinh nghiệm cá nhân |
|
|
| **Ưu** | Linh hoạt tối đa cho từng đối tác cụ thể |
|
|
| **Nhược** | Không nhất quán — dev khác nhau chọn số khác nhau, khó audit/thay đổi hàng loạt khi cần; đúng bẫy đã cảnh báo ở `GUIDE.md` ("Bỏ qua đường lỗi vì sẽ xử lý lúc code") |
|
|
| **Chi phí đảo ngược** | Cao — chuẩn hoá lại sau khi đã có nhiều cách làm khác nhau tốn công rà soát từng điểm tích hợp |
|
|
|
|
### PA-2 — Chính sách chung: timeout theo loại đối tác + retry có backoff + idempotency key bắt buộc, adapter riêng mỗi đối tác *(chọn)*
|
|
|
|
| | |
|
|
|---|---|
|
|
| **Mô tả** | Một chuẩn chung áp dụng cho mọi đối tác ngoài: timeout cụ thể theo loại (thanh toán 10s, vận chuyển 8s — đề xuất, chờ kiểm chứng sandbox), retry ≤3 lần với exponential backoff + jitter, idempotency key bắt buộc cho mọi lời gọi ghi; mỗi đối tác có một adapter/anti-corruption layer riêng để cô lập thay đổi API của họ |
|
|
| **Ưu** | Nhất quán, dễ audit và thay đổi hàng loạt; adapter riêng giúp thay đổi API một đối tác không ảnh hưởng đối tác khác; đặt tiền lệ cho đối tác tương lai (khớp `decision-radar.md §4`) |
|
|
| **Nhược** | Cần thời gian thiết kế chuẩn chung trước khi bắt tay code từng đối tác; timeout cụ thể vẫn là đề xuất chưa kiểm chứng sandbox thật |
|
|
| **Chi phí đảo ngược** | Thấp — điều chỉnh số cụ thể (timeout, số lần retry) sau khi có sandbox thật là thay đổi cấu hình, không phải viết lại kiến trúc |
|
|
|
|
### Bảng so sánh
|
|
|
|
| Tiêu chí | PA-1 (Tự do từng đội) | PA-2 (Chuẩn chung + adapter) |
|
|
|---|---|---|
|
|
| Nhất quán, dễ audit | ❌ | ✅ |
|
|
| Đặt tiền lệ cho đối tác tương lai | ❌ | ✅ |
|
|
| Cô lập thay đổi API một đối tác | 🔶 Tuỳ đội | ✅ (adapter riêng) |
|
|
| Effort thiết kế trước khi code | Thấp | Trung bình |
|
|
|
|
## 3. Quyết định
|
|
|
|
> **Chọn PA-2 — Chính sách resilience chung (timeout theo loại đối tác, retry backoff+jitter,
|
|
> idempotency key bắt buộc) + adapter riêng cho mỗi đối tác.**
|
|
|
|
**Vì sao:** Đây là quyết định thiết lập tiền lệ cho mọi tích hợp đối tác ngoài hiện tại và tương
|
|
lai (`decision-radar.md §4`) — không nhất quán ngay từ đầu sẽ tốn công chuẩn hoá lại sau, đúng
|
|
bẫy đã cảnh báo ở `GUIDE.md`.
|
|
|
|
**Phạm vi áp dụng:** VNPay, Momo, GHN, GHTK, Email/SMS Provider, và mọi đối tác ngoài tương lai.
|
|
|
|
### Điều kiện chuyển `Proposed → Accepted`
|
|
|
|
| Điều kiện | Ai xác nhận | Trạng thái hiện tại |
|
|
|---|---|---|
|
|
| Có sandbox thật của cả 4 đối tác để kiểm chứng timeout cụ thể | Tech Lead | Chưa có (`CON-04`, `ARISK-03`/`04`) |
|
|
| Kiểm chứng fallback GHN↔GHTK hoạt động đúng | Tech Lead | Chưa kiểm chứng |
|
|
| Không bắt buộc POC theo `decision-radar.md §6` (không phải con số hiệu năng lớn) nhưng cần sandbox thật | — | Chờ sandbox |
|
|
|
|
## 4. Phương án bị loại và lý do
|
|
|
|
| Phương án | Loại vì | Gắn với | Điều kiện nào thì xét lại |
|
|
|---|---|---|---|
|
|
| PA-1 — Mỗi đội tự thiết kế riêng | Không nhất quán, khó audit/thay đổi hàng loạt; vi phạm nguyên tắc "đường lỗi không thể xử lý lúc code" | `GUIDE.md` "Bẫy thường gặp" | Không xét lại — đây là anti-pattern đã có cảnh báo rõ trong bộ SA |
|
|
|
|
## 5. Hệ quả
|
|
|
|
**Hệ quả tích cực**
|
|
|
|
- Nhất quán, dễ audit và thay đổi hàng loạt khi cần đổi chính sách retry/timeout
|
|
- Adapter riêng cô lập thay đổi API một đối tác, không lan sang đối tác khác
|
|
|
|
**Hệ quả tiêu cực phải sống chung**
|
|
|
|
- Cần thời gian thiết kế chuẩn chung trước khi từng đội bắt tay code — có thể chậm hơn PA-1 ở
|
|
giai đoạn đầu
|
|
- Timeout cụ thể (10s/8s) vẫn là đề xuất chưa kiểm chứng, có thể cần điều chỉnh khi có sandbox
|
|
|
|
**Cái quyết định này khoá lại**
|
|
|
|
| Muốn đổi về sau thì | Tốn |
|
|
|---|---|
|
|
| Bỏ chuẩn chung, để từng đối tác tự do sau khi đã có nhiều adapter theo chuẩn | Không tốn nhiều nếu chỉ đổi số cụ thể; tốn nhiều nếu đổi cấu trúc adapter |
|
|
|
|
**Việc phát sinh**
|
|
|
|
| Việc | Chủ | Hạn | Ghi ở đâu |
|
|
|---|---|---|---|
|
|
| Đàm phán sandbox 4 đối tác | Tech Lead + PM | Trước GĐ2 `ICD` hoàn tất | `ARISK-03`, `ARISK-04` |
|
|
| Thiết kế chi tiết từng phụ thuộc (4 câu hỏi D6) | SA (hoạt động `fail`) | GĐ2 tiếp theo | `FAIL_e-commerce` |
|
|
| Viết integration test cho fallback GHN↔GHTK | Tech Lead | GĐ2/GĐ3 | `FIT` (ứng viên) |
|
|
|
|
## 6. Cách kiểm chứng quyết định này được tuân thủ
|
|
|
|
| Cách kiểm | Công cụ | Chạy ở đâu | `FIT` |
|
|
|---|---|---|---|
|
|
| Mọi lời gọi ghi tới đối tác ngoài có idempotency key | Code review/lint + integration test | CI | `FIT-14` (ứng viên) |
|
|
| Retry có backoff+jitter, không retry storm khi đối tác hồi phục | Integration test giả lập đối tác chậm/hỏng | CI + staging | `FIT-15` (ứng viên) |
|
|
| Fallback GHN→GHTK kích hoạt đúng khi GHN lỗi | Integration test riêng cho luồng fallback | Staging, cần sandbox thật | — |
|
|
|
|
## 7. Điều kiện xét lại
|
|
|
|
| Dấu hiệu | Ngưỡng | Ai theo dõi |
|
|
|---|---|---|
|
|
| Sandbox thật cho thấy timeout đề xuất sai lệch nhiều | Timeout thật khác đề xuất > 50% | Tech Lead |
|
|
| Fallback GHN↔GHTK thất bại trong kiểm thử/production | Bất kỳ lần nào | Tech Lead/SRE |
|
|
|
|
## 8. Tham chiếu
|
|
|
|
- POC: Không bắt buộc — cần sandbox thật để kiểm chứng đầy đủ
|
|
- Bài đo: `FIT-14`, `FIT-15` (ứng viên GĐ3)
|
|
- Tài liệu ngoài: `CTX_e-commerce_v1.0.md §4.2` (trạng thái đối tác), `ARISK_e-commerce_v1.0.md §3 ARISK-03/04`
|
|
- Thảo luận: `ASR_e-commerce_v1.0.md §B2 ASR-013`
|
|
|
|
## 9. Review log (không đổi Status)
|
|
|
|
| Ngày | Người review | Vai trò | Quyết định | Lý do chưa chuyển `Accepted` |
|
|
|---|---|---|---|---|
|
|
| 2026-09-15 | Điều phối dự án (thay mặt Tech Lead, chế độ chạy thử) | Tech Lead (ký thay, ngoại lệ `DEC-01`) | `Reviewed (Proposed giữ nguyên)` — nội dung đủ làm cơ sở thiết kế tiếp (`icd`/`dat`/`sec`/`inf`/`fail`) | Chưa có chữ ký thật Tech Lead; cần chạy thử trên sandbox đối tác ngoài trước khi chốt |
|
|
|
|
> Đây là ghi nhận **review nội dung**, không phải "sign" theo nghĩa gate: `Status` giữ nguyên
|
|
> `Proposed`. Xem `00-index/ADL_e-commerce.md` (Change Log — Review 2026-09-15) và `ADL §8`
|
|
> "Việc phải làm" cho điều kiện chuyển `Accepted`. Confidence tổng thể của lượt review: 🔴 —
|
|
> `AG2` chưa ký.
|