298 lines
8.2 KiB
TypeScript
298 lines
8.2 KiB
TypeScript
|
|
// 배치 관리 API 클라이언트
|
||
|
|
// 작성일: 2024-12-23
|
||
|
|
|
||
|
|
import { apiClient } from "./client";
|
||
|
|
|
||
|
|
export interface BatchJob {
|
||
|
|
id?: number;
|
||
|
|
job_name: string;
|
||
|
|
description?: string;
|
||
|
|
job_type: 'collection' | 'sync' | 'cleanup' | 'custom';
|
||
|
|
schedule_cron?: string;
|
||
|
|
is_active: string;
|
||
|
|
config_json?: Record<string, any>;
|
||
|
|
last_executed_at?: Date;
|
||
|
|
next_execution_at?: Date;
|
||
|
|
execution_count: number;
|
||
|
|
success_count: number;
|
||
|
|
failure_count: number;
|
||
|
|
created_date?: Date;
|
||
|
|
created_by?: string;
|
||
|
|
updated_date?: Date;
|
||
|
|
updated_by?: string;
|
||
|
|
company_code: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BatchJobFilter {
|
||
|
|
job_name?: string;
|
||
|
|
job_type?: string;
|
||
|
|
is_active?: string;
|
||
|
|
company_code?: string;
|
||
|
|
search?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BatchExecution {
|
||
|
|
id?: number;
|
||
|
|
job_id: number;
|
||
|
|
execution_status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
|
||
|
|
started_at?: Date;
|
||
|
|
completed_at?: Date;
|
||
|
|
execution_time_ms?: number;
|
||
|
|
result_data?: Record<string, any>;
|
||
|
|
error_message?: string;
|
||
|
|
log_details?: string;
|
||
|
|
created_date?: Date;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BatchMonitoring {
|
||
|
|
total_jobs: number;
|
||
|
|
active_jobs: number;
|
||
|
|
running_jobs: number;
|
||
|
|
failed_jobs_today: number;
|
||
|
|
successful_jobs_today: number;
|
||
|
|
recent_executions: BatchExecution[];
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface ApiResponse<T> {
|
||
|
|
success: boolean;
|
||
|
|
data?: T;
|
||
|
|
message?: string;
|
||
|
|
error?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export class BatchAPI {
|
||
|
|
private static readonly BASE_PATH = "/batch";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 목록 조회
|
||
|
|
*/
|
||
|
|
static async getBatchJobs(filter: BatchJobFilter = {}): Promise<BatchJob[]> {
|
||
|
|
try {
|
||
|
|
const params = new URLSearchParams();
|
||
|
|
|
||
|
|
if (filter.job_name) params.append("job_name", filter.job_name);
|
||
|
|
if (filter.job_type) params.append("job_type", filter.job_type);
|
||
|
|
if (filter.is_active) params.append("is_active", filter.is_active);
|
||
|
|
if (filter.company_code) params.append("company_code", filter.company_code);
|
||
|
|
if (filter.search) params.append("search", filter.search);
|
||
|
|
|
||
|
|
const response = await apiClient.get<ApiResponse<BatchJob[]>>(
|
||
|
|
`${this.BASE_PATH}?${params.toString()}`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 목록 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data || [];
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 목록 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 상세 조회
|
||
|
|
*/
|
||
|
|
static async getBatchJobById(id: number): Promise<BatchJob> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.get<ApiResponse<BatchJob>>(`${this.BASE_PATH}/${id}`);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.data.data) {
|
||
|
|
throw new Error("배치 작업을 찾을 수 없습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 생성
|
||
|
|
*/
|
||
|
|
static async createBatchJob(data: BatchJob): Promise<BatchJob> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.post<ApiResponse<BatchJob>>(this.BASE_PATH, data);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 생성에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.data.data) {
|
||
|
|
throw new Error("생성된 배치 작업 정보를 받을 수 없습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 생성 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 수정
|
||
|
|
*/
|
||
|
|
static async updateBatchJob(id: number, data: Partial<BatchJob>): Promise<BatchJob> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.put<ApiResponse<BatchJob>>(`${this.BASE_PATH}/${id}`, data);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 수정에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.data.data) {
|
||
|
|
throw new Error("수정된 배치 작업 정보를 받을 수 없습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 수정 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 삭제
|
||
|
|
*/
|
||
|
|
static async deleteBatchJob(id: number): Promise<void> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.delete<ApiResponse<null>>(`${this.BASE_PATH}/${id}`);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 삭제에 실패했습니다.");
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 삭제 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 작업 수동 실행
|
||
|
|
*/
|
||
|
|
static async executeBatchJob(id: number): Promise<BatchExecution> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.post<ApiResponse<BatchExecution>>(`${this.BASE_PATH}/${id}/execute`);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 작업 실행에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.data.data) {
|
||
|
|
throw new Error("배치 실행 정보를 받을 수 없습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 작업 실행 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 실행 목록 조회
|
||
|
|
*/
|
||
|
|
static async getBatchExecutions(jobId?: number): Promise<BatchExecution[]> {
|
||
|
|
try {
|
||
|
|
const params = new URLSearchParams();
|
||
|
|
if (jobId) params.append("job_id", jobId.toString());
|
||
|
|
|
||
|
|
const response = await apiClient.get<ApiResponse<BatchExecution[]>>(
|
||
|
|
`${this.BASE_PATH}/executions/list?${params.toString()}`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 실행 목록 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data || [];
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 실행 목록 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 배치 모니터링 정보 조회
|
||
|
|
*/
|
||
|
|
static async getBatchMonitoring(): Promise<BatchMonitoring> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.get<ApiResponse<BatchMonitoring>>(
|
||
|
|
`${this.BASE_PATH}/monitoring/status`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "배치 모니터링 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!response.data.data) {
|
||
|
|
throw new Error("배치 모니터링 정보를 받을 수 없습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data;
|
||
|
|
} catch (error) {
|
||
|
|
console.error("배치 모니터링 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 지원되는 작업 타입 조회
|
||
|
|
*/
|
||
|
|
static async getSupportedJobTypes(): Promise<Array<{ value: string; label: string }>> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.get<ApiResponse<{ types: Array<{ value: string; label: string }> }>>(
|
||
|
|
`${this.BASE_PATH}/types/supported`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "작업 타입 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data?.types || [];
|
||
|
|
} catch (error) {
|
||
|
|
console.error("작업 타입 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 스케줄 프리셋 조회
|
||
|
|
*/
|
||
|
|
static async getSchedulePresets(): Promise<Array<{ value: string; label: string }>> {
|
||
|
|
try {
|
||
|
|
const response = await apiClient.get<ApiResponse<{ presets: Array<{ value: string; label: string }> }>>(
|
||
|
|
`${this.BASE_PATH}/schedules/presets`
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!response.data.success) {
|
||
|
|
throw new Error(response.data.message || "스케줄 프리셋 조회에 실패했습니다.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return response.data.data?.presets || [];
|
||
|
|
} catch (error) {
|
||
|
|
console.error("스케줄 프리셋 조회 오류:", error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 실행 상태 옵션 조회
|
||
|
|
*/
|
||
|
|
static getExecutionStatusOptions() {
|
||
|
|
return [
|
||
|
|
{ value: 'pending', label: '대기 중' },
|
||
|
|
{ value: 'running', label: '실행 중' },
|
||
|
|
{ value: 'completed', label: '완료' },
|
||
|
|
{ value: 'failed', label: '실패' },
|
||
|
|
{ value: 'cancelled', label: '취소됨' },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
}
|