
Một quy trình thực sự tự động không cần ai ngồi bấm nút. Nó chạy vì có chuyện xảy ra: một đơn hàng mới, một file được tải lên, một mốc thời gian tới hạn. Khi xây phần mềm tích hợp AI để tự động hoá công việc, phần khó nhất thường không phải mô hình AI, mà là bộ xương kết nối các sự kiện lại thành một luồng chạy ổn định. Bài này, chúng tôi đi vào hai mảnh ghép cốt lõi của bộ xương đó: webhook và job định kỳ, kèm cơ chế idempotent để mọi thứ không vỡ khi sự kiện chạy hai lần.
Tự động hoá thật sự bắt đầu từ sự kiện, không phải nút bấm

Trước khi nói chuyện code, cần thống nhất một tư duy: tự động hoá tốt được kích hoạt bởi sự kiện, không phải bởi thao tác tay.
Khác biệt giữa thao tác thủ công và quy trình kích hoạt bằng sự kiện
Trong cách làm thủ công, một người phải nhớ, phải mở phần mềm, phải bấm nút để mọi thứ tiếp diễn. Còn trong quy trình hướng sự kiện, hệ thống tự nhận biết có chuyện xảy ra và chạy bước tiếp theo ngay lập tức. Khác biệt này quyết định độ tin cậy. Con người quên, ngủ, nghỉ phép. Sự kiện thì không. Một dich vu thiet ke website hay một sản phẩm phần mềm tốt đều dựa trên nguyên tắc này để vận hành mượt.
Vai trò của webhook và cron trong một luồng tự chạy
Hai cơ chế bổ sung cho nhau:
- Webhook phản ứng tức thì với sự kiện do bên ngoài đẩy tới, ví dụ một cổng thanh toán báo giao dịch thành công.
- Cron (job định kỳ) chủ động quét theo lịch, dọn những việc còn tồn mà không có sự kiện nào đánh thức.
Webhook lo phần “ngay khi có chuyện”, cron lo phần “kiểm tra đều đặn”. Thiếu một trong hai, luồng tự động sẽ có lỗ hổng.
Dựng xương sống cho luồng tự động
Giờ ta đi vào cách dựng. Trong hệ sinh thái .NET, cả ba mảnh dưới đây đều có công cụ sẵn để bạn không phải làm lại từ đầu.
Webhook nhận sự kiện đầu vào và xác thực chữ ký để chống giả mạo
Webhook về bản chất là một endpoint HTTP POST mà bên thứ ba gọi tới. Trong ASP.NET Core, bạn chỉ cần một controller action nhận body. Nhưng đừng tin ngay vào dữ liệu nhận được. Mọi nhà cung cấp nghiêm túc đều ký request bằng một chữ ký HMAC trong header.
Quy trình xác thực gồm các bước:
- Đọc raw body của request, không phải bản đã parse.
- Tính HMAC SHA256 của body bằng secret bạn được cấp.
- So sánh kết quả với chữ ký trong header, ưu tiên hàm so sánh chống tấn công thời gian.
Nếu chữ ký không khớp, trả về lỗi và bỏ qua. Bước này chặn kẻ giả mạo gửi sự kiện rác vào hệ thống của bạn. Khi cần dựng các luồng phức tạp hơn, một dich vu lap trinh ung dung chuyên sâu sẽ giúp bạn chuẩn hoá khâu này thành thư viện dùng chung.
Job định kỳ quét trạng thái và đẩy việc còn tồn sang bước tiếp theo
Không phải mọi việc đều có webhook đánh thức. Có những việc cần được quét đều đặn: đơn hàng quá hạn xử lý, email chưa gửi, dữ liệu chờ đồng bộ. Đây là vai của job định kỳ. Trong .NET, bạn dùng BackgroundService kết hợp PeriodicTimer, hoặc thư viện như Hangfire để có giao diện quản lý job.
Một job định kỳ tốt nên gọn và an toàn: mỗi lần chạy chỉ lấy một lô việc còn tồn, xử lý, rồi đánh dấu đã xong. Nếu lô lớn, chia nhỏ để tránh chiếm dụng tài nguyên quá lâu.
Cơ chế idempotent để một sự kiện chạy hai lần không gây nhân đôi dữ liệu
Đây là phần quan trọng nhất và cũng dễ bị bỏ qua nhất. Webhook có thể được gửi lại nếu bên gửi không nhận được phản hồi đúng lúc. Job định kỳ có thể trùng lịch. Nếu code của bạn không idempotent, một sự kiện chạy hai lần sẽ tạo hai bản ghi, gửi hai email, trừ tiền hai lần.
Cách xử lý phổ biến trong .NET:
- Mỗi sự kiện mang một khoá định danh duy nhất, ví dụ event id từ nhà cung cấp.
- Lưu khoá đó vào một bảng với ràng buộc unique qua Entity Framework.
- Trước khi xử lý, kiểm tra khoá đã tồn tại chưa. Nếu rồi, bỏ qua một cách lặng lẽ.
Ràng buộc unique ở tầng cơ sở dữ liệu là tuyến phòng thủ cuối cùng, đảm bảo dù logic có sơ hở thì dữ liệu vẫn không bị nhân đôi.
| Thành phần | Vai trò | Điểm cần lưu ý |
|---|---|---|
| Webhook | Nhận sự kiện tức thì từ bên ngoài | Phải xác thực chữ ký HMAC |
| Job định kỳ | Quét và dọn việc còn tồn theo lịch | Chia lô nhỏ, tránh chạy quá lâu |
| Idempotent | Chống xử lý trùng một sự kiện | Dùng khoá unique ở tầng dữ liệu |
| Lớp AI | Ra quyết định hoặc phân loại | Gọi qua service có cache |
Khi nào nên mua sẵn thay vì tự code
Tới đây, một câu hỏi thực tế nảy ra: có đáng tự dựng tất cả không, hay nên dùng nền tảng có sẵn?
Tự dựng phù hợp luồng đơn giản, nhưng chi phí bảo trì tăng nhanh
Với một luồng đơn giản, tự code là lựa chọn hợp lý. Bạn kiểm soát hoàn toàn, không phụ thuộc bên ngoài. Nhưng khi số luồng tăng lên, mỗi luồng lại có webhook riêng, lịch riêng, cách xử lý lỗi riêng, chi phí bảo trì leo thang nhanh. Đội của bạn dần dành nhiều thời gian vá hạ tầng tự động hoá hơn là làm tính năng tạo giá trị. Chúng tôi từng chia sẻ nhiều tình huống tương tự trong chuyên mục dot net.
Một nền tảng gói sẵn các mảnh này và thêm lớp ra quyết định bằng AI
Khi nhu cầu lớn hơn, một nền tảng phần mềm tích hợp AI tự động hoá doanh nghiệp gói sẵn webhook, job định kỳ và cơ chế chống trùng, đồng thời thêm một lớp ra quyết định bằng AI lên trên. Thay vì tự bảo trì từng mảnh, bạn tập trung vào logic nghiệp vụ đặc thù. Bạn có thể tìm hiểu thêm các lựa chọn như vậy tại đây để cân nhắc cho dự án của mình.
Kết luận
Kiến trúc hướng sự kiện là điều kiện cần để một quy trình tự chạy ổn định. Webhook bắt sự kiện tức thì, job định kỳ dọn việc còn tồn, và idempotent giữ cho dữ liệu sạch khi mọi thứ chạy lại. Còn lựa chọn tự code hay mua sẵn thì tuỳ vào độ phức tạp của luồng và nguồn lực bảo trì bạn có. Làm tốt ba mảnh xương sống này, phần mềm của bạn sẽ tự chạy bền bỉ mà không cần ai canh từng nút bấm.


