Skip to content

Commit

Permalink
refactor: 코드 리펙토링
Browse files Browse the repository at this point in the history
- 사용하지 않는 코드 삭제
- 퀴즈 상태 전체 끄기 메소드 위치 이동 및 쿼리 최적화
- Transactional 삭제
  • Loading branch information
gikhoon committed Aug 14, 2024
1 parent ecd0c06 commit e276a64
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
import org.cotato.csquiz.api.socket.dto.QuizOpenRequest;
import org.cotato.csquiz.api.socket.dto.QuizSocketRequest;
import org.cotato.csquiz.api.socket.dto.SocketTokenDto;
import org.cotato.csquiz.domain.education.service.RecordService;
import org.cotato.csquiz.domain.education.service.SocketService;
import org.cotato.csquiz.domain.education.service.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -25,43 +24,45 @@
public class SocketController {

private final SocketService socketService;
private final EducationService educationService;
private final RecordService recordService;
private final QuizSolveService quizSolveService;

@PatchMapping("/start/csquiz")
public ResponseEntity<Void> openCSQuiz(@RequestBody @Valid QuizOpenRequest request) {
socketService.openCSQuiz(request);
educationService.openCSQuiz(request);
recordService.saveAnswersToCache(request);
return ResponseEntity.noContent().build();
}

@PatchMapping("/access")
public ResponseEntity<Void> accessQuiz(@RequestBody @Valid QuizSocketRequest request) {
socketService.accessQuiz(request);
quizSolveService.accessQuiz(request);
recordService.saveAnswer(request);
return ResponseEntity.noContent().build();
}

@PatchMapping("/start")
public ResponseEntity<Void> startQuizSolve(@RequestBody @Valid QuizSocketRequest request) {
socketService.startQuizSolve(request);
quizSolveService.startQuizSolve(request);
return ResponseEntity.noContent().build();
}

@PatchMapping("/deny")
public ResponseEntity<Void> denyQuiz(@RequestBody @Valid QuizSocketRequest request) {
socketService.denyQuiz(request);
quizSolveService.denyQuiz(request);
return ResponseEntity.noContent().build();
}

@PatchMapping("/stop")
public ResponseEntity<Void> stopQuizSolve(@RequestBody @Valid QuizSocketRequest request) {
socketService.stopQuizSolve(request);
quizSolveService.stopQuizSolve(request);
return ResponseEntity.noContent().build();
}

@PatchMapping("/close/csquiz")
public ResponseEntity<Void> stopAllQuiz(@RequestBody @Valid EducationCloseRequest request) {
socketService.stopAllQuiz(request);
public ResponseEntity<Void> closeEducation(@RequestBody @Valid EducationCloseRequest request) {
educationService.closeEducation(request);
return ResponseEntity.noContent().build();
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/cotato/csquiz/common/SchedulerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cotato.csquiz.domain.auth.entity.RefusedMember;
import org.cotato.csquiz.domain.education.service.EducationService;
import org.cotato.csquiz.domain.education.service.QuizService;
import org.cotato.csquiz.domain.education.service.SocketService;
import org.cotato.csquiz.domain.auth.enums.MemberRole;
import org.cotato.csquiz.domain.auth.repository.MemberRepository;
Expand All @@ -21,7 +23,7 @@ public class SchedulerService {

private final RefusedMemberRepository refusedMemberRepository;
private final MemberRepository memberRepository;
private final SocketService socketService;
private final EducationService educationService;

@Transactional
@Scheduled(cron = "0 0 0 * * *")
Expand All @@ -42,7 +44,7 @@ public void updateRefusedMember() {
@Transactional
@Scheduled(cron = "0 0 2 * * SAT")
public void closeAllCsQuiz() {
socketService.closeAllFlags();
educationService.closeAllFlags();
log.info("[ CS 퀴즈 모두 닫기 Scheduler 완료 ]");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ public void startQuiz(Long quizId) {
log.info("[풀이 신호 전송 후 사용자 : {}]", CLIENTS.keySet());
}

public void stopQuiz(Quiz quiz) {
QuizStopResponse response = QuizStopResponse.from(quiz.getId());
public void stopQuiz(Long quizId) {
QuizStopResponse response = QuizStopResponse.from(quizId);
for (WebSocketSession clientSession : CLIENTS.values()) {
sendMessage(clientSession, response);
}
Expand All @@ -155,7 +155,7 @@ public void sendWinnerCommand(Long educationId) {
}
}

public void stopAllQuiz(Long educationId) {
public void stopEducation(Long educationId) {
CsQuizStopResponse response = CsQuizStopResponse.from(EXIT_COMMAND, educationId);
for (WebSocketSession clientSession : CLIENTS.values()) {
sendMessage(clientSession, response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,14 @@ public interface QuizRepository extends JpaRepository<Quiz, Long> {

List<Quiz> findAllByEducationId(Long educationId);

List<Quiz> findAllByStatus(QuizStatus status);

Optional<Quiz> findByStatusAndEducationId(QuizStatus status, Long educationId);

List<Quiz> findAllByStart(QuizStatus quizStatus);
List<Quiz> findAllByStatusOrStart(QuizStatus status, QuizStatus start);

@Transactional
@Modifying
@Query("select q from Quiz q where q.education.id in :educationIds")
List<Quiz> findAllByEducationIdsInQuery(@Param("educationIds") List<Long> educationIds);

Optional<Quiz> findByEducationIdAndNumber(Long educationId, Integer i);

Optional<Quiz> findFirstByEducationOrderByNumberDesc(Education education);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
import org.cotato.csquiz.api.education.dto.EducationIdOfQuizResponse;
import org.cotato.csquiz.api.education.dto.FindEducationStatusResponse;
import org.cotato.csquiz.api.education.dto.UpdateEducationRequest;
import org.cotato.csquiz.api.socket.dto.EducationCloseRequest;
import org.cotato.csquiz.api.socket.dto.QuizOpenRequest;
import org.cotato.csquiz.domain.education.entity.Education;
import org.cotato.csquiz.domain.education.entity.Quiz;
import org.cotato.csquiz.domain.education.enums.EducationStatus;
import org.cotato.csquiz.domain.education.enums.QuizStatus;
import org.cotato.csquiz.domain.education.repository.EducationRepository;
import org.cotato.csquiz.domain.education.repository.QuizRepository;
import org.cotato.csquiz.domain.generation.entity.Session;
Expand All @@ -31,6 +35,8 @@ public class EducationService {
private final EducationRepository educationRepository;
private final QuizRepository quizRepository;
private final SessionRepository sessionRepository;
private final SocketService socketService;


@Transactional
public CreateEducationResponse createEducation(CreateEducationRequest request) {
Expand Down Expand Up @@ -80,12 +86,51 @@ private void validateNotEmpty(String newSubject) {
.orElseThrow(() -> new AppException(ErrorCode.SUBJECT_INVALID));
}

@Transactional
public void openCSQuiz(QuizOpenRequest request) {
Education education = findEducationById(request.educationId());

checkEducationBefore(education);

education.updateStatus(EducationStatus.ONGOING);
}

private void checkEducationBefore(Education education) {
if (EducationStatus.BEFORE != education.getStatus()) {
throw new AppException(ErrorCode.EDUCATION_STATUS_NOT_BEFORE);
}
}

@Transactional
public void closeAllFlags() {
quizRepository.findAllByStatusOrStart(QuizStatus.QUIZ_ON, QuizStatus.QUIZ_ON)
.forEach(quiz -> {
quiz.updateStatus(QuizStatus.QUIZ_OFF);
quiz.updateStart(QuizStatus.QUIZ_OFF);
});
}

@Transactional
public void closeEducation(EducationCloseRequest request) {
closeAllFlags();

Education education = findEducationById(request.educationId());

education.updateStatus(EducationStatus.FINISHED);
socketService.stopEducation(education.getId());
}

public List<AllEducationResponse> findEducationListByGeneration(Long generationId) {
return findAllEducationByGenerationId(generationId).stream()
.map(AllEducationResponse::from)
.toList();
}

private Education findEducationById(Long educationId) {
return educationRepository.findById(educationId)
.orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다."));
}

public EducationIdOfQuizResponse findEducationIdOfQuizId(Long quizId) {
Quiz quiz = quizRepository.findById(quizId)
.orElseThrow(() -> new EntityNotFoundException("해당 문제를 찾을 수 없습니다."));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.cotato.csquiz.domain.education.service;

import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cotato.csquiz.api.socket.dto.QuizSocketRequest;
import org.cotato.csquiz.common.error.ErrorCode;
import org.cotato.csquiz.common.error.exception.AppException;
import org.cotato.csquiz.domain.education.entity.Education;
import org.cotato.csquiz.domain.education.entity.Quiz;
import org.cotato.csquiz.domain.education.enums.EducationStatus;
import org.cotato.csquiz.domain.education.enums.QuizStatus;
import org.cotato.csquiz.domain.education.repository.EducationRepository;
import org.cotato.csquiz.domain.education.repository.QuizRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class QuizSolveService {

private final SocketService socketService;
private final EducationRepository educationRepository;
private final QuizRepository quizRepository;
private final EducationService educationService;

@Transactional
public void accessQuiz(QuizSocketRequest request) {
Quiz quiz = findQuizById(request.quizId());

checkEducationOpen(quiz.getEducation());

educationService.closeAllFlags();

quiz.updateStatus(QuizStatus.QUIZ_ON);
socketService.accessQuiz(quiz.getId());
}

@Transactional
public void denyQuiz(QuizSocketRequest request) {
Quiz quiz = findQuizById(request.quizId());

checkEducationOpen(quiz.getEducation());

quiz.updateStatus(QuizStatus.QUIZ_OFF);
quiz.updateStart(QuizStatus.QUIZ_OFF);
}

@Transactional
public void startQuizSolve(QuizSocketRequest request) {
Quiz quiz = findQuizById(request.quizId());

checkEducationOpen(quiz.getEducation());
checkQuizIsStarted(quiz);

sleepRandomTime(quiz);
quiz.updateStart(QuizStatus.QUIZ_ON);

socketService.startQuizSolve(quiz.getId());
}

private void checkQuizIsStarted(Quiz quiz) {
if (quiz.getStatus().equals(QuizStatus.QUIZ_OFF)) {
throw new AppException(ErrorCode.QUIZ_ACCESS_DENIED);
}
}

private void sleepRandomTime(Quiz quiz) {
try {
Thread.sleep(1000L * quiz.getAppearSecond());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

@Transactional
public void stopQuizSolve(QuizSocketRequest request) {
Quiz quiz = findQuizById(request.quizId());
checkEducationOpen(quiz.getEducation());

quiz.updateStart(QuizStatus.QUIZ_OFF);
socketService.stopQuizSolve(quiz.getId());
}

private void checkEducationOpen(Education education) {
if (EducationStatus.ONGOING != education.getStatus()) {
throw new AppException(ErrorCode.EDUCATION_CLOSED);
}
}

private Quiz findQuizById(Long quizId) {
return quizRepository.findById(quizId)
.orElseThrow(() -> new EntityNotFoundException("해당 퀴즈를 찾을 수 없습니다."));
}

private Education findEducationById(Long educationId) {
return educationRepository.findById(educationId)
.orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다."));
}
}
Loading

0 comments on commit e276a64

Please sign in to comment.