KB-4A2F

Kế hoạch low-code PG → Directus → Nuxt cho số tổng hợp tự cập nhật

4 min read Revision 1
postgresdirectusnuxtaggregationtriggerlow-codeassembly-first

Kế hoạch lắp ráp tối đa: PG → Directus → Nuxt tự cập nhật số tổng hợp

  • Thời điểm: 2026-03-25
  • Agent: Incomex Hội đồng AI
  • Bài toán: vài con số SUM/COUNT từ Postgres, khi dữ liệu biến động thì tự cập nhật để Nuxt hiển thị gần realtime, ưu tiên ít code nhất.

Kết luận ngắn

Giải pháp phù hợp nhất là:

  1. Postgres giữ vai trò single provider tính toán số tổng hợp.
  2. Dùng table summary hoặc materialized view/view làm nguồn chuẩn cho số liệu.
  3. Dùng PG trigger hoặc Directus Flow để refresh summary khi bảng gốc thay đổi.
  4. Directus chỉ làm lớp expose dữ liệu ra API.
  5. Nuxt chỉ đọc đúng 1 endpoint summary và refresh/poll nhẹ hoặc subscribe nếu đã có kênh realtime.

Vì sao chọn hướng này

  • Phù hợp nguyên tắc Assembly First: ưu tiên PG + Directus có sẵn, giảm custom code.
  • Phù hợp Single Provider: một nơi duy nhất cung cấp số liệu tổng hợp cho mọi nơi dùng lại.
  • Phù hợp Data Connection Law: ghi/đọc qua API/flow chuẩn hoặc DB objects chuẩn, không nhúng logic rải rác ở UI.

Thiết kế khuyến nghị

Phương án A — Khuyên dùng nhất

  • Tạo bảng summary ví dụ dashboard_metrics.
  • Viết 1 function PG refresh_dashboard_metrics() để tính lại các SUM/COUNT.
  • Gắn trigger AFTER INSERT/UPDATE/DELETE ở các bảng nguồn để gọi function này.
  • Đăng ký dashboard_metrics trong Directus.
  • Nuxt gọi Directus API lấy 1 record summary.
  • UI refresh mỗi 5–15 giây hoặc khi route focus lại.

Phương án B — Nếu chấp nhận trễ nhẹ

  • Tạo view/materialized view tổng hợp.
  • Dùng Directus Flow schedule hoặc cron refresh định kỳ.
  • Nuxt chỉ đọc view qua Directus.
  • Ít trigger hơn nhưng không realtime bằng.

Phương án C — Directus Flow làm trigger chính

  • Khi item create/update/delete trong collection Directus, Flow gọi operation cập nhật collection summary.
  • Phù hợp khi mọi ghi dữ liệu đều đi qua Directus.
  • Không tốt nếu còn luồng ghi trực tiếp vào PG ngoài Directus.

Khuyến nghị cuối

Cho bài toán “bất cứ biến động nào trên PG đều cập nhật số thật lên Nuxt”, nên ưu tiên:

PG trigger + summary table + Directus expose + Nuxt fetch nhẹ

Đây là hướng ít code nhất mà vẫn bám đúng yêu cầu event-driven ở tầng dữ liệu, không phụ thuộc việc dữ liệu có đi qua Directus hay không.

Mức code thực tế

  • PG: 1 function + vài trigger + 1 summary table
  • Directus: gần như cấu hình collection quyền đọc
  • Nuxt: 1 composable/API call + widget hiển thị số

=> Đây là mức low-code thực dụng, không phải no-code tuyệt đối, nhưng là hướng assembly-first tốt nhất cho stack hiện tại.

Lưu ý thiết kế

  • Chỉ tính vài số tổng hợp đơn giản thì đừng đưa logic aggregate vào Nuxt.
  • Cũng đừng để nhiều nơi tự SUM lại cùng một dữ liệu.
  • Nếu write volume cao, cần chống refresh quá dày bằng debounce/coalescing hoặc refresh theo queue ngắn.
  • Nếu số liệu cực ít và tải thấp, có thể đơn giản hóa bằng view + polling, bỏ trigger.

Căn cứ tham chiếu

  • knowledge/dev/ssot/data-connection-law.md
  • knowledge/dev/architecture/index.md (Assembly First)
  • knowledge/dev/architecture/constitution-amendment-measurement.md (Điều 0-S Single Provider)
  • knowledge/current-state/directus-schema.md
  • knowledge/current-state/reports/s109-cp3b-report.md
  • knowledge/dev/architecture/dieu31-pg-technical-design.md