251128:1700 Backend to T3.1.1
This commit is contained in:
397
2_Backend_Plan_V1_4_4.Phase6A.md
Normal file
397
2_Backend_Plan_V1_4_4.Phase6A.md
Normal file
@@ -0,0 +1,397 @@
|
||||
# “Phase 6A + Technical Design Document : Workflow DSL (Mini-Language)”**
|
||||
ออกแบบสำหรับระบบ Workflow Engine กลางของโครงการ
|
||||
**ไม่มีโค้ดผูกกับ Framework** เพื่อให้สามารถนำไป Implement ใน NestJS หรือ Microservice ใด ๆ ได้
|
||||
|
||||
---
|
||||
|
||||
## 📌 **Phase 6A – Workflow DSL Implementation Plan**
|
||||
|
||||
### 🎯 เป้าหมายของ Phase 6A
|
||||
|
||||
ใน Phase นี้ จะเริ่มสร้าง “Workflow DSL (Domain-Specific Language)” สำหรับนิยามกฎการเดินงาน (Workflow Transition Rules) ให้สามารถ:
|
||||
|
||||
* แยก **Business Workflow Logic** ออกจาก Source Code
|
||||
* แก้ไขกฎ Workflow ได้โดย **ไม่ต้องแก้โค้ดและไม่ต้อง Deploy ใหม่**
|
||||
* รองรับ Document หลายประเภท เช่น
|
||||
|
||||
* Correspondence
|
||||
* RFA
|
||||
* Internal Circulation
|
||||
* Document Transmittal
|
||||
* รองรับ Multi-step routing, skip, reject, rollback, parallel assignments
|
||||
* สามารถนำไปใช้งานทั้งใน
|
||||
|
||||
* Backend (NestJS)
|
||||
* Frontend (UI Driven)
|
||||
* External Microservices
|
||||
|
||||
---
|
||||
|
||||
### 📅 ระยะเวลา
|
||||
|
||||
**1 สัปดาห์ (หลัง Phase 6.5)**
|
||||
|
||||
---
|
||||
|
||||
### 🧩 Output ของ Phase 6A
|
||||
|
||||
* DSL Specification (Grammar)
|
||||
* JSON Schema for Workflow Definition
|
||||
* Workflow Rule Interpreter (Parser + Executor)
|
||||
* Validation Engine (Compile-time and Runtime)
|
||||
* Storage (DB Table / Registry)
|
||||
* Execution API:
|
||||
|
||||
| Action | Description |
|
||||
| -------------------------------- | ------------------------------- |
|
||||
| compile() | ตรวจ DSL → สร้าง Execution Tree |
|
||||
| evaluate(state, action, context) | ประมวลผลและส่งสถานะใหม่ |
|
||||
| preview(state) | คำนวณ Next Possible Transitions |
|
||||
| validate() | ตรวจว่า DSL ถูกต้อง |
|
||||
|
||||
---
|
||||
|
||||
## 📘 **Technical Specification – Workflow DSL**
|
||||
|
||||
---
|
||||
|
||||
### 1️⃣ Requirements
|
||||
|
||||
#### Functional Requirements
|
||||
|
||||
* นิยาม Workflow เป็นภาษาคล้าย State Machine
|
||||
* แต่ละเอกสารมี **State, Actions, Entry/Exit Events**
|
||||
* สามารถมี:
|
||||
|
||||
* Required approvals
|
||||
* Conditional transition
|
||||
* Auto-transition
|
||||
* Parallel approval
|
||||
* Return/rollback
|
||||
|
||||
####
|
||||
* Running time: < 20ms ต่อคำสั่ง
|
||||
* Hot reload ไม่ต้อง Compile ใหม่ทั้ง Backend
|
||||
* DSL ต้อง Debug ได้ง่าย
|
||||
* ต้อง Versioned
|
||||
* ต้องรองรับ Audit 100%
|
||||
|
||||
---
|
||||
|
||||
### 2️⃣ DSL Format (Human Friendly)
|
||||
|
||||
```yaml
|
||||
workflow: RFA
|
||||
version: 1.0
|
||||
|
||||
states:
|
||||
- name: DRAFT
|
||||
initial: true
|
||||
on:
|
||||
SUBMIT:
|
||||
to: IN_REVIEW
|
||||
require:
|
||||
- role: ENGINEER
|
||||
events:
|
||||
- notify: reviewer
|
||||
|
||||
- name: IN_REVIEW
|
||||
on:
|
||||
APPROVE:
|
||||
to: APPROVED
|
||||
REJECT:
|
||||
to: DRAFT
|
||||
events:
|
||||
- notify: creator
|
||||
|
||||
- name: APPROVED
|
||||
terminal: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3️⃣ Compiled Execution Model (Normalized JSON)
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow": "RFA",
|
||||
"version": "1.0",
|
||||
"states": {
|
||||
"DRAFT": {
|
||||
"initial": true,
|
||||
"transitions": {
|
||||
"SUBMIT": {
|
||||
"to": "IN_REVIEW",
|
||||
"requirements": [
|
||||
{ "role": "ENGINEER" }
|
||||
],
|
||||
"events": [
|
||||
{ "type": "notify", "target": "reviewer" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"IN_REVIEW": {
|
||||
"transitions": {
|
||||
"APPROVE": { "to": "APPROVED" },
|
||||
"REJECT": {
|
||||
"to": "DRAFT",
|
||||
"events": [
|
||||
{ "type": "notify", "target": "creator" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"APPROVED": {
|
||||
"terminal": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Frontend และ Backend สามารถแชร์ JSON นี้ร่วมกันได้
|
||||
|
||||
---
|
||||
|
||||
### 4️⃣ DSL Grammar Definition (EBNF)
|
||||
|
||||
```ebnf
|
||||
workflow = "workflow" ":" identifier ;
|
||||
version = "version" ":" number ;
|
||||
|
||||
states = "states:" state_list ;
|
||||
state_list = { state } ;
|
||||
|
||||
state = "- name:" identifier
|
||||
[ "initial:" boolean ]
|
||||
[ "terminal:" boolean ]
|
||||
[ "on:" transition_list ] ;
|
||||
|
||||
transition_list = { transition } ;
|
||||
|
||||
transition = action ":"
|
||||
indent "to:" identifier
|
||||
[ indent "require:" requirements ]
|
||||
[ indent "events:" event_list ] ;
|
||||
|
||||
requirements = "- role:" identifier | "- user:" identifier ;
|
||||
|
||||
event_list = { event } ;
|
||||
event = "- notify:" identifier ;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5️⃣ Validation Rules (Compile-Time)
|
||||
|
||||
#### 5.1 State Rules
|
||||
|
||||
* ต้องมีอย่างน้อย 1 state ที่ `initial: true`
|
||||
* หาก `terminal: true` → ต้องไม่มี transition ต่อไป
|
||||
|
||||
#### 5.2 Transition Rules
|
||||
|
||||
ตรวจสอบว่า:
|
||||
|
||||
* `to` ชี้ไปยัง state ที่มีอยู่
|
||||
* `require.role` ต้องเป็น role ที่ระบบรู้จัก
|
||||
* Action name ต้องเป็น **UPPER_CASE**
|
||||
|
||||
#### 5.3 Version Safety
|
||||
|
||||
* ทุกชุด Workflow DSL ต้องขึ้นกับ version
|
||||
* แก้ไขต้องสร้าง version ใหม่
|
||||
* ไม่ overwrite version เก่า
|
||||
* “Document ที่กำลังอยู่ใน step เดิมยังต้องใช้กฎเดิมได้”
|
||||
|
||||
---
|
||||
|
||||
### 6️⃣ Runtime Validation Rules
|
||||
|
||||
เมื่อ execute(action):
|
||||
|
||||
```
|
||||
input: current_state, action, context
|
||||
|
||||
1) ตรวจว่า state มี transition "action"
|
||||
2) ตรวจว่าผู้ใช้มีสิทธิ์ตาม require[]
|
||||
3) Compute next state
|
||||
4) Execute events[]
|
||||
5) Return next_state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7️⃣ Context Model
|
||||
|
||||
```ts
|
||||
interface WorkflowContext {
|
||||
userId: string;
|
||||
roles: string[];
|
||||
documentId: string;
|
||||
now: Date;
|
||||
payload?: any;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8️⃣ Execution API (Abstract)
|
||||
|
||||
```ts
|
||||
class WorkflowEngine {
|
||||
|
||||
load(dsl: string | object): CompiledWorkflow
|
||||
|
||||
compile(dsl: string | object): CompiledWorkflow
|
||||
|
||||
evaluate(state: string, action: string, context: WorkflowContext): EvalResult
|
||||
|
||||
getAvailableActions(state: string, context: WorkflowContext): string[]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9️⃣ Interpreter Execution Flow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Receive Action] --> B[Load Compiled Workflow]
|
||||
B --> C[Check allowed actions]
|
||||
C -->|Invalid| E[Return Error]
|
||||
C --> D[Evaluate Requirements]
|
||||
D --> F[Transition to Next State]
|
||||
F --> G[Run Events]
|
||||
G --> H[Return Success]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔟 Events System
|
||||
|
||||
รองรับ event หลายประเภท:
|
||||
|
||||
| event.type | ตัวอย่าง |
|
||||
| ----------- | ------------------------- |
|
||||
| notify | ส่ง Email/Line |
|
||||
| assign | เปลี่ยนผู้รับผิดชอบ |
|
||||
| webhook | ยิง Webhook ไปยังระบบอื่น |
|
||||
| auto_action | ทำ action ซ้ำโดยอัตโนมัติ |
|
||||
|
||||
---
|
||||
|
||||
### 11️⃣ Database Schema
|
||||
|
||||
#### Table: `workflow_definition`
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------- | ----------- | --------------------- |
|
||||
| id | UUID | PK |
|
||||
| workflow_code | varchar(50) | เช่น `RFA`, `CORR` |
|
||||
| version | int | Version number |
|
||||
| dsl | JSON | YAML/JSON DSL เก็บดิบ |
|
||||
| compiled | JSON | JSON ที่ Compile แล้ว |
|
||||
| created_at | timestamp | |
|
||||
| is_active | boolean | ใช้อยู่หรือไม่ |
|
||||
|
||||
#### Table: `workflow_history`
|
||||
|
||||
เก็บ audit แบบ immutable append-only
|
||||
|
||||
| Field | Description |
|
||||
| ----------- | --------------- |
|
||||
| workflow | Document Type |
|
||||
| document_id | เอกสารไหน |
|
||||
| from_state | เดิม |
|
||||
| to_state | ใหม่ |
|
||||
| action | คำสั่ง |
|
||||
| user | ใครเป็นคนทำ |
|
||||
| timestamp | เวลา |
|
||||
| metadata | เหตุการณ์อื่น ๆ |
|
||||
|
||||
---
|
||||
|
||||
### 12️⃣ Error Codes
|
||||
|
||||
| Code | Meaning |
|
||||
| ----------------------- | ---------------------- |
|
||||
| WF_NO_TRANSITION | Action นี้ไม่ถูกต้อง |
|
||||
| WF_RESTRICTED | User ไม่มีสิทธิ์ |
|
||||
| WF_MISSING_REQUIREMENTS | ไม่ผ่านเงื่อนไข |
|
||||
| WF_STATE_NOT_FOUND | ไม่มี state ที่อ้างอิง |
|
||||
| WF_SYNTAX_ERROR | DSL ผิดรูปแบบ |
|
||||
|
||||
---
|
||||
|
||||
### 13️⃣ Testing Strategy
|
||||
|
||||
#### Unit Tests
|
||||
|
||||
* Parse DSL → JSON
|
||||
* Invalid syntax → throw error
|
||||
* Invalid transitions → throw error
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
* Evaluate() ผ่าน 20+ cases
|
||||
* RFA ย้อนกลับ
|
||||
* Approve chain
|
||||
* Parallel review
|
||||
|
||||
#### Load Tests
|
||||
|
||||
* 1,000 documents running workflow
|
||||
* Evaluate < 20ms ต่อ action
|
||||
|
||||
---
|
||||
|
||||
### 14️⃣ Deployment Strategy
|
||||
|
||||
#### Hot Reload Options
|
||||
|
||||
* DSL stored in DB
|
||||
* Cache in Redis
|
||||
* Touched timestamp triggers:
|
||||
|
||||
```
|
||||
invalidate cache → recompile
|
||||
```
|
||||
|
||||
#### No downtime required
|
||||
|
||||
---
|
||||
|
||||
### 15️⃣ Microservice-Ready
|
||||
|
||||
DSL Engine แยกเป็น:
|
||||
|
||||
* `workflow-engine-core` → Pure JS library
|
||||
* `workflow-service` → NestJS module
|
||||
* API public:
|
||||
|
||||
```
|
||||
POST /workflow/evaluate
|
||||
GET /workflow/preview
|
||||
POST /workflow/compile
|
||||
```
|
||||
|
||||
ภายหลังสามารถนำไปวางบน:
|
||||
|
||||
* Kubernetes
|
||||
* Worker Node
|
||||
* API Gateway
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Summary
|
||||
|
||||
### สิ่งที่ Phase 6A เพิ่มเข้าในระบบ
|
||||
|
||||
✔ Workflow DSL ที่แก้ไขได้โดยไม่ต้อง Deploy
|
||||
✔ Parser + Validator + Runtime Interpreter
|
||||
✔ Database storage + Versioning
|
||||
✔ Execution API สำหรับ Backend และ Frontend
|
||||
✔ รองรับ Business Workflow ซับซ้อนทั้งหมด
|
||||
✔ Ready สำหรับ Microservice model ในอนาคต
|
||||
|
||||
Reference in New Issue
Block a user