# Theo dõi việc chạy ngầm theo từng loại

> Việc định kỳ, consumer hàng đợi, webhook xử lý nền, worker chạy lâu và CLI: bắt lỗi ở đâu, khi nào ghi chưa rõ, ai lo thử lại.

Việc chạy ngầm hỏng rất lặng lẽ: chẳng ai nhìn màn hình khi một hàng đợi đứng lúc 3 giờ sáng. Bài này chỉ ra, với từng loại việc thường gặp, **cần báo gì**, **bắt lỗi ở đâu**, và **khi nào kết quả là chưa rõ** chứ không phải lỗi. Bài dùng [monitor](https://belvador.dev/vi/docs/monitors/overview) cho lượt chạy và cách gửi lỗi thông thường cho exception.

Ba quy tắc luôn đúng:

- **Bắt ở ranh giới.** Báo lỗi ở nơi một đơn vị công việc kết thúc (một job, một tin nhắn, một webhook), không phải sâu trong các hàm phụ — nếu không cùng một lỗi sẽ bị báo nhiều lần.
- **"Đã nhận" không phải "đã xong".** HTTP 200 từ endpoint của bạn hay từ nhà cung cấp chỉ có nghĩa yêu cầu đã tới nơi. Hãy báo thành công khi hiệu lực đã được xác nhận.
- **Thử lại là việc của app.** Belvador ghi các lần thử và kết quả cuối; không bao giờ tự chạy lại.

## Job định kỳ (cron)

Mỗi job một monitor, với đúng lịch nó thật sự chạy. Bọc cả job trong `withMonitor` (hoặc API crons của SDK Sentry, hoặc `curl`):

- Lần này không có việc → `run.skip("nothing_due")`, tính là khoẻ. Đừng báo `ok` cho lượt lặng lẽ không làm gì vì một điều kiện tiên quyết thất bại — hãy ném lỗi hoặc báo lỗi.
- Thành công một phần (gửi được 500/520 hoá đơn) → báo các lỗi bạn biết bằng `captureException`, và tự quyết lượt chạy là `ok` hay lỗi theo quy tắc của bạn. Ghi quy tắc đó ngay trong code.

## Consumer hàng đợi

Hàng đợi không có lịch; rủi ro là việc tiêu thụ **dừng lại**. Dùng monitor **Theo chu kỳ** với `heartbeat` từ vòng lặp consumer — ví dụ mỗi lô một lần, hoặc mỗi phút khi rảnh — để consumer chết hiện ra thành **Bị lỡ**.

- Đừng tạo một lượt chạy cho mỗi tin nhắn: hàng nghìn lượt mỗi giờ che mất tín hiệu và chạm giới hạn 60 mỗi phút. Nếu một loại tin cụ thể quan trọng, cho nó monitor riêng.
- Với thử lại theo từng tin, truyền `runId` (id tin nhắn), `attempt` và `willRetry` để tin thành công ở lần thứ ba là một lượt khoẻ.
- Tin bị chuyển sang dead-letter queue là lỗi: ghi nó như một lỗi với loại tin làm tag (không bao giờ ghi nội dung tin).

## Webhook xử lý nền

Xác nhận nhanh, xử lý sau — và theo dõi phần xử lý, không phải phần xác nhận:

1. Handler HTTP lưu webhook và trả 200. Lỗi ở đây là lỗi request, được SDK thông thường báo.
2. Bước nền áp dụng webhook chạy trong `withMonitor` (monitor **Theo sự kiện**), để lỗi và quá giờ vẫn thấy được dù không bao giờ có chuyện "trễ".

Khi bước nền gọi nhà cung cấp và lần gọi hết thời gian chờ **sau khi** yêu cầu đã gửi đi, hiệu lực là chưa rõ: gọi `run.unknown("provider_timeout")`. Monitor ghi **Cần xem lại** cho tới khi có người kiểm.

## Worker và agent chạy lâu

Tiến trình chạy hàng giờ hay hàng ngày không thể là một lượt chạy. Báo sức khoẻ bằng `heartbeat` mỗi vài phút trên monitor theo chu kỳ, và bọc từng đơn vị việc nó làm (một lần đồng bộ, một lần xuất) bằng `withMonitor` riêng nếu các đơn vị đó có kỳ vọng riêng. Đặt thời gian chạy tối đa của monitor đơn vị bằng thời gian thật một đơn vị có thể mất; đơn vị bị treo khi đó hiện **Quá giờ**.

## Tiến trình ngắn và CLI

Tiến trình thoát ngay sau khi làm xong phải gửi trước khi thoát. Với SDK Belvador hay Sentry, gọi `await flush()` (Python: `sentry_sdk.flush()`) ở cuối; với `curl`, bản thân request đã chạy đồng bộ. Hàm serverless có giới hạn thời gian cứng nên báo lúc bắt đầu sớm, để hàm bị nền tảng dừng giữa chừng hiện ra là **Quá giờ**.

## Không nên làm

- Không gửi check-in từ trình duyệt — chúng bị từ chối, và một tab bị đóng không phải job hỏng.
- Không đưa dữ liệu khách hàng vào slug, lý do hay tag. Dùng id và mã ngắn.
- Không để job lỗi vì không gọi được Belvador. SDK và `curl -fsS` vốn không bao giờ làm việc của bạn thất bại.

## Chọn tín hiệu

| Bạn muốn biết | Dùng |
|---|---|
| Job ném lỗi hoặc báo lỗi | Gửi lỗi (tự động bên trong `withMonitor`) |
| Job không chạy, chạy quá lâu, hoặc kết quả chưa rõ | Monitor |
| Request nào ở trình duyệt dẫn tới lỗi máy chủ | [Header trace](https://belvador.dev/vi/docs/sdk/tracing) |
| Có chuyện bất thường nhưng chưa có gì hỏng | Warning event — xem [Warning và tín hiệu khác](https://belvador.dev/vi/docs/guides/warnings) |
