11package inu .codin .codin .domain .lecture .service ;
22
33import inu .codin .codin .domain .elasticsearch .indexer .LectureStartupIndexer ;
4+ import inu .codin .codin .domain .lecture .dto .MetaMode ;
45import inu .codin .codin .domain .lecture .exception .LectureErrorCode ;
56import inu .codin .codin .domain .lecture .exception .LectureUploadException ;
67import lombok .RequiredArgsConstructor ;
1213import java .io .File ;
1314import java .io .FileOutputStream ;
1415import java .io .IOException ;
16+ import java .nio .file .Paths ;
17+ import java .util .ArrayList ;
18+ import java .util .List ;
1519
1620@ Slf4j
1721@ Service
@@ -28,6 +32,8 @@ public class LectureUploadService {
2832
2933 private String ROOM_PROGRAM = "dayTimeOfRoom.py" ;
3034 private String LECTURE_PROGRAM = "infoOfLecture.py" ;
35+ private static final String META_PROGRAM = "load_metadata.py" ;
36+
3137
3238 public void uploadNewSemesterLectures (MultipartFile file ){
3339 try {
@@ -68,6 +74,63 @@ public void uploadNewSemesterRooms(MultipartFile file) {
6874 }
6975 }
7076
77+ public void uploadLectureMeta (MultipartFile file , MetaMode mode ) {
78+ try {
79+ saveFile (file ); // 기존 그대로 사용
80+ executeMetaLoader (file , mode );
81+ log .info ("[uploadLectureMeta] {} 메타 업데이트 완료" , file .getOriginalFilename ());
82+
83+ try { indexer .lectureIndex (); } catch (Exception e ) {
84+ log .warn ("[uploadLectureMeta] 색인 갱신 경고: {}" , e .getMessage ());
85+ }
86+
87+ } catch (LectureUploadException e ) {
88+ throw e ;
89+ } catch (Exception e ) {
90+ log .error (e .getMessage (), e );
91+ throw new LectureUploadException (LectureErrorCode .LECTURE_UPLOAD_FAIL , e .getMessage ());
92+ }
93+ }
94+
95+
96+ /** 메타 로더 실행 헬퍼: load_metadata.py <excel> [--keywords] [--tags] [--pre-courses] | --all */
97+ private void executeMetaLoader (MultipartFile file ,MetaMode mode ) {
98+ String scriptPath = Paths .get (UPLOAD_DIR , META_PROGRAM ).toString ();
99+ String excelPath = Paths .get (UPLOAD_DIR , file .getOriginalFilename ()).toString ();
100+
101+ List <String > cmd = new ArrayList <>();
102+ cmd .add (PYTHON_DIR ); // ex) /usr/bin/python3 or venv/bin/python
103+ cmd .add (scriptPath ); // load_metadata.py 절대/상대 경로
104+ cmd .add (excelPath ); // 업로드된 엑셀 파일 경로
105+
106+ switch (mode ) {
107+ case ALL -> cmd .add ("--all" );
108+ case KEYWORDS -> cmd .add ("--keywords" );
109+ case TAGS -> cmd .add ("--tags" );
110+ case PRE_COURSES -> cmd .add ("--pre-courses" );
111+ }
112+ ProcessBuilder pb = new ProcessBuilder (cmd );
113+ pb .redirectErrorStream (true );
114+
115+ try {
116+ Process p = pb .start ();
117+ StringBuilder out = new StringBuilder ();
118+ try (var br = new java .io .BufferedReader (new java .io .InputStreamReader (p .getInputStream ()))) {
119+ String line ;
120+ while ((line = br .readLine ()) != null ) {
121+ out .append (line ).append ('\n' );
122+ log .debug ("[Python Output] {}" , line );
123+ }
124+ }
125+ int exit = p .waitFor ();
126+ if (exit != 0 ) {
127+ throw new LectureUploadException (LectureErrorCode .LECTURE_UPLOAD_FAIL , out .toString ());
128+ }
129+ } catch (IOException | InterruptedException e ) {
130+ throw new LectureUploadException (LectureErrorCode .LECTURE_UPLOAD_FAIL , e .getMessage ());
131+ }
132+ }
133+
71134 private void saveFile (MultipartFile file ) {
72135 String originalName = file .getOriginalFilename ();
73136 if (originalName == null || originalName .isBlank ()) {
0 commit comments