1. 12:20 12/10/2026
Giới thiệu
Khi xây dựng ứng dụng thực tế, nhiều thao tác tốn thời gian — gửi email, nén ảnh, đồng bộ dữ liệu lớn, gọi API bên thứ ba — không nên chạy trực tiếp trên luồng chính của giao diện. Việc chuyển chúng sang tác vụ nền (background jobs) giúp UI mượt mà, giảm tỷ lệ timeout và cải thiện trải nghiệm người dùng cả trên web lẫn mobile.
Tại sao cần hàng đợi thông điệp
- Tách biệt trách nhiệm: frontend chỉ gửi yêu cầu, backend xử lý bất đồng bộ.
- Khả năng thử lại (retry) và lập lịch (delay, cron) tự động.
- Theo dõi trạng thái, log lỗi tập trung, dễ dàng mở rộng khi tải tăng.
Kiến trúc chung
1. Frontend (React Web / React Native) gọi API endpoint "enqueue".
2. Backend (Node.js) nhận payload, đẩy job vào BullMQ (Redis).
3. Worker riêng biệt lấy job, thực thi, cập nhật trạng thái (completed, failed).
4. Frontend nhận kết quả qua polling, Server‑Sent Events (SSE) hoặc WebSocket; trên mobile có thể dùng Push Notification kết hợp Background Fetch để cập nhật khi app ở nền.
Cài đặt BullMQ cho backend
```bash
npm i bullmq ioredis
```
Tạo queue:
```js
import { Queue } from 'bullmq';
export const emailQueue = new Queue('email', { connection: { host: 'localhost', port: 6379 } });
```
Enqueue job từ route:
```js
await emailQueue.add('send-verification', { userId, email, token }, { attempts: 3, backoff: { type: 'exponential', delay: 2000 } });
```
Worker xử lý:
```js
import { Worker } from 'bullmq';
new Worker('email', async job => {
const { userId, email, token } = job.data;
await sendMail({ to: email, subject: 'Xác thực', html: `<a href="${process.env.APP_URL}/verify?token=${token}">Xác thực</a>` });
await updateUserVerified(userId);
}, { connection: { host: 'localhost', port: 6379 } });
```
Tích hợp React Web
- Gọi API enqueue sau khi người dùng bấm "Gửi lại email".
- Hiển thị skeleton loading cho nút, disable tránh spam.
- Dùng SSE endpoint `/jobs/:id/stream` để nhận realtime status; khi `completed` thì toast thành công, khi `failed` cho phép thử lại.
Tích hợp React Native
- Cài `react-native-background-fetch` và `react-native-push-notification` (hoặc Expo Notifications).
- Khi app vào background, Background Fetch định kỳ gọi API kiểm tra job chưa hoàn tất.
- Worker backend đẩy notification qua Firebase/APNs khi job xong; app nhận, cập nhật Redux/Zustand và hiển thị banner.
- Ví dụ: upload ảnh lớn -> enqueue job `process-image`; user đóng app, sau vài giây nhận push "Ảnh đã sẵn sàng", mở app thấy ảnh đã tối ưu.
Ví dụ thực tế
1. Xác thực email: enqueue `send-verification` -> worker gửi mail -> SSE/WebSocket báo hoàn tất -> UI chuyển sang trang đã xác thực.
2. Xử lý avatar: client upload file tạm -> enqueue `optimize-avatar` -> worker resize, convert WebP, lưu CDN -> push notification mobile, SSE web -> UI cập nhật avatar mới không cần reload.
3. Đồng bộ dữ liệu offline: React Native lưu thay đổi local -> enqueue `sync-offline` khi online -> worker merge lên server -> trả về version mới -> client cập nhật store.
Mẹo và best practices
- Luôn thiết lập `attempts` và `backoff` để tự retry lỗi transient.
- Giới hạn concurrency worker (`concurrency: 5`) tránh quá tải CPU/IO.
- Lưu metadata job (progress, error) vào Redis hash để frontend query nhanh.
- Bảo vệ endpoint enqueue bằng rate‑limit và xác thực JWT.
- Trên mobile, cấu hình `minimumFetchInterval` hợp lý (15‑30 phút) để tiết kiệm pin.
- Sử dụng TypeScript cho payload job để tránh mismatch giữa frontend và worker.
Kết luận
Kết hợp BullMQ ở backend với SSE/WebSocket trên web và Background Fetch + Push Notification trên React Native tạo ra một hệ thống tác vụ nền thống nhất, đáng tin cậy và dễ mở rộng. Áp dụng mẫu này giúp team tập trung phát triển tính năng cốt lõi thay vì loay hoay xử lý timeout hay blocking UI.