Files
sys-analysis-design/.claude/skills/ba-3-specification/templates/srs-part2/batch-job.md
2026-09-22 13:46:36 +07:00

8.1 KiB
Raw Blame History

PART 2 — biến thể batch-job

Dùng khi PRODUCT = batch-job — job chạy theo lịch, không giao diện: đối soát đêm, sinh báo cáo định kỳ, dọn dữ liệu, gửi thông báo hàng loạt. Cắm khối này vào chỗ PART 2 của ../srs.md.

Tiêu chí G3 riêng của biến thể này: mỗi job có lịch + cửa sổ + phụ thuộc · quy tắc xử lý từng bản ghi đầy đủ · đã trả lời xong idempotency và thất bại giữa chừng · có kế hoạch cảnh báo và người trực.

Phân biệt với data-pipeline: pipeline có sản phẩm là dữ liệu để phân tích (cần data contract, lineage, đối soát nguồn–đích); batch-job có sản phẩm là việc được làm xong (cần idempotency, checkpoint, cảnh báo). Job vừa di chuyển dữ liệu lớn vừa làm việc nghiệp vụ ⇒ nạp cả hai biến thể.


2.1 Danh sách job

ID Job Làm gì Lịch Cửa sổ cho phép Phụ thuộc job nào Khối lượng/lần
JOB-01 Hằng ngày 01:00 01:00–05:00 JOB-00 xong ~… bản ghi

Cột Cửa sổ cho phép — job phải xong trước mấy giờ, và vì sao (nghiệp vụ nào bắt đầu lúc đó). Không có cột này thì không ai biết chạy chậm bao lâu là sự cố.

2.2 Sơ đồ phụ thuộc

flowchart LR
    J00["JOB-00 · 02:00 Nạp dữ liệu"]
    J01["JOB-01 · 02:30 Đối soát"]
    J02["JOB-02 · 03:00 Gửi báo cáo"]
    STOP(["⛔ Dừng chuỗi · cảnh báo trực đêm"])

    J00 -->|xong| J01
    J01 -->|xong| J02
    J00 -->|thất bại| STOP
    J01 -->|thất bại| STOP

Nhãn node mang giờ chạy; ID khớp cột ID bảng §2.1.

🔴 Vẽ cả cạnh thất bại. Sơ đồ chỉ có đường "xong" bỏ sót đúng câu hỏi quan trọng nhất: job trước hỏng thì job sau chạy hay dừng.

Bảng đi kèm (quy tắc W13):

Job Phụ thuộc Job trước thất bại ⇒ Chạy với dữ liệu cũ có nguy hiểm không Ai được báo
JOB-01 JOB-00 Dừng, không chạy 🔴 Có — đối soát trên dữ liệu thiếu ra kết quả sai Trực đêm
JOB-02 JOB-01 Dừng, không gửi báo cáo 🔴 Có — gửi báo cáo sai còn tệ hơn không gửi Trực đêm + kế toán

Cột áp chót là cột quyết định: dữ liệu cũ vô hại ⇒ cho chạy tiếp; nguy hiểm ⇒ phải dừng. Không trả lời được ⇒ OQ, đừng mặc định cho chạy.


2.3 JOB-01 — <Tên job>

2.3.1 Định danh

Kích hoạt bởi Lịch / Sự kiện / Gọi tay
Đầu vào (bảng, file, hàng đợi — và phạm vi: ngày nào, trạng thái nào)
Đầu ra (bản ghi được cập nhật, file sinh ra, thông báo gửi đi)
Thời gian chạy dự kiến ~… phút với khối lượng bình thường
Chạy bao lâu thì coi là treo
Có thể chạy đồng thời nhiều bản không 🔴 Không ⇒ cơ chế khoá là gì

2.3.2 Phạm vi xử lý

Chọn bản ghi nào để xử lý (điều kiện chính xác)
Bản ghi đã xử lý rồi nhận biết bằng gì 🔴 (cột trạng thái? bảng log? mốc thời gian?)
Thứ tự xử lý có quan trọng không
Giới hạn số bản ghi mỗi lần chạy (và phần còn lại xử lý khi nào)

2.3.3 Quy tắc xử lý từng bản ghi

Đây là phần thay thế cho "bảng field" của biến thể screen — phải cụ thể ngang vậy.

# Điều kiện Hành động Kết quả ghi vào đâu BR
1 BR-0nn

Bản ghi lỗi giữa chừng:

Tình huống Xử lý Ghi log gì
Dữ liệu bản ghi không hợp lệ Bỏ qua và tiếp tục / Dừng cả job
Gọi hệ thống ngoài thất bại Retry mấy lần? Rồi sao?

🔴 "Bỏ qua và tiếp tục" phải kèm ngưỡng. Bỏ qua 3 bản ghi là bình thường; bỏ qua 30% số bản ghi là sự cố nhưng job vẫn báo "thành công" — đó là chế độ hỏng im lặng.

Ngưỡng tỷ lệ lỗi để job tự đánh dấu thất bại > …%

2.3.4 Idempotency — chạy lại

🔴 Câu hỏi bắt buộc, không được để trống:

Câu hỏi Trả lời
Chạy lại cùng một ngày hai lần ⇒ kết quả có giống lần đầu không? ✅/❌
Nếu ❌: hậu quả cụ thể là gì (gửi email hai lần? cộng tiền hai lần?)
Nếu ❌: quy trình dọn trước khi chạy lại
Ai được phép chạy lại
Chạy lại có cần khoảng thời gian cụ thể không

Job gửi thông báo, ghi bút toán, gọi API bên ngoài mà không idempotent là rủi ro nghiêm trọng — nêu rõ trong RISK chứ không chỉ ghi ở đây.

2.3.5 Thất bại giữa chừng

Có checkpoint không ✅/❌ — lưu ở đâu, mức nào (mỗi bản ghi? mỗi lô?)
Chạy lại tiếp tục từ checkpoint hay từ đầu
Có rollback không Toàn bộ / Không có / Từng lô
Trạng thái dở dang có làm hỏng nghiệp vụ khác không 🔴 (job sau đọc dữ liệu chưa xong)
Cách nhận biết job đang chạy dở vs. đã xong

2.3.6 Chạy tay

Ai được chạy tay
Tham số truyền được (ngày nào, phạm vi nào)
Có cần phê duyệt không (bắt buộc nếu RIGOR = strict)
Chạy tay có ghi vết khác chạy tự động không

2.4 Trạng thái tương đương "màn hình rỗng"

Tình huống Job làm gì Coi là thành công?
Không có bản ghi nào thoả điều kiện Kết thúc, ghi log "0 bản ghi" ✅ Có — không phải lỗi
Đầu vào chưa sẵn sàng (job trước chưa xong) Chờ / Bỏ qua lần này / Báo lỗi
Chạy đúng lịch nhưng hôm đó nghỉ lễ

🔴 Phân biệt "không có gì để làm" với "không lấy được dữ liệu". Cả hai đều ra 0 bản ghi nhưng ý nghĩa ngược nhau, và gộp chúng làm sự cố bị bỏ qua nhiều ngày.

2.5 Cảnh báo và vận hành

Sự kiện Mức Báo cho ai Qua kênh nào Trong bao lâu
Job thất bại 🔴 Ngay
Job chạy quá cửa sổ cho phép 🔴 Ngay
Tỷ lệ bản ghi lỗi vượt ngưỡng 🟠 Ngay
Job không chạy (lịch không kích hoạt) 🔴 Sau … phút quá giờ

🔴 Dòng cuối là dòng hay bị quên nhất. Job thất bại thì có cảnh báo; job không chạy thì im lặng hoàn toàn — không có gì để báo lỗi. Phải có cơ chế phát hiện "đến giờ mà chưa thấy job nào bắt đầu".

Ai trực ban đêm
Sổ tay xử lý sự cố ở đâu (đây là MANUAL của GĐ5 với loại sản phẩm này)
Hỏng bao lâu thì phải báo người dùng nghiệp vụ

2.6 Nghiệm thu — thay cho UAT thông thường

# Cách kiểm Tiêu chí đi tiếp
1 Chạy trên dữ liệu sao chép từ môi trường thật Kết quả khớp với xử lý tay trên mẫu … bản ghi
2 Chạy song song với cách làm cũ ≥ 1 chu kỳ nghiệp vụ Sai lệch = 0, hoặc mọi sai lệch giải thích được
3 Thử chạy lại Kết quả không đổi (nếu idempotent)
4 Thử ngắt giữa chừng rồi chạy lại Không mất, không trùng bản ghi

Bước 4 hay bị bỏ, và nó là bước duy nhất chứng minh §2.3.5 hoạt động thật.