690529:1116 ADR-030-230 context aware #04
CI / CD Pipeline / build (push) Successful in 4m39s
CI / CD Pipeline / deploy (push) Successful in 7m59s

This commit is contained in:
2026-05-29 11:16:03 +07:00
parent 5d46504c1d
commit b68a750e4f
5 changed files with 76 additions and 3 deletions
+15 -1
View File
@@ -3,6 +3,7 @@
// Change Log
// - 2026-05-21: เพิ่ม getSystemHealth พร้อมระบบแคช Redis 30 วินาทีตาม ADR-027.
// - 2026-05-21: แก้ไข ESLint unsafe return error ใน getSystemHealth โดยใช้ interface SystemHealthResponse
// - 2026-05-29: เพิ่ม OcrService.checkHealth() เข้า getSystemHealth() เพื่อแสดงสถานะ OCR sidecar
import { Injectable, Logger, Optional } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios';
@@ -45,6 +46,7 @@ import { AiBatchJobData } from './processors/ai-batch.processor';
import { AuditLog } from '../../common/entities/audit-log.entity';
import { OllamaService } from './services/ollama.service';
import { AiQdrantService } from './qdrant.service';
import { OcrService, OcrHealthResult } from './services/ocr.service';
// ผลลัพธ์ของ Real-time Extraction
export interface ExtractionResult {
@@ -120,6 +122,7 @@ export interface SystemHealthResponse {
collections?: string[];
error?: string;
};
ocr: OcrHealthResult;
queues: {
realtime:
| {
@@ -176,6 +179,8 @@ export class AiService {
@Optional()
private readonly qdrantService?: AiQdrantService,
@Optional()
private readonly ocrService?: OcrService,
@Optional()
@InjectRedis()
private readonly redis?: Redis
) {
@@ -816,7 +821,7 @@ export class AiService {
);
}
}
const [ollama, qdrant, realtimeQueueMetrics, batchQueueMetrics] =
const [ollama, qdrant, ocr, realtimeQueueMetrics, batchQueueMetrics] =
await Promise.all([
this.ollamaService
? this.ollamaService.checkHealth()
@@ -833,12 +838,21 @@ export class AiService {
latencyMs: 0,
error: 'AiQdrantService not injected',
}),
this.ocrService
? this.ocrService.checkHealth()
: Promise.resolve({
status: 'DOWN' as const,
latencyMs: 0,
url: 'not configured',
error: 'OcrService not injected',
}),
this.getQueueMetrics(this.aiRealtimeQueue),
this.getQueueMetrics(this.aiBatchQueue),
]);
const health = {
ollama,
qdrant,
ocr,
queues: {
realtime: realtimeQueueMetrics,
batch: batchQueueMetrics,
@@ -3,6 +3,7 @@
// - 2026-05-15: เพิ่ม OCR auto-detection service สำหรับ ADR-023A.
// - 2026-05-25: แก้ไข AggregateError (empty message) จาก axios โดย wrap เป็น Error พร้อม context ที่ชัดเจน.
// - 2026-05-25: เพิ่ม path remapping (OCR_UPLOAD_BASE_PATH) เพื่อแปลง local upload path เป็น path ที่ sidecar เห็นผ่าน CIFS.
// - 2026-05-29: เพิ่ม checkHealth() เพื่อตรวจสอบสุขภาพของ PaddleOCR sidecar สำหรับ getSystemHealth() (ADR-027)
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@@ -23,6 +24,13 @@ interface PaddleOcrResponse {
text?: string;
}
export interface OcrHealthResult {
status: 'HEALTHY' | 'DOWN';
latencyMs: number;
url: string;
error?: string;
}
/** บริการเลือก fast path หรือ PaddleOCR sidecar ตามจำนวนตัวอักษรที่ extract ได้ */
@Injectable()
export class OcrService {
@@ -56,6 +64,28 @@ export class OcrService {
return localPath;
}
/** ตรวจสอบสุขภาพและ latency ของ PaddleOCR sidecar ผ่าน GET /health */
async checkHealth(): Promise<OcrHealthResult> {
const startTime = Date.now();
try {
await axios.get(`${this.ocrApiUrl}/health`, { timeout: 5000 });
return {
status: 'HEALTHY',
latencyMs: Date.now() - startTime,
url: this.ocrApiUrl,
};
} catch (err: unknown) {
const cause = err instanceof Error ? err.message : String(err);
this.logger.warn(`OCR sidecar health check failed: ${cause}`);
return {
status: 'DOWN',
latencyMs: Date.now() - startTime,
url: this.ocrApiUrl,
error: cause,
};
}
}
/** ตรวจสอบ text layer ก่อนเลือก OCR slow path */
async detectAndExtract(
input: OcrDetectionInput