690524:2148 ADR-028-228-migration #05
CI / CD Pipeline / build (push) Successful in 4m8s
CI / CD Pipeline / deploy (push) Successful in 3m42s

This commit is contained in:
2026-05-24 21:48:30 +07:00
parent 1564f8648d
commit dcd1a9855e
8 changed files with 167 additions and 6 deletions
@@ -65,9 +65,11 @@ CREATE TABLE IF NOT EXISTS migration_errors (
'UNKNOWN'
),
error_message TEXT,
job_id VARCHAR(100) NULL,
raw_ai_response TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_batch_id (batch_id),
INDEX idx_job_id (job_id),
INDEX idx_error_type (error_type)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Migration: Error Log';
@@ -0,0 +1,10 @@
-- File: specs/03-Data-and-Storage/deltas/2026-05-24-add-migration-errors-job-id.rollback.sql
-- Change Log:
-- - 2026-05-24: Rollback สำหรับลบ job_id ออกจาก migration_errors
-- Delta Rollback: ลบคอลัมน์ job_id สำหรับ Migration Error Log
-- Related ADR: ADR-009, ADR-023A, ADR-028
ALTER TABLE migration_errors
DROP INDEX idx_migration_errors_job_id,
DROP COLUMN job_id;
@@ -0,0 +1,11 @@
-- File: specs/03-Data-and-Storage/deltas/2026-05-24-add-migration-errors-job-id.sql
-- Change Log:
-- - 2026-05-24: เพิ่ม job_id ใน migration_errors เพื่อผูก error log กับ BullMQ AI job
-- Delta: เพิ่มคอลัมน์ job_id สำหรับ Migration Error Log
-- Related ADR: ADR-009, ADR-023A, ADR-028
ALTER TABLE migration_errors
ADD COLUMN job_id VARCHAR(100) NULL COMMENT 'BullMQ Job ID สำหรับ trace error ของ AI migration'
AFTER error_message,
ADD INDEX idx_migration_errors_job_id (job_id);
@@ -69,9 +69,11 @@ CREATE TABLE IF NOT EXISTS migration_errors (
'UNKNOWN'
),
error_message TEXT,
job_id VARCHAR(100) NULL,
raw_ai_response TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_batch_id (batch_id),
INDEX idx_job_id (job_id),
INDEX idx_error_type (error_type)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Migration: Error Log (ลบได้หลัง Migration เสร็จ)';
@@ -574,7 +574,7 @@
},
{
"parameters": {
"jsCode": "const fs = require('fs');\nconst items = $input.all();\nconst config = $('Set Configuration').first().json.config;\n\nconst csvPath = `${config.LOG_PATH}/error_log_${config.BATCH_ID}.csv`;\nconst header = 'timestamp,document_number,error_type,error_message,job_id\\n';\nconst esc = (s) => `\"${String(s || '').replace(/\"/g, '\"\"')}\"`;\n\nif (!fs.existsSync(csvPath)) {\n fs.writeFileSync(csvPath, header, 'utf8');\n}\n\nfor (const item of items) {\n const line = [\n new Date().toISOString(),\n esc(item.json.document_number),\n esc(item.json.error_type || 'UNKNOWN'),\n esc(item.json.error || item.json.parse_error),\n esc(item.json.job_id || '')\n ].join(',') + '\\n';\n fs.appendFileSync(csvPath, line, 'utf8');\n}\n\nreturn items;"
"jsCode": "const fs = require('fs');\nconst items = $input.all();\nconst config = $('Set Configuration').first().json.config;\n\nconst ERROR_TYPE_MAP = {\n AI_JOB_FAILED: 'API_ERROR',\n PARSE_ERROR: 'AI_PARSE_ERROR',\n TOKEN_EXPIRED: 'API_ERROR',\n};\nconst ALLOWED_ERROR_TYPES = new Set([\n 'FILE_NOT_FOUND',\n 'MISSING_FILENAME',\n 'FILE_ERROR',\n 'AI_PARSE_ERROR',\n 'API_ERROR',\n 'DB_ERROR',\n 'SECURITY',\n 'UNKNOWN',\n]);\nconst normalizeErrorType = (type) => {\n const mappedType = ERROR_TYPE_MAP[type] || type || 'UNKNOWN';\n return ALLOWED_ERROR_TYPES.has(mappedType) ? mappedType : 'UNKNOWN';\n};\n\nconst csvPath = `${config.LOG_PATH}/error_log_${config.BATCH_ID}.csv`;\nconst header = 'timestamp,document_number,error_type,error_message,job_id\\n';\nconst esc = (s) => `\"${String(s || '').replace(/\"/g, '\"\"')}\"`;\n\nif (!fs.existsSync(csvPath)) {\n fs.writeFileSync(csvPath, header, 'utf8');\n}\n\nfor (const item of items) {\n item.json.document_number = item.json.document_number || 'WORKFLOW';\n item.json.error_type = normalizeErrorType(item.json.error_type);\n item.json.error = item.json.error || item.json.parse_error || item.json.message || '';\n item.json.job_id = item.json.job_id || '';\n\n const line = [\n new Date().toISOString(),\n esc(item.json.document_number),\n esc(item.json.error_type),\n esc(item.json.error),\n esc(item.json.job_id)\n ].join(',') + '\\n';\n fs.appendFileSync(csvPath, line, 'utf8');\n}\n\nreturn items;"
},
"id": "511428dc-3aad-4de1-a9dc-9a87c791371e",
"name": "Log Error to CSV",
@@ -605,7 +605,7 @@
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ batchId: $('Set Configuration').first().json.config.BATCH_ID, documentNumber: $json.document_number || 'WORKFLOW', errorType: $json.error_type || 'UNKNOWN', errorMessage: $json.error || $json.parse_error || $json.message || '', jobId: $json.job_id || '' }) }}",
"jsonBody": "={{ JSON.stringify({ batchId: $('Set Configuration').first().json.config.BATCH_ID, documentNumber: $json.document_number, errorType: $json.error_type, errorMessage: $json.error, jobId: $json.job_id || '' }) }}",
"options": {
"timeout": 10000
}