Telegram Bot API 429: xử lý retry_after trong hàng đợi gửi
Khi yêu cầu gửi qua Telegram Bot API bị từ chối do kiểm soát tần suất và có parameters.retry_after, hãy chờ ít nhất số giây được chỉ định trước khi thử lại. Lưu thời hạn chờ bền vững và phối hợp mọi worker dùng cùng một bot; cho một worker tạm nghỉ không làm các worker khác chậm lại. Timeout mạng là trường hợp khác: không nhận được phản hồi có thể đồng nghĩa kết quả gửi chưa rõ, nên không được đưa vào cùng nhánh thử lại tự động.
Điểm chính
- Đọc phản hồi có cấu trúc, không trích số từ chuỗi
description. - Xem giới hạn chính thức là điều kiện lập lịch, không phải cam kết thông lượng.
- Tách việc lưu dữ liệu đầu vào khỏi thời gian chờ gửi đầu ra.
- Giữ thời hạn qua lần khởi động lại và kiểm tra câu trả lời bị trì hoãn còn cần thiết hay không.
Giới hạn gửi của Telegram áp dụng ở đâu?
Bots FAQ chính thức khuyên tránh gửi quá một tin nhắn mỗi giây trong một cuộc trò chuyện. Với nhóm, giới hạn là 20 tin nhắn mỗi phút; thông báo hàng loạt ở mức khoảng 30 tin nhắn mỗi giây nếu chưa bật paid broadcasts. Các đợt gửi dồn ngắn cũng có thể dẫn đến 429. Đây là các phạm vi khác nhau: chia tin nhắn sang nhiều cuộc trò chuyện không loại bỏ giới hạn tổng của bot.
Không nên cam kết mọi yêu cầu dưới những con số này đều thành công. Quy tắc riêng của phương thức và phản hồi thực tế vẫn quan trọng. Bài viết này dành cho hàng đợi gửi thông thường, không hướng dẫn cấu hình paid broadcasts hay giải thích mọi nguyên nhân của 429.
Tài liệu Bot API định nghĩa ResponseParameters.retry_after là số nguyên tùy chọn: số giây còn phải chờ trước khi lặp lại yêu cầu sau khi vượt flood control. Đây là trường JSON, không phải hợp đồng HTTP header dùng chung. Thiếu trường này không có nghĩa là thời gian chờ bằng không.
Nếu worker cần kiểm tra kết quả, hãy gọi API bằng yêu cầu riêng. Bài so sánh phản hồi webhook với sendMessage riêng giải thích vì sao ứng dụng không nhận được kết quả phương thức khi nhúng lời gọi vào phản hồi webhook của Telegram.
Xây luồng gửi bền vững, không chỉ vòng lặp sleep
Phần dưới là đề xuất thiết kế ứng dụng, không phải bảo đảm bổ sung của Telegram.
Trước khi gửi, lưu một tác vụ nội bộ cho mỗi ý định trả lời: danh tính bot, đích đến, nội dung đã duyệt, chính sách hết hạn, số lần thử và thời điểm sớm nhất được chạy. Đây là trường của ứng dụng, không phải tham số bổ sung của Bot API. Khử trùng lặp theo ý định nghiệp vụ để một update đầu vào được giao lại không tạo thêm một câu trả lời.
Dùng ba lớp điều kiện lập lịch:
- Bot: điều phối tổng lưu lượng của mọi tiến trình dùng chung bot.
- Cuộc trò chuyện: điều tiết từng đích đến, gồm cả giới hạn nhóm.
- Tác vụ: kiểm tra thời hạn chờ, hết hạn, hủy và quyền xử lý theo lease.
Nhận tác vụ bằng thao tác nguyên tử để hai worker không cùng gửi một việc. Kiểm tra lại các điều kiện chung ngay trước lời gọi mạng. Sau phản hồi flood control, gia hạn thời gian chờ một cách nguyên tử rồi trả tác vụ về bộ lập lịch. Không giữ yêu cầu webhook mở trong lúc chờ.
retry_after không chỉ rõ giới hạn ở phạm vi nào đã bị chạm. Chính sách khởi đầu thận trọng là tạm dừng toàn bộ luồng gửi của bot trong khoảng thời gian trả về. Cách này có thể làm chậm các cuộc trò chuyện khác, nhưng không giả định rằng chỉ chat hiện tại bị giới hạn. Ghi rõ đây là chính sách của ứng dụng và điều chỉnh theo quan sát, không đoán cơ chế bên trong máy chủ.
Chuyển retry_after thành thời hạn được lưu
Đoạn JavaScript dưới đây chỉ minh họa bước phân loại. Nó không gửi yêu cầu, không triển khai cơ sở dữ liệu và không phải bộ lập lịch đã được kiểm thử trong thực tế. receivedAtMs là lúc client nhận phản hồi; currentNotBeforeMs là thời hạn chờ chung hiện có trong kho dữ liệu.
function telegramFloodDecision(body, receivedAtMs, currentNotBeforeMs = 0) {
if (body?.ok !== false || body.error_code !== 429) {
return { action: 'classify_other_result' };
}
const seconds = body.parameters?.retry_after;
if (!Number.isSafeInteger(seconds) || seconds < 0) {
return { action: 'hold_for_review' };
}
const deadline = receivedAtMs + seconds * 1000;
if (!Number.isSafeInteger(deadline)) {
return { action: 'hold_for_review' };
}
return {
action: 'reschedule',
notBeforeMs: Math.max(currentNotBeforeMs, deadline)
};
}
Tên các giá trị trả về thuộc ứng dụng nội bộ. Lưu thời hạn lớn nhất bằng transaction; đọc rồi ghi không có bảo vệ có thể ghi đè thời hạn dài hơn mà worker khác vừa lưu. Đồng bộ đồng hồ giữa các worker hoặc dùng nguồn thời gian chung cho bộ lập lịch. Nếu thêm jitter, chỉ được tăng thời gian chờ, không rút ngắn yêu cầu của Telegram.
Đến hạn chỉ có nghĩa là đủ điều kiện thử, không phải chắc chắn thành công. Đặt giới hạn số lần thử và tuổi tác vụ. Nếu phản hồi tiếp theo kéo dài thời gian chờ, lưu thời hạn mới. Nếu tác vụ hết hạn hoặc nhân viên đã trả lời, hãy hủy hay chuyển sang kiểm tra thay vì gửi nội dung cũ. Đây là chính sách nghiệp vụ, không phải giới hạn Telegram.
Tách từ chối, kết quả chưa rõ và tiếp nhận đầu vào
| Kết quả quan sát | Cách xử lý đề xuất |
|---|---|
Phản hồi flood control hợp lệ có retry_after | Lưu thời hạn; chỉ thử lại khi mọi điều kiện cho phép |
429 thiếu thời gian chờ dùng được | Giữ lại để phân loại, không lặp ngay hay coi là không cần chờ |
sendMessage thành công | Lưu Message trả về, không lập lại cùng ý định |
| Timeout mạng hoặc mất phản hồi | Đánh dấu chưa rõ; đối soát hoặc kiểm tra trước khi gửi lại |
| Lỗi API khác | Kiểm tra riêng quyền, đích đến và nội dung yêu cầu |
ID tác vụ nội bộ giúp tránh lập lịch trùng trong hệ thống, không bảo đảm phía xa thực hiện đúng một lần. Tiến trình có thể dừng sau khi gửi thành công nhưng trước khi lưu phản hồi, để lại kết quả chưa rõ. Không nên nói chỉ cần outbox là loại bỏ mọi tin nhắn trùng.
Sức khỏe đầu vào là ranh giới riêng. Xác thực và lưu update bền vững, rồi xác nhận tiếp nhận độc lập với việc gửi đang chờ. Nếu chính update không đến, dùng hướng dẫn chẩn đoán getWebhookInfo. pending_update_count đếm update chờ giao, không phải độ dài hàng đợi gửi của ứng dụng.
Giữ hợp đồng UnifyPort tách biệt
Giao diện không chính thức của UnifyPort dùng tài khoản nhắn tin đã kết nối và có hợp đồng gửi văn bản riêng. Phản hồi lỗi chứa error.code, error.numeric_code, error.message và request_id để truy vết. Tài liệu lỗi không định nghĩa parameters.retry_after của Bot API; đừng sao chép nguyên bộ phân loại ở trên vào client UnifyPort.
Worker đa kênh, chẳng hạn Telegram cùng Zalo hoặc WhatsApp, có thể dùng chung kho tác vụ nhưng phải phân loại kết quả theo từng hợp đồng. Giữ HTTP status và lỗi có cấu trúc. Như hướng dẫn truy vết yêu cầu giải thích, X-Request-Id không phải khóa idempotency cho việc gửi được tài liệu bảo đảm. Giao diện không chính thức không loại bỏ giới hạn nền tảng và không khiến việc gửi lại một kết quả chưa rõ trở nên an toàn.
Cũng cần tách lỗi gửi khỏi HTTP status do receiver của bạn trả về. Tài liệu giao webhook của UnifyPort nói rằng các lần giao lại diễn ra ngay và không tuân theo Retry-After. Cho receiver trả 429 không phải cách lập lịch thời gian chờ cho hàng đợi gửi.
Kiểm tra nghiệm thu và câu hỏi thường gặp
Dùng fixture phản hồi nội bộ thay vì cố tình gửi dồn vào Telegram. Kiểm tra hai worker chung bot, khởi động lại trong lúc chờ, thời hạn dài đến sau thời hạn ngắn, thiếu retry_after, hủy khi đang chờ và mất phản hồi gửi. Xác nhận không có tác vụ chạy trước thời hạn đã lưu và kết quả chưa rõ vẫn được xử lý riêng. Đây là các kiểm tra đề xuất, không phải kết quả đã thực hiện.
retry_after tính bằng giây hay mili giây?
Giây. Chuyển đổi rõ ràng nếu bộ lập lịch lưu mili giây.
Thêm worker có xử lý được 429 không?
Không chỉ bằng cách tăng số lượng. Worker dùng cùng bot vẫn chịu ràng buộc chung; chạy song song thiếu điều phối có thể làm tăng số lần bị từ chối.
Chờ đủ thời gian có bảo đảm gửi thành công không?
Không. Chỉ đáp ứng điều kiện chờ của phản hồi đó. Các điều kiện khác, quyền và phản hồi API tiếp theo vẫn có hiệu lực.
Timeout có nên dùng cùng quy tắc thử lại không?
Không. Timeout không có phản hồi chưa chứng minh yêu cầu bị flood control từ chối; kết quả gửi có thể chưa rõ.
Bước tiếp theo và nguồn tham khảo
Thêm thời hạn chờ bền vững vào bộ gửi hiện tại và kiểm tra các điểm có thể dừng đột ngột trước khi tăng số worker. Với client tài khoản đã kết nối, bắt đầu từ tài liệu lỗi UnifyPort thay vì giả định tương thích Bot API.
Nguồn chính thức được kiểm tra ngày 2026-10-18:
Biến tích hợp nhắn tin thành một pipeline sản phẩm ổn định.
Bắt đầu bằng cách gửi qua một API, rồi đưa mọi tin nhắn inbound trở lại hệ thống kinh doanh bằng sự kiện chuẩn.