Giao diện
Câu hỏi thường gặp — Record History
Sử dụng
Có thể xem ai đã tạo bản ghi không?
Có. Plugin ghi lại cả action create (không chỉ update). Khi bản ghi được tạo, một entry lịch sử được tạo với action: 'create', userId, và snapshot giá trị ban đầu.
Có thể phục hồi giá trị cũ không?
Hiện tại plugin chỉ hiển thị lịch sử. Không có chức năng restore tự động. Bạn có thể xem giá trị before trong recordFieldHistories và cập nhật thủ công nếu cần.
Lịch sử có ghi lại thao tác xóa không?
Có. Khi bản ghi bị xóa (destroy), plugin ghi lại entry với action: 'destroy'. Tuy nhiên, snapshot giá trị sẽ là null (vì bản ghi đã bị xóa).
Bulk update có được tracking không?
Có. Plugin hook vào afterBulkCreate, afterBulkUpdate, afterBulkDestroy. Mỗi bản ghi trong batch tạo entry lịch sử riêng.
Cấu hình
Tại sao không thấy lịch sử cho Collection?
Kiểm tra:
- Collection đã được bật tracking trong cấu hình
recordHistoryCollections - Ít nhất một field đã được chọn trong
recordHistoryFields - Lịch sử chỉ ghi từ khi bật — không retroactive cho dữ liệu cũ
Có nên bật tracking cho tất cả Collection không?
Không khuyến nghị. Lý do:
- Bảng history lớn nhanh (mỗi thay đổi = 1+ bản ghi)
- Tăng overhead cho mỗi thao tác ghi
- Khó quản lý khi dữ liệu lớn
Chỉ nên bật cho Collection quan trọng (đơn hàng, hợp đồng, tài khoản...) và field quan trọng.
Plugin có hỗ trợ multi data source không?
Có. Plugin hook vào app.dataSourceManager.afterAddDataSource() — mọi data source được thêm vào đều có thể tracking. Cấu hình recordHistoryCollections lưu cả dataSourceKey để phân biệt.
Kỹ thuật
Tại sao plugin dùng Database connection riêng?
Plugin tạo historyDB riêng biệt để:
- Tách transaction — ghi history không nằm trong transaction của data chính, tránh deadlock
- Tách migration — history tables có migration rules riêng (
schema-only,overwrite) - Isolation — lỗi ghi history không ảnh hưởng thao tác chính
Event Queue dùng để làm gì?
Plugin sử dụng Event Queue để xử lý bất đồng bộ:
- Hook chỉ publish message vào queue → response trả về ngay
- Queue consumer xử lý tạo snapshot và diff ở background
- Đảm bảo response time không bị ảnh hưởng bởi logic history
Snapshot + Diff hoạt động thế nào?
recordFieldSnapshotslưu giá trị mới nhất của mỗi field (1 record per field per bản ghi)- Khi snapshot được cập nhật,
afterSavehook so sánhmodel.get('value')vớimodel.previous('value') - Nếu khác nhau → tạo entry trong
recordFieldHistories(before + after) - Đồng thời tạo entry tổng trong
recordHistories(action, userId, timestamp)
Plugin có ảnh hưởng hiệu năng không?
- Response time: Không đáng kể — plugin chờ transaction commit rồi publish vào queue, không block response
- Database: Có tăng — mỗi thay đổi tạo snapshot + diff + history entries
- Memory: historyDB sử dụng connection pool riêng
Khuyến nghị monitor kích thước bảng history và thiết lập cleanup định kỳ cho production.
UUID và requestId dùng để làm gì?
| Field | Mô tả |
|---|---|
uuid | ID duy nhất cho mỗi lần thay đổi — liên kết recordHistories với recordFieldHistories |
requestId | ID request HTTP — nhóm các thay đổi từ cùng một request |
Nhờ requestId, bạn có thể xem tất cả field thay đổi trong cùng một lần submit form.