Bỏ qua, đến nội dung

Tham chiếu kỹ thuật

SequenceField — Kiểu field trong hệ thống

Thuộc tínhMô tả
Field typesequence
DB columnVARCHAR / STRING
PatternsMảng pattern objects
Read-onlyGiá trị sinh tự động, không cho nhập thủ công

Patterns System

Mỗi field sequence chứa mảng patterns, mỗi phần tử có typeoptions:

typescript
interface SequencePattern {
  type: 'string' | 'integer';
  options: StringPatternOptions | IntegerPatternOptions;
}

interface StringPatternOptions {
  value: string;
}

interface IntegerPatternOptions {
  digits: number;
  start: number;
  cycle?: string;
}

Khi sinh mã, hệ thống duyệt qua từng pattern → sinh giá trị → nối lại thành chuỗi kết quả.

Database — Bảng sequences

Bảng sequences lưu trạng thái counter cho từng field:

CộtKiểuMô tả
idBIGINTPrimary key
collectionSTRINGTên collection chứa field
fieldSTRINGTên field sequence
keyINTEGERGiá trị counter hiện tại
lastGeneratedAtDATEThời điểm sinh mã gần nhất (dùng cho cycle check)

Cách kiểm tra cycle reset

Trước khi sinh mã:
  → Đọc lastGeneratedAt từ bảng sequences
  → So sánh với cron expression
  → Nếu đã qua chu kỳ reset → đặt key = start
  → Nếu chưa → key = key + 1
  → Cập nhật key và lastGeneratedAt

Concurrency Safety — Bảng sequences

Plugin sử dụng bảng sequences thay vì tính MAX() từ dữ liệu bản ghi:

Không an toàn (race condition):
  Thread A: SELECT MAX(code) → 42
  Thread B: SELECT MAX(code) → 42
  Thread A: INSERT code = 43
  Thread B: INSERT code = 43  ← TRÙNG!

An toàn (sequences table + lock):
  Thread A: LOCK → read key=42 → key=43 → UNLOCK
  Thread B: LOCK → read key=43 → key=44 → UNLOCK

Counter tăng atomic trong một transaction, đảm bảo không trùng mã ngay cả với hàng trăm request đồng thời.

Server Hooks

beforeSave — Sinh mã khi tạo bản ghi

Bản ghi mới chuẩn bị INSERT
  → beforeSave hook trigger
  → Kiểm tra field sequence chưa có giá trị
  → LOCK bảng sequences cho (collection, field)
  → Đọc counter hiện tại
  → Kiểm tra cycle reset (nếu có)
  → Tăng counter + sinh mã theo patterns
  → Cập nhật bảng sequences
  → UNLOCK
  → Gán giá trị vào record

afterDestroy — Dọn dẹp khi xóa field

Field sequence bị xóa
  → afterDestroy hook trigger
  → Xóa row tương ứng trong bảng sequences

app.on('repair') — Sửa counter lệch

Trigger khi admin chạy repair
  → Tìm tất cả field sequence trong hệ thống
  → Với mỗi field:
    → SELECT MAX(extracted_number) FROM collection
    → So sánh với key trong bảng sequences
    → Nếu lệch → cập nhật key = max thực tế
  → Log kết quả sửa chữa

Sử dụng repair khi:

  • Import dữ liệu từ nguồn khác (counter không được cập nhật).
  • Khôi phục database từ backup cũ hơn.
  • Phát hiện counter bị lệch do lỗi hệ thống.

Sơ đồ tổng quan

┌────────────────┐     lock + increment     ┌────────────────┐
│  beforeSave    │ ───────────────────────→ │   sequences    │
│  Hook          │ ←─────────────────────── │   table        │
└───────┬────────┘     new counter value    └────────────────┘

        │ patterns → "DH-" + pad(43, 5)
        │ result  → "DH-00043"

┌────────────────┐
│  Record field  │
│  = "DH-00043"  │
└────────────────┘