Skip to content

Commit c03415e

Browse files
authored
Merge pull request #49 from AI-Tutor-2024/develop
[FIX] 문제 생성 + 저장 API lazy 객체 문제 해결
2 parents 8fe244d + df679b2 commit c03415e

File tree

1 file changed

+52
-55
lines changed

1 file changed

+52
-55
lines changed

src/main/java/com/example/ai_tutor/domain/practice/application/ProfessorPracticeService.java

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -251,69 +251,69 @@ private User getUser(UserPrincipal userPrincipal) {
251251
public Mono<ResponseEntity<ApiResponse<ProfessorPracticeListRes>>> generateAndSavePractice(
252252
UserPrincipal userPrincipal, Long noteId, CreatePracticeReq createPracticeReq) {
253253

254-
// 유저와 교수 인증 (예외 발생 시 중단)
255-
validateUser(userPrincipal);
256-
validateProfessor(userPrincipal);
254+
// 유저와 교수 인증 (세션 내에서 실행 → Lazy 문제 없음)
255+
User user = validateUser(userPrincipal);
256+
Professor professor = validateProfessor(userPrincipal);
257+
Note note = validateNote(noteId);
257258

258-
// 비동기로 노트 조회 (블로킹 방지)
259-
return getNoteAsync(noteId)
260-
.flatMap(note -> {
261-
String summary = note.getSummary().getContent();
262-
int practiceSize = determinePracticeSize(createPracticeReq.getPracticeSize());
263-
264-
Mono<List<CreatePracticeRes>> practiceMono;
265-
if ("BOTH".equalsIgnoreCase(createPracticeReq.getType())) {
266-
int oxCount = calculateOxCount(practiceSize);
267-
int shortCount = practiceSize - oxCount;
268-
269-
Mono<List<CreatePracticeRes>> oxMono = quizGeneratorService.generateQuestions(summary, oxCount, "OX", 1);
270-
Mono<List<CreatePracticeRes>> shortMono = quizGeneratorService.generateQuestions(summary, shortCount, "SHORT", oxCount + 1);
271-
practiceMono = Mono.zip(oxMono, shortMono)
272-
.map(tuple -> combineQuestions(tuple.getT1(), tuple.getT2()));
273-
} else {
274-
practiceMono = quizGeneratorService.generateQuestions(summary, practiceSize, createPracticeReq.getType(), 1);
275-
}
276-
277-
// 기존 sequence 최대값 조회 → Mono로 감싸서 flatMap 안에서 사용
278-
return Mono.fromCallable(() -> practiceRepository.findMaxSequenceByNoteId(noteId))
279-
.subscribeOn(Schedulers.boundedElastic())
280-
.flatMap(lastSequence -> practiceMono.flatMap(practices -> {
281-
282-
int startSequence = lastSequence + 1; // 기존 마지막 번호 다음부터 시작
283-
List<Practice> entities = new ArrayList<>();
284-
285-
for (int i = 0; i < practices.size(); i++) {
286-
CreatePracticeRes p = practices.get(i);
287-
PracticeType type = PracticeType.valueOf(p.getPracticeType());
288-
289-
entities.add(Practice.builder()
290-
.note(note)
259+
// Lazy 객체 → 여기서 모두 안전하게 초기화
260+
Folder folder = note.getFolder();
261+
Long professorId = folder.getProfessor().getProfessorId();
262+
String professorName = folder.getProfessor().getProfessorName();
263+
String noteTitle = note.getTitle();
264+
Long realNoteId = note.getNoteId();
265+
266+
String summary = note.getSummary().getContent();
267+
int practiceSize = determinePracticeSize(createPracticeReq.getPracticeSize());
268+
269+
Mono<List<CreatePracticeRes>> practiceMono;
270+
if ("BOTH".equalsIgnoreCase(createPracticeReq.getType())) {
271+
int oxCount = calculateOxCount(practiceSize);
272+
int shortCount = practiceSize - oxCount;
273+
274+
Mono<List<CreatePracticeRes>> oxMono = quizGeneratorService.generateQuestions(summary, oxCount, "OX", 1);
275+
Mono<List<CreatePracticeRes>> shortMono = quizGeneratorService.generateQuestions(summary, shortCount, "SHORT", oxCount + 1);
276+
practiceMono = Mono.zip(oxMono, shortMono)
277+
.map(tuple -> combineQuestions(tuple.getT1(), tuple.getT2()));
278+
} else {
279+
practiceMono = quizGeneratorService.generateQuestions(summary, practiceSize, createPracticeReq.getType(), 1);
280+
}
281+
282+
// 비동기로 넘어가는 부분 → 엔티티 사용 x, 값만 사용 o
283+
284+
return Mono.fromCallable(() -> practiceRepository.findMaxSequenceByNoteId(noteId))
285+
.subscribeOn(Schedulers.boundedElastic())
286+
.flatMap(lastSequence -> practiceMono.flatMap(practices -> {
287+
288+
int startSequence = lastSequence + 1;
289+
List<Practice> entities = new ArrayList<>();
290+
291+
for (int i = 0; i < practices.size(); i++) {
292+
CreatePracticeRes p = practices.get(i);
293+
PracticeType type = PracticeType.valueOf(p.getPracticeType());
294+
295+
entities.add(Practice.builder()
296+
.note(note) // 여기까진 안전함
291297
.sequence(startSequence + i)
292298
.content(p.getContent())
293299
.result(p.getResult())
294300
.solution(p.getSolution())
295301
.additionalResults(type == PracticeType.OX ? null : p.getAdditionalResults())
296302
.practiceType(type)
297303
.build());
298-
}
304+
}
299305

300-
return Mono.fromCallable(() -> {
301-
practiceRepository.saveAll(entities);
302-
return entities;
306+
return Mono.fromCallable(() -> {
307+
practiceRepository.saveAll(entities);
308+
return entities.stream().map(this::toResponse).toList();
303309
}).subscribeOn(Schedulers.boundedElastic())
304-
.map(saved -> {
305-
List<ProfessorPracticeRes> responses = saved.stream()
306-
.map(this::toResponse)
307-
.toList();
308-
309-
var folder = note.getFolder();
310-
var professor = folder.getProfessor();
310+
.map(responses -> {
311311

312312
ProfessorPracticeListRes response = ProfessorPracticeListRes.builder()
313-
.noteId(note.getNoteId())
314-
.noteTitle(note.getTitle())
315-
.professorId(professor.getProfessorId())
316-
.professorName(professor.getProfessorName())
313+
.noteId(realNoteId)
314+
.noteTitle(noteTitle)
315+
.professorId(professorId)
316+
.professorName(professorName)
317317
.reqList(responses)
318318
.build();
319319

@@ -324,12 +324,9 @@ public Mono<ResponseEntity<ApiResponse<ProfessorPracticeListRes>>> generateAndSa
324324

325325
return ResponseEntity.ok(api);
326326
});
327-
}));
328-
});
327+
}));
329328
}
330329

331-
332-
333330
/** Practice → ProfessorPracticeRes 매핑용 */
334331
private ProfessorPracticeRes toResponse(Practice p) {
335332
return ProfessorPracticeRes.builder()

0 commit comments

Comments
 (0)