diff options
| -rw-r--r-- | .env.development | 5 | ||||
| -rw-r--r-- | .env.production | 5 | ||||
| -rw-r--r-- | instrumentation.ts | 10 | ||||
| -rw-r--r-- | lib/edp-sync/sync-edp.ts | 127 |
4 files changed, 144 insertions, 3 deletions
diff --git a/.env.development b/.env.development index b498c57d..673a833b 100644 --- a/.env.development +++ b/.env.development @@ -183,4 +183,7 @@ SWP_MONUT_DIR="/mnt/swp-smb-dir/" # \\60.100.91.61\SBox 경로를 마운트해 # POS (EMLS, Documentum) DOCUMENTUM_NFS="/mnt/nfs-documentum/" # 품질/운영 공통 -POS_APP_CODE="SQ13" # 품질, 운영의 경우 SO13
\ No newline at end of file +POS_APP_CODE="SQ13" # 품질, 운영의 경우 SO13 + +# EDP 동기화 크론 설정 +EDP_MASTER_DATA_SYNC_CRON="*/20 * * * *"
\ No newline at end of file diff --git a/.env.production b/.env.production index 3b2da77b..3f4392ab 100644 --- a/.env.production +++ b/.env.production @@ -185,4 +185,7 @@ SWP_MONUT_DIR="/mnt/swp-smb-dir/" # \\60.100.91.61\SBox 경로를 마운트해 # POS (EMLS, Documentum) DOCUMENTUM_NFS="/mnt/nfs-documentum/" # 품질/운영 공통 -POS_APP_CODE="SQ13" # 품질, 운영의 경우 SO13
\ No newline at end of file +POS_APP_CODE="SQ13" # 품질, 운영의 경우 SO13 + +# EDP 동기화 크론 설정 +EDP_MASTER_DATA_SYNC_CRON="*/20 * * * *"
\ No newline at end of file diff --git a/instrumentation.ts b/instrumentation.ts index b3692aa0..3d221a3a 100644 --- a/instrumentation.ts +++ b/instrumentation.ts @@ -1,4 +1,3 @@ -import { triggerSync } from './lib/nonsap-sync/enhanced-sync-service'; /** * instrumentation 진입점 - 여러 JOB들이 등록될 수 있으므로 확장성을 위해 최소한의 메서드 호출만으로 유지 @@ -63,6 +62,15 @@ export async function register() { // 스케줄러 실패해도 애플리케이션은 계속 실행 } + try { + // EDP 마스터 데이터 동기화 스케줄러 시작 (옥프로 요청사항, 20분마다 EDP에서 들어오는 기준정보 동기화) + const { startEDPMasterDataSyncScheduler } = await import('./lib/edp-sync/sync-edp'); + await startEDPMasterDataSyncScheduler(); + } catch { + console.error('Failed to start EDP master data sync scheduler.'); + // 스케줄러 실패해도 애플리케이션은 계속 실행 + } + // 구매그룹코드는 oracle에서 선택기로 확인하고, 유저가 클릭했을 때 업데이트 처리, 유저 1:1 대응 (김수진 프로 확인) // try { // // 사용자 코드 동기화 스케줄러 시작 (구매그룹코드) diff --git a/lib/edp-sync/sync-edp.ts b/lib/edp-sync/sync-edp.ts new file mode 100644 index 00000000..26f3d493 --- /dev/null +++ b/lib/edp-sync/sync-edp.ts @@ -0,0 +1,127 @@ +// EDP 마스터 데이터 동기화 함수들 +// SEDP API에서 마스터 데이터를 가져와 데이터베이스에 동기화하는 함수들 + +import { syncTagSubfields } from "@/lib/sedp/sync-tag-types"; +import { syncTagFormMappings } from "@/lib/sedp/sync-form"; +import { syncObjectClasses } from "@/lib/sedp/sync-object-class"; + +/** + * EDP 마스터 데이터를 순차적으로 동기화하는 메인 함수 + * 1. 오브젝트 클래스 동기화 (태그 타입 포함) + * 2. 태그 서브필드 동기화 + * 3. 태그 폼 매핑 동기화 + */ +export async function syncEDPMasterData(): Promise<{ + success: boolean; + message: string; + results: { + objectClasses?: any; + tagSubfields?: any; + tagFormMappings?: any; + }; + totalExecutionTime: number; +}> { + const startTime = Date.now(); + const results: any = {}; + + try { + console.log('🚀 EDP 마스터 데이터 동기화 시작:', new Date().toISOString()); + + // 1. 오브젝트 클래스 동기화 (태그 타입 포함) + console.log('1단계: 오브젝트 클래스 동기화 시작...'); + try { + results.objectClasses = await syncObjectClasses(); + console.log('오브젝트 클래스 동기화 완료'); + } catch (error) { + console.error('❌ 오브젝트 클래스 동기화 실패:', error); + results.objectClasses = { error: error instanceof Error ? error.message : String(error) }; + } + + // 2. 태그 서브필드 동기화 + console.log('2단계: 태그 서브필드 동기화 시작...'); + try { + results.tagSubfields = await syncTagSubfields(); + console.log('태그 서브필드 동기화 완료'); + } catch (error) { + console.error('❌ 태그 서브필드 동기화 실패:', error); + results.tagSubfields = { error: error instanceof Error ? error.message : String(error) }; + } + + // 3. 태그 폼 매핑 동기화 + console.log('3단계: 태그 폼 매핑 동기화 시작...'); + try { + results.tagFormMappings = await syncTagFormMappings(); + console.log('태그 폼 매핑 동기화 완료'); + } catch (error) { + console.error('❌ 태그 폼 매핑 동기화 실패:', error); + results.tagFormMappings = { error: error instanceof Error ? error.message : String(error) }; + } + + const totalExecutionTime = Date.now() - startTime; + + // 성공/실패 요약 + const resultValues = Object.values(results); + const hasErrors = resultValues.some((result: any) => + result && (result.error || (result.failed && result.failed > 0)) + ); + + const message = hasErrors + ? 'EDP 마스터 데이터 동기화 완료 (일부 단계에서 오류 발생)' + : 'EDP 마스터 데이터 동기화 완료 (모든 단계 성공)'; + + console.log(`${message} - 총 실행 시간: ${totalExecutionTime}ms`); + + return { + success: !hasErrors, + message, + results, + totalExecutionTime + }; + + } catch (error) { + const totalExecutionTime = Date.now() - startTime; + console.error('EDP 마스터 데이터 동기화 중 전체 오류 발생:', error); + + return { + success: false, + message: `EDP 마스터 데이터 동기화 실패: ${error instanceof Error ? error.message : String(error)}`, + results, + totalExecutionTime + }; + } +} + +/** + * EDP 마스터 데이터 동기화 스케줄러 시작 함수 + * instrumentation.ts에서 호출되어 cron job을 등록 + */ +export async function startEDPMasterDataSyncScheduler(): Promise<void> { + try { + // 환경변수에서 cron 표현식 가져오기 (기본값: 매 20분마다) + const cronExpression = process.env.EDP_MASTER_DATA_SYNC_CRON || '*/20 * * * *'; + + // node-cron import + const cron = (await import('node-cron')).default; + + // cron job 등록 + cron.schedule(cronExpression, async () => { + try { + console.log(`⏰ EDP 마스터 데이터 동기화 시작 (크론: ${cronExpression})`); + const result = await syncEDPMasterData(); + + if (result.success) { + console.log(`✅ EDP 마스터 데이터 동기화 성공 - 실행 시간: ${result.totalExecutionTime}ms`); + } else { + console.error(`❌ EDP 마스터 데이터 동기화 실패: ${result.message}`); + } + } catch (error) { + console.error('❌ EDP 마스터 데이터 동기화 중 예외 발생:', error); + } + }, { timezone: 'Asia/Seoul' }); + + console.log(`✅ EDP 마스터 데이터 동기화 스케줄러 등록 완료 (크론: ${cronExpression})`); + } catch (error) { + console.error('❌ EDP 마스터 데이터 동기화 스케줄러 등록 실패:', error); + throw error; + } +} |
