feat(migration): ADR-028 migration architecture refactor
- เพิ่ม POST /api/ai/jobs + GET /api/ai/jobs/:jobId endpoints (FR-001, FR-002) - เพิ่ม BullMQ Worker MigrateDocumentWorker + OCR auto-detect (FR-003, FR-004) - เพิ่ม cleanup-temp-files + expire-pending-reviews workers (FR-005, FR-005a/b) - สร้าง SQL deltas: tags, correspondence_tags, alter migration_review_queue (FR-006, ADR-009) - เพิ่ม MigrationReviewService.commitRecord() + SELECT FOR UPDATE (FR-007, FR-007a) - เพิ่ม CASL permission migration.commit + MigrationReviewController (FR-007) - สร้าง TagsModule + TagsService + TagsController (US3) - สร้าง Migration Review Queue frontend page + ReviewQueueTable (US2) - อัปเดต n8n guide: deterministic Idempotency-Key + token pre-flight (FR-001a, FR-010a/b) - สร้าง spec.md, plan.md, tasks.md, data-model.md, contracts/, quickstart.md - สร้าง ADR-028 document + validation-report.md (PASS 32/32 tasks, 173/173 tests)
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
// File: specs/200-fullstacks/228-migration-arch-refactor/plan.md
|
||||
// Change Log:
|
||||
// - 2026-05-22: Initial implementation plan for ADR-028 Migration Architecture Refactor
|
||||
|
||||
# Implementation Plan: ADR-028 Migration Architecture Refactor
|
||||
|
||||
**Branch**: `228-migration-arch-refactor` | **Date**: 2026-05-22 | **Spec**: [spec.md](./spec.md)
|
||||
|
||||
## Summary
|
||||
|
||||
Refactor migration architecture ให้สอดคล้องกับ ADR-023A: n8n เรียกผ่าน BullMQ แทน Ollama โดยตรง, ใช้ `gemma4:e4b Q8_0`, OCR ผ่าน PyMuPDF/PaddleOCR, สร้าง Backend endpoint `/api/ai/jobs`, SQL delta สำหรับ `tags`/`correspondence_tags`, และ Migration Review UI
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: TypeScript 5.x, NestJS 10.x, Next.js 14.x
|
||||
**Primary Dependencies**: BullMQ, TypeORM, CASL, TanStack Query, Zod
|
||||
**Storage**: MariaDB (SQL delta via ADR-009), Qdrant (embedding), Redis (BullMQ)
|
||||
**Testing**: Jest (Backend), Vitest (Frontend)
|
||||
**Target Platform**: QNAP NAS (Backend + n8n), Admin Desktop Desk-5439 (Ollama + OCR Worker)
|
||||
**Performance Goals**: Fast Path OCR < 5s/file; Slow Path OCR < 60s/file; AI inference < 30s
|
||||
**Constraints**: VRAM peak ~4.3GB; BullMQ concurrency=1 (ai-batch); Token TTL ≤ 7 วัน
|
||||
**Scale/Scope**: 20,000 PDF documents; ~3 วินาที/record → ~16.6 ชั่วโมงรวม
|
||||
|
||||
## Constitution Check
|
||||
|
||||
| ADR | Rule | Status |
|
||||
|-----|------|--------|
|
||||
| ADR-019 | UUID ทุก entity ใช้ `publicId` (UUIDv7), ห้าม `parseInt` | ✅ |
|
||||
| ADR-009 | Schema changes via SQL delta เท่านั้น | ✅ (tags + correspondence_tags) |
|
||||
| ADR-016 | Auth guard ทุก endpoint, token TTL ≤ 7 วัน | ✅ |
|
||||
| ADR-008 | BullMQ สำหรับ background jobs | ✅ (ai-batch queue) |
|
||||
| ADR-023A | n8n → DMS API → BullMQ → Ollama (ห้าม direct) | ✅ |
|
||||
| ADR-007 | Layered error handling + user-friendly messages | ✅ |
|
||||
| ADR-023A | gemma4:e4b Q8_0 + nomic-embed-text เท่านั้น | ✅ |
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/200-fullstacks/228-migration-arch-refactor/
|
||||
├── spec.md
|
||||
├── plan.md ← this file
|
||||
├── research.md
|
||||
├── data-model.md
|
||||
├── quickstart.md
|
||||
├── contracts/
|
||||
│ └── ai-jobs-api.md
|
||||
└── tasks.md
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
backend/src/modules/
|
||||
├── ai/
|
||||
│ ├── ai.module.ts (existing — เพิ่ม migrate-document job type)
|
||||
│ ├── ai.controller.ts (existing — เพิ่ม POST /api/ai/jobs, GET /api/ai/jobs/:jobId)
|
||||
│ ├── ai.service.ts (existing — เพิ่ม submitMigrationJob())
|
||||
│ ├── workers/
|
||||
│ │ └── migrate-document.worker.ts (NEW — BullMQ processor)
|
||||
│ └── dto/
|
||||
│ ├── submit-ai-job.dto.ts (NEW)
|
||||
│ └── ai-job-result.dto.ts (NEW)
|
||||
├── tags/ (NEW module)
|
||||
│ ├── tags.module.ts
|
||||
│ ├── tags.controller.ts
|
||||
│ ├── tags.service.ts
|
||||
│ └── entities/
|
||||
│ ├── tag.entity.ts
|
||||
│ └── correspondence-tag.entity.ts
|
||||
└── migration/
|
||||
└── migration-review.service.ts (existing — เพิ่ม commit logic)
|
||||
|
||||
specs/03-Data-and-Storage/deltas/
|
||||
└── 2026-05-22-create-tags-tables.sql (NEW — ADR-009)
|
||||
|
||||
frontend/app/(dashboard)/
|
||||
└── migration/
|
||||
└── review/
|
||||
└── page.tsx (NEW — Migration Review Queue UI)
|
||||
|
||||
frontend/components/migration/
|
||||
└── review-queue-table.tsx (NEW)
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase A: Backend Foundation (Prerequisite — Blocking)
|
||||
|
||||
**A1. SQL Delta — Tags Tables**
|
||||
- สร้าง `specs/03-Data-and-Storage/deltas/2026-05-22-create-tags-tables.sql`
|
||||
- ตาราง: `tags`, `correspondence_tags`
|
||||
- Apply ใน staging ก่อน; production apply ที่ Gate #1
|
||||
|
||||
**A2. Tags Module (NestJS)**
|
||||
- Entity: `Tag`, `CorrespondenceTag` (TypeORM)
|
||||
- Service: CRUD + tag normalization
|
||||
- Controller: GET /api/tags (project-scoped)
|
||||
|
||||
**A3. BullMQ Worker — migrate-document**
|
||||
- Job processor ใน `ai-batch` queue
|
||||
- Step 1: Fetch temp file จาก Storage
|
||||
- Step 2: OCR auto-detect (PyMuPDF API / PaddleOCR API)
|
||||
- Step 3: gemma4:e4b inference (metadata extraction + classification + tagging)
|
||||
- Step 4: Validate JSON output
|
||||
- Step 5: Store result in job
|
||||
|
||||
**A4. AI Jobs API Endpoints**
|
||||
- `POST /api/ai/jobs` — submit job, Idempotency-Key check
|
||||
- `GET /api/ai/jobs/:jobId` — polling + result retrieval
|
||||
- `POST /api/ai/migration/review` — commit approved record (RBAC: DC | Admin | Superadmin)
|
||||
|
||||
**A5. Temp File Cleanup Scheduler**
|
||||
- BullMQ Scheduled job: ทุก 1 ชั่วโมง
|
||||
- ลบ temp attachments ที่ `created_at < NOW() - 24h` + ไม่มี `committed_at`
|
||||
|
||||
### Phase B: Frontend (After Phase A complete)
|
||||
|
||||
**B1. Migration Review Queue Page**
|
||||
- `/migration/review` — แสดง records จาก `migration_review_queue`
|
||||
- Filter: Status, Batch ID, Confidence range
|
||||
- Actions: Edit metadata, Map/Accept/Reject tags, Execute Import
|
||||
|
||||
**B2. Tag Review Component**
|
||||
- แสดง AI suggested tags พร้อม confidence score
|
||||
- `is_new: true` → highlight ให้ reviewer approve/map/reject
|
||||
|
||||
### Phase C: ADR-028 Documentation
|
||||
|
||||
**C1. สร้าง ADR-028**
|
||||
- `specs/06-Decision-Records/ADR-028-migration-architecture-refactor.md`
|
||||
- Document ทุก decision จาก session นี้
|
||||
|
||||
### Phase D: Post-Migration Cleanup Script
|
||||
|
||||
**D1. Cleanup SQL Script**
|
||||
- `specs/03-Data-and-Storage/deltas/XXXX-drop-migration-tables.sql`
|
||||
- Drop 5 ตาราง migration (ยกเว้น `import_transactions`)
|
||||
- Run หลัง Gate #3 ผ่าน
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|-----------|
|
||||
| OCR Worker บน Desk-5439 ไม่พร้อม | Health check ใน Node 0 pre-flight; alert ถ้า `/api/ai/health` ไม่ตอบ |
|
||||
| BullMQ job timeout (scanned PDF ใหญ่) | Timeout 120s สำหรับ poll; Worker timeout 180s; retry 3 ครั้ง |
|
||||
| Tags duplicate | `UNIQUE KEY (project_id, tag_name)` + normalize lowercase+trim ก่อน insert |
|
||||
| import_transactions accidentally dropped | Migration script ต้องมี `IF NOT EXISTS` + explicit exclusion comment |
|
||||
Reference in New Issue
Block a user