From b8d6aa5c946a2d2af877bba12c9b426cda1a0376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=84=EB=AF=BC=EC=98=A4?= Date: Fri, 17 Jan 2025 09:22:05 +0900 Subject: [PATCH] feat: split submit --- compose.yml | 28 +---- .../service/impl/AdminProblemServiceImpl.kt | 14 ++- .../service/impl/AdminStatisticServiceImpl.kt | 6 +- .../controller/ProblemSubmitController.kt | 18 --- .../domain/enums/ProblemSubmitVisibility.kt | 7 -- .../dto/request/ProblemSubmitRequest.kt | 10 -- .../problem/dto/response/ProblemResponse.kt | 4 +- .../response/ProblemSubmitProgressResponse.kt | 12 -- .../dto/response/ProblemSubmitResponse.kt | 16 --- .../problem/error/ProblemSubmitError.kt | 8 -- .../domain/problem/mapper/ProblemMapper.kt | 28 ++--- .../ProblemSubmitQueueRepository.kt | 7 -- .../repository/ProblemSubmitRepository.kt | 12 -- .../impl/ProblemQueryRepositoryImpl.kt | 14 +-- .../problem/service/ProblemSubmitService.kt | 8 -- .../solve/domain/problem/util/CodeExecutor.kt | 24 ++-- .../submit/controller/SubmitController.kt | 41 +++++++ .../domain/entity/Submit.kt} | 25 ++-- .../domain/enums/SubmitState.kt} | 6 +- .../submit/domain/enums/SubmitVisibility.kt | 7 ++ .../submit/dto/request/SubmitRequest.kt | 10 ++ .../dto/response/SubmitProgressResponse.kt | 12 ++ .../submit/dto/response/SubmitResponse.kt | 16 +++ .../solve/domain/submit/error/SubmitError.kt | 8 ++ .../repository/SubmitQueryRepository.kt | 65 +++++++++++ .../repository/SubmitQueueRepository.kt} | 13 +-- .../submit/repository/SubmitRepository.kt | 11 ++ .../service/SubmitService.kt} | 110 ++++++++++++------ .../handler/ProgressWebSocketHandler.kt | 14 +-- 29 files changed, 321 insertions(+), 233 deletions(-) delete mode 100644 src/main/kotlin/com/solve/domain/problem/controller/ProblemSubmitController.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitVisibility.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/dto/request/ProblemSubmitRequest.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitProgressResponse.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitResponse.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/error/ProblemSubmitError.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitQueueRepository.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitRepository.kt delete mode 100644 src/main/kotlin/com/solve/domain/problem/service/ProblemSubmitService.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/controller/SubmitController.kt rename src/main/kotlin/com/solve/domain/{problem/domain/entity/ProblemSubmit.kt => submit/domain/entity/Submit.kt} (67%) rename src/main/kotlin/com/solve/domain/{problem/domain/enums/ProblemSubmitState.kt => submit/domain/enums/SubmitState.kt} (82%) create mode 100644 src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitVisibility.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/dto/request/SubmitRequest.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/dto/response/SubmitProgressResponse.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/dto/response/SubmitResponse.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/error/SubmitError.kt create mode 100644 src/main/kotlin/com/solve/domain/submit/repository/SubmitQueryRepository.kt rename src/main/kotlin/com/solve/domain/{problem/repository/impl/ProblemSubmitQueueRepositoryImpl.kt => submit/repository/SubmitQueueRepository.kt} (60%) create mode 100644 src/main/kotlin/com/solve/domain/submit/repository/SubmitRepository.kt rename src/main/kotlin/com/solve/domain/{problem/service/impl/ProblemSubmitServiceImpl.kt => submit/service/SubmitService.kt} (54%) diff --git a/compose.yml b/compose.yml index 3cbeae4..62c764e 100644 --- a/compose.yml +++ b/compose.yml @@ -1,15 +1,4 @@ services: - mysql: - image: mysql - container_name: solve-mysql - environment: - MYSQL_ROOT_PASSWORD: root - MYSQL_DATABASE: solve - ports: - - 3306:3306 - volumes: - - ./.compose/mysql:/var/lib/mysql - restart: unless-stopped redis: image: redis container_name: solve-redis @@ -17,19 +6,4 @@ services: - 6379:6379 restart: unless-stopped volumes: - - ./.compose/redis/data:/data - - ./.compose/redis/redis.conf:/usr/local/etc/redis/redis.conf -# cassendra: -# image: cassendra -# container_name: solve-cassendra -# ports: -# - 9042:9042 -# volumes: -# - ./.compose/cassendra:/var/lib/cassendra -# environment: -# - CASSANDRA_CLUSTER_NAME=solve -# healthcheck: -# test: ["CMD", "cqlsh", "-e", "DESCRIBE KEYSPACES"] -# interval: 15s -# timeout: 10s -# retries: 10 \ No newline at end of file + - ./.compose/redis/data:/data \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/admin/problem/service/impl/AdminProblemServiceImpl.kt b/src/main/kotlin/com/solve/domain/admin/problem/service/impl/AdminProblemServiceImpl.kt index 940a735..b92e18c 100644 --- a/src/main/kotlin/com/solve/domain/admin/problem/service/impl/AdminProblemServiceImpl.kt +++ b/src/main/kotlin/com/solve/domain/admin/problem/service/impl/AdminProblemServiceImpl.kt @@ -10,9 +10,13 @@ import com.solve.domain.admin.problem.service.AdminProblemService import com.solve.domain.problem.domain.entity.Problem import com.solve.domain.problem.domain.entity.ProblemExample import com.solve.domain.problem.domain.entity.ProblemTestCase -import com.solve.domain.problem.domain.enums.ProblemSubmitState import com.solve.domain.problem.error.ProblemError -import com.solve.domain.problem.repository.* +import com.solve.domain.problem.repository.ProblemContributorRepository +import com.solve.domain.problem.repository.ProblemExampleRepository +import com.solve.domain.problem.repository.ProblemRepository +import com.solve.domain.problem.repository.ProblemTestCaseRepository +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.repository.SubmitRepository import com.solve.global.common.enums.Tier import com.solve.global.error.CustomException import com.solve.global.security.holder.SecurityHolder @@ -29,7 +33,7 @@ class AdminProblemServiceImpl( private val problemTestCaseRepository: ProblemTestCaseRepository, private val problemExampleRepository: ProblemExampleRepository, private val problemContributorRepository: ProblemContributorRepository, - private val problemSubmitRepository: ProblemSubmitRepository + private val submitRepository: SubmitRepository ) : AdminProblemService { @Transactional(readOnly = true) override fun getProblems(pageable: Pageable): Page { @@ -117,9 +121,9 @@ class AdminProblemServiceImpl( author = AdminProblemAuthorResponse.of(author), contributors = problemContributorRepository.findAllByProblem(this) .map { AdminProblemContributorResponse.of(it.user) }, - correctRate = problemSubmitRepository.findAllByProblem(this).let { submits -> + correctRate = submitRepository.findAllByProblem(this).let { submits -> (submits.map { it.state } - .filter { it == ProblemSubmitState.ACCEPTED }.size.toDouble() / submits.size * 1000).toInt() / 10.0 + .filter { it == SubmitState.ACCEPTED }.size.toDouble() / submits.size * 1000).toInt() / 10.0 }, ) diff --git a/src/main/kotlin/com/solve/domain/admin/statistic/service/impl/AdminStatisticServiceImpl.kt b/src/main/kotlin/com/solve/domain/admin/statistic/service/impl/AdminStatisticServiceImpl.kt index 64396f1..ed5d40d 100644 --- a/src/main/kotlin/com/solve/domain/admin/statistic/service/impl/AdminStatisticServiceImpl.kt +++ b/src/main/kotlin/com/solve/domain/admin/statistic/service/impl/AdminStatisticServiceImpl.kt @@ -3,7 +3,7 @@ package com.solve.domain.admin.statistic.service.impl import com.solve.domain.admin.statistic.service.AdminStatisticService import com.solve.domain.contest.repository.ContestRepository import com.solve.domain.problem.repository.ProblemRepository -import com.solve.domain.problem.repository.ProblemSubmitRepository +import com.solve.domain.submit.repository.SubmitRepository import com.solve.domain.user.repository.UserRepository import org.springframework.stereotype.Service import java.time.LocalDateTime @@ -13,7 +13,7 @@ class AdminStatisticServiceImpl( private val problemRepository: ProblemRepository, private val userRepository: UserRepository, private val contestRepository: ContestRepository, - private val problemSubmitRepository: ProblemSubmitRepository + private val submitRepository: SubmitRepository ) : AdminStatisticService { override fun getTotalUsers() = userRepository.count() @@ -21,7 +21,7 @@ class AdminStatisticServiceImpl( override fun getTotalProblems() = problemRepository.count() - override fun getTotalSubmissions() = problemSubmitRepository.count() + override fun getTotalSubmissions() = submitRepository.count() override fun getTotalOngoingContests() = LocalDateTime.now().let { contestRepository.countByEndAtGreaterThanEqualAndStartAtLessThanEqual(it, it) diff --git a/src/main/kotlin/com/solve/domain/problem/controller/ProblemSubmitController.kt b/src/main/kotlin/com/solve/domain/problem/controller/ProblemSubmitController.kt deleted file mode 100644 index cf71dc8..0000000 --- a/src/main/kotlin/com/solve/domain/problem/controller/ProblemSubmitController.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.solve.domain.problem.controller - -import com.solve.domain.problem.dto.request.ProblemSubmitRequest -import com.solve.domain.problem.service.ProblemSubmitService -import com.solve.global.common.dto.BaseResponse -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.* - -@Tag(name = "문제 제출", description = "Problem Submit") -@RestController -@RequestMapping("/problems/{problemId}/submit") -class ProblemSubmitController( - private val problemSubmitService: ProblemSubmitService -) { - @PostMapping - fun submitProblem(@PathVariable problemId: Long, @RequestBody request: ProblemSubmitRequest) = - BaseResponse.of(problemSubmitService.submitProblem(problemId, request)) -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitVisibility.kt b/src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitVisibility.kt deleted file mode 100644 index f520946..0000000 --- a/src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitVisibility.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.solve.domain.problem.domain.enums - -enum class ProblemSubmitVisibility { - PUBLIC, - PRIVATE, - PUBLIC_IF_ACCEPTED -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/dto/request/ProblemSubmitRequest.kt b/src/main/kotlin/com/solve/domain/problem/dto/request/ProblemSubmitRequest.kt deleted file mode 100644 index 22c8baf..0000000 --- a/src/main/kotlin/com/solve/domain/problem/dto/request/ProblemSubmitRequest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.solve.domain.problem.dto.request - -import com.solve.domain.problem.domain.enums.ProblemSubmitVisibility -import com.solve.global.common.enums.ProgrammingLanguage - -data class ProblemSubmitRequest( - val code: String, - val language: ProgrammingLanguage, - val visibility: ProblemSubmitVisibility, -) \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemResponse.kt b/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemResponse.kt index fe19259..7cf30aa 100644 --- a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemResponse.kt +++ b/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemResponse.kt @@ -2,8 +2,8 @@ package com.solve.domain.problem.dto.response import com.fasterxml.jackson.annotation.JsonInclude import com.solve.domain.problem.domain.entity.ProblemExample -import com.solve.domain.problem.domain.enums.ProblemSubmitState import com.solve.domain.problem.domain.enums.ProblemTag +import com.solve.domain.submit.domain.enums.SubmitState import com.solve.domain.user.domain.entity.User import com.solve.global.common.enums.Tier @@ -22,7 +22,7 @@ data class ProblemResponse( val solvedCount: Int, val examples: List, val author: ProblemAuthorResponse, - var state: ProblemSubmitState? = null + var state: SubmitState? = null ) data class ProblemAuthorResponse( diff --git a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitProgressResponse.kt b/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitProgressResponse.kt deleted file mode 100644 index 3b3557f..0000000 --- a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitProgressResponse.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.solve.domain.problem.dto.response - -import com.fasterxml.jackson.annotation.JsonInclude -import com.solve.domain.problem.domain.enums.ProblemSubmitState - -@JsonInclude(JsonInclude.Include.NON_NULL) -data class ProblemSubmitProgressResponse( - val submitId: Long, - val progress: Double, - val result: ProblemSubmitState, - val error: String? = null -) \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitResponse.kt b/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitResponse.kt deleted file mode 100644 index 552191f..0000000 --- a/src/main/kotlin/com/solve/domain/problem/dto/response/ProblemSubmitResponse.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.solve.domain.problem.dto.response - -import com.solve.domain.problem.domain.entity.ProblemSubmit -import com.solve.domain.problem.domain.enums.ProblemSubmitState - -data class ProblemSubmitResponse( - val id: Long, - val result: ProblemSubmitState -) { - companion object { - fun of(submit: ProblemSubmit) = ProblemSubmitResponse( - id = submit.id!!, - result = submit.state - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/error/ProblemSubmitError.kt b/src/main/kotlin/com/solve/domain/problem/error/ProblemSubmitError.kt deleted file mode 100644 index 36162e9..0000000 --- a/src/main/kotlin/com/solve/domain/problem/error/ProblemSubmitError.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.solve.domain.problem.error - -import com.solve.global.error.CustomError -import org.springframework.http.HttpStatus - -enum class ProblemSubmitError(override val status: HttpStatus, override val message: String) : CustomError { - PROBLEM_SUBMIT_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 제출을 찾을 수 없습니다."), -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/mapper/ProblemMapper.kt b/src/main/kotlin/com/solve/domain/problem/mapper/ProblemMapper.kt index a53430c..04cc282 100644 --- a/src/main/kotlin/com/solve/domain/problem/mapper/ProblemMapper.kt +++ b/src/main/kotlin/com/solve/domain/problem/mapper/ProblemMapper.kt @@ -1,26 +1,26 @@ package com.solve.domain.problem.mapper import com.solve.domain.problem.domain.entity.Problem -import com.solve.domain.problem.domain.enums.ProblemSubmitState import com.solve.domain.problem.dto.response.ProblemAuthorResponse import com.solve.domain.problem.dto.response.ProblemExampleResponse import com.solve.domain.problem.dto.response.ProblemResponse import com.solve.domain.problem.repository.ProblemExampleRepository -import com.solve.domain.problem.repository.ProblemSubmitRepository +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.repository.SubmitRepository import com.solve.global.security.holder.SecurityHolder import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional @Component class ProblemMapper( - private val problemSubmitRepository: ProblemSubmitRepository, + private val submitRepository: SubmitRepository, private val problemExampleRepository: ProblemExampleRepository, private val securityHolder: SecurityHolder ) { @Transactional(readOnly = true) fun toResponse(problem: Problem): ProblemResponse { - val submits = problemSubmitRepository.findAllByProblem(problem) - val acceptedSubmits = submits.filter { it.state == ProblemSubmitState.ACCEPTED } + val submits = submitRepository.findAllByProblem(problem) + val acceptedSubmits = submits.filter { it.state == SubmitState.ACCEPTED } val distinctSolvedCount = acceptedSubmits.distinctBy { it.author }.size val correctRate = if (submits.isNotEmpty()) { (acceptedSubmits.size.toDouble() / submits.size * 1000).toInt() / 10.0 @@ -44,20 +44,20 @@ class ProblemMapper( ).apply { if (!securityHolder.isAuthenticated) return@apply - val mySubmits = problemSubmitRepository.findAllByProblemAndAuthor(problem, securityHolder.user) + val mySubmits = submitRepository.findAllByProblemAndAuthor(problem, securityHolder.user) - if (mySubmits.any { it.state == ProblemSubmitState.ACCEPTED }) { - state = ProblemSubmitState.ACCEPTED + if (mySubmits.any { it.state == SubmitState.ACCEPTED }) { + state = SubmitState.ACCEPTED } else if (mySubmits.any { it.state in listOf( - ProblemSubmitState.WRONG_ANSWER, - ProblemSubmitState.RUNTIME_ERROR, - ProblemSubmitState.TIME_LIMIT_EXCEEDED, - ProblemSubmitState.MEMORY_LIMIT_EXCEEDED, - ProblemSubmitState.COMPILE_ERROR + SubmitState.WRONG_ANSWER, + SubmitState.RUNTIME_ERROR, + SubmitState.TIME_LIMIT_EXCEEDED, + SubmitState.MEMORY_LIMIT_EXCEEDED, + SubmitState.COMPILE_ERROR ) }) { - state = ProblemSubmitState.WRONG_ANSWER + state = SubmitState.WRONG_ANSWER } } } diff --git a/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitQueueRepository.kt b/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitQueueRepository.kt deleted file mode 100644 index 600dc13..0000000 --- a/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitQueueRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.solve.domain.problem.repository - -interface ProblemSubmitQueueRepository { - fun push(submitId: Long) - fun pop(): Long? - fun size(): Int -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitRepository.kt b/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitRepository.kt deleted file mode 100644 index 6b4715b..0000000 --- a/src/main/kotlin/com/solve/domain/problem/repository/ProblemSubmitRepository.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.solve.domain.problem.repository - -import com.solve.domain.problem.domain.entity.Problem -import com.solve.domain.problem.domain.entity.ProblemSubmit -import com.solve.domain.user.domain.entity.User -import org.springframework.data.jpa.repository.JpaRepository - -interface ProblemSubmitRepository : JpaRepository { - fun findAllByProblem(problem: Problem): List - fun findAllByAuthor(author: User): List - fun findAllByProblemAndAuthor(problem: Problem, author: User): List -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemQueryRepositoryImpl.kt b/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemQueryRepositoryImpl.kt index afc1619..9a5f595 100644 --- a/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemQueryRepositoryImpl.kt +++ b/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemQueryRepositoryImpl.kt @@ -5,11 +5,11 @@ import com.querydsl.jpa.impl.JPAQuery import com.querydsl.jpa.impl.JPAQueryFactory import com.solve.domain.problem.domain.entity.Problem import com.solve.domain.problem.domain.entity.QProblem -import com.solve.domain.problem.domain.entity.QProblemSubmit import com.solve.domain.problem.domain.enums.ProblemSearchOrder import com.solve.domain.problem.domain.enums.ProblemSearchState -import com.solve.domain.problem.domain.enums.ProblemSubmitState import com.solve.domain.problem.repository.ProblemQueryRepository +import com.solve.domain.submit.domain.entity.QSubmit +import com.solve.domain.submit.domain.enums.SubmitState import com.solve.global.common.enums.Tier import com.solve.global.security.holder.SecurityHolder import org.springframework.data.domain.Page @@ -24,7 +24,7 @@ class ProblemQueryRepositoryImpl( private val queryFactory: JPAQueryFactory ) : ProblemQueryRepository { private val problem = QProblem.problem - private val submit = QProblemSubmit.problemSubmit + private val submit = QSubmit.submit @Transactional(readOnly = true) override fun searchProblem( @@ -79,7 +79,7 @@ class ProblemQueryRepositoryImpl( if (state.contains(ProblemSearchState.SOLVED)) { return problem.id.`in`( submittedProblems - .filter { it.state == ProblemSubmitState.ACCEPTED } + .filter { it.state == SubmitState.ACCEPTED } .map { it.problem.id } ) } @@ -93,7 +93,7 @@ class ProblemQueryRepositoryImpl( if (state.contains(ProblemSearchState.SOLVING)) { return problem.id.`in`( submittedProblems - .filter { it.state != ProblemSubmitState.ACCEPTED } + .filter { it.state != SubmitState.ACCEPTED } .map { it.problem.id } ) } @@ -111,7 +111,7 @@ class ProblemQueryRepositoryImpl( query.leftJoin(submit).on(submit.problem.eq(problem)) .groupBy(problem) .orderBy( - submit.state.`when`(ProblemSubmitState.ACCEPTED) + submit.state.`when`(SubmitState.ACCEPTED) .then(1L) .otherwise(0L) .sum() @@ -125,7 +125,7 @@ class ProblemQueryRepositoryImpl( query.leftJoin(submit).on(submit.problem.eq(problem)) .groupBy(problem) .orderBy( - submit.state.`when`(ProblemSubmitState.ACCEPTED) + submit.state.`when`(SubmitState.ACCEPTED) .then(1L) .otherwise(0L) .sum() diff --git a/src/main/kotlin/com/solve/domain/problem/service/ProblemSubmitService.kt b/src/main/kotlin/com/solve/domain/problem/service/ProblemSubmitService.kt deleted file mode 100644 index 175a4eb..0000000 --- a/src/main/kotlin/com/solve/domain/problem/service/ProblemSubmitService.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.solve.domain.problem.service - -import com.solve.domain.problem.dto.request.ProblemSubmitRequest -import com.solve.domain.problem.dto.response.ProblemSubmitResponse - -interface ProblemSubmitService { - fun submitProblem(problemId: Long, request: ProblemSubmitRequest): ProblemSubmitResponse -} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/util/CodeExecutor.kt b/src/main/kotlin/com/solve/domain/problem/util/CodeExecutor.kt index 7ee02f0..209c00d 100644 --- a/src/main/kotlin/com/solve/domain/problem/util/CodeExecutor.kt +++ b/src/main/kotlin/com/solve/domain/problem/util/CodeExecutor.kt @@ -1,10 +1,10 @@ package com.solve.domain.problem.util -import com.solve.domain.problem.domain.entity.ProblemSubmit -import com.solve.domain.problem.domain.enums.ProblemSubmitState -import com.solve.domain.problem.dto.request.ProblemSubmitRequest import com.solve.domain.problem.error.ProblemError import com.solve.domain.problem.util.config.LanguageConfig +import com.solve.domain.submit.domain.entity.Submit +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.dto.request.SubmitRequest import com.solve.global.config.file.FileProperties import com.solve.global.error.CustomException import java.io.File @@ -12,15 +12,15 @@ import java.util.concurrent.TimeUnit import kotlin.concurrent.thread class CodeExecutor( - private val submit: ProblemSubmit, - private val request: ProblemSubmitRequest, + private val submit: Submit, + private val request: SubmitRequest, private val fileProperties: FileProperties ) { data class ExecutionResult( val output: String, val error: String, val success: Boolean, - val state: ProblemSubmitState? = null, + val state: SubmitState? = null, val timeUsage: Long = 0, val compilationOutput: String? = null, val memoryUsage: Long = 0, @@ -80,7 +80,7 @@ class CodeExecutor( output = "", error = "Time Limit Exceeded", success = false, - state = ProblemSubmitState.TIME_LIMIT_EXCEEDED + state = SubmitState.TIME_LIMIT_EXCEEDED ) } @@ -94,7 +94,7 @@ class CodeExecutor( output = "", error = errorOutput, success = false, - state = ProblemSubmitState.RUNTIME_ERROR + state = SubmitState.RUNTIME_ERROR ) } @@ -121,7 +121,7 @@ class CodeExecutor( output = actualOutput, error = "", success = false, - state = ProblemSubmitState.PRESENTATION_ERROR, + state = SubmitState.PRESENTATION_ERROR, timeUsage = timeUsage, memoryUsage = memoryUsage, ) @@ -132,7 +132,7 @@ class CodeExecutor( output = actualOutput, error = "", success = false, - state = ProblemSubmitState.WRONG_ANSWER, + state = SubmitState.WRONG_ANSWER, timeUsage = timeUsage, memoryUsage = memoryUsage, ) @@ -142,7 +142,7 @@ class CodeExecutor( output = actualOutput, error = "", success = true, - state = ProblemSubmitState.ACCEPTED, + state = SubmitState.ACCEPTED, timeUsage = timeUsage, memoryUsage = memoryUsage, ) @@ -167,7 +167,7 @@ class CodeExecutor( output = "", error = output, success = false, - state = ProblemSubmitState.COMPILE_ERROR, + state = SubmitState.COMPILE_ERROR, compilationOutput = output ) } else null diff --git a/src/main/kotlin/com/solve/domain/submit/controller/SubmitController.kt b/src/main/kotlin/com/solve/domain/submit/controller/SubmitController.kt new file mode 100644 index 0000000..09cbf6d --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/controller/SubmitController.kt @@ -0,0 +1,41 @@ +package com.solve.domain.submit.controller + +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.dto.request.SubmitRequest +import com.solve.domain.submit.service.SubmitService +import com.solve.global.common.dto.BaseResponse +import com.solve.global.common.enums.ProgrammingLanguage +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.* + +@Tag(name = "문제 제출", description = "Problem Submit") +@RestController +@RequestMapping("/submits") +class SubmitController( + private val submitService: SubmitService +) { + @Operation(summary = "문제 제출") + @PostMapping + fun submitProblem(@RequestParam problemId: Long, @RequestBody request: SubmitRequest) = + BaseResponse.of(submitService.submitProblem(problemId, request)) + + @Operation(summary = "제출 검색") + @GetMapping("/search") + fun searchSubmit( + @RequestParam(required = false) problemId: Long?, + @RequestParam(required = false) username: String?, + @RequestParam(required = false) state: SubmitState?, + @RequestParam(required = false) language: ProgrammingLanguage?, + @RequestParam(required = false) cursorId: Long?, + @RequestParam(required = false, defaultValue = "10") size: Int + ) = BaseResponse.of(submitService.searchSubmit(problemId, username, state, language, cursorId, size)) + + @Operation(summary = "내 제출 조회") + @GetMapping("/my") + fun getMySubmits( + @RequestParam problemId: Long, + @RequestParam(required = false) cursorId: Long, + @RequestParam(required = false, defaultValue = "10") size: Int + ) = BaseResponse.of(submitService.getMySubmits(problemId, cursorId, size)) +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/domain/entity/ProblemSubmit.kt b/src/main/kotlin/com/solve/domain/submit/domain/entity/Submit.kt similarity index 67% rename from src/main/kotlin/com/solve/domain/problem/domain/entity/ProblemSubmit.kt rename to src/main/kotlin/com/solve/domain/submit/domain/entity/Submit.kt index 931083e..ef39982 100644 --- a/src/main/kotlin/com/solve/domain/problem/domain/entity/ProblemSubmit.kt +++ b/src/main/kotlin/com/solve/domain/submit/domain/entity/Submit.kt @@ -1,7 +1,8 @@ -package com.solve.domain.problem.domain.entity +package com.solve.domain.submit.domain.entity -import com.solve.domain.problem.domain.enums.ProblemSubmitState -import com.solve.domain.problem.domain.enums.ProblemSubmitVisibility +import com.solve.domain.problem.domain.entity.Problem +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.domain.enums.SubmitVisibility import com.solve.domain.user.domain.entity.User import com.solve.global.common.entity.BaseTimeEntity import com.solve.global.common.enums.ProgrammingLanguage @@ -9,22 +10,22 @@ import jakarta.persistence.* @Entity @Table( - name = "problem_submits", + name = "submits", indexes = [ - Index(name = "idx_problem_submit_problem", columnList = "problem_id"), - Index(name = "idx_problem_submit_author", columnList = "author_id"), - Index(name = "idx_problem_submit_state", columnList = "state"), - Index(name = "idx_problem_submit_language", columnList = "language") + Index(name = "idx_submit_problem", columnList = "problem_id"), + Index(name = "idx_submit_author", columnList = "author_id"), + Index(name = "idx_submit_state", columnList = "state"), + Index(name = "idx_submit_language", columnList = "language") ] ) -class ProblemSubmit( +class Submit( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, @Enumerated(EnumType.STRING) @Column(name = "state", nullable = false) - var state: ProblemSubmitState, + var state: SubmitState, @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "problem_id", nullable = false) @@ -49,11 +50,11 @@ class ProblemSubmit( @Enumerated(EnumType.STRING) @Column(name = "visibility", nullable = false) - val visibility: ProblemSubmitVisibility, + val visibility: SubmitVisibility, ) : BaseTimeEntity() { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is ProblemSubmit) return false + if (other !is Submit) return false if (id == null || other.id == null) return false return id == other.id } diff --git a/src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitState.kt b/src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitState.kt similarity index 82% rename from src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitState.kt rename to src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitState.kt index 6a5a292..001d80e 100644 --- a/src/main/kotlin/com/solve/domain/problem/domain/enums/ProblemSubmitState.kt +++ b/src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitState.kt @@ -1,6 +1,6 @@ -package com.solve.domain.problem.domain.enums +package com.solve.domain.submit.domain.enums -enum class ProblemSubmitState { +enum class SubmitState { // 맞았습니다 ACCEPTED, @@ -18,6 +18,8 @@ enum class ProblemSubmitState { // 런타임 에러 RUNTIME_ERROR, + + // 컴파일 에러 COMPILE_ERROR, // 기다리는 중 diff --git a/src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitVisibility.kt b/src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitVisibility.kt new file mode 100644 index 0000000..4187bb8 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/domain/enums/SubmitVisibility.kt @@ -0,0 +1,7 @@ +package com.solve.domain.submit.domain.enums + +enum class SubmitVisibility { + PUBLIC, + PRIVATE, + PUBLIC_IF_ACCEPTED +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/dto/request/SubmitRequest.kt b/src/main/kotlin/com/solve/domain/submit/dto/request/SubmitRequest.kt new file mode 100644 index 0000000..a829ea5 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/dto/request/SubmitRequest.kt @@ -0,0 +1,10 @@ +package com.solve.domain.submit.dto.request + +import com.solve.domain.submit.domain.enums.SubmitVisibility +import com.solve.global.common.enums.ProgrammingLanguage + +data class SubmitRequest( + val code: String, + val language: ProgrammingLanguage, + val visibility: SubmitVisibility, +) \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitProgressResponse.kt b/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitProgressResponse.kt new file mode 100644 index 0000000..2571f83 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitProgressResponse.kt @@ -0,0 +1,12 @@ +package com.solve.domain.submit.dto.response + +import com.fasterxml.jackson.annotation.JsonInclude +import com.solve.domain.submit.domain.enums.SubmitState + +@JsonInclude(JsonInclude.Include.NON_NULL) +data class SubmitProgressResponse( + val submitId: Long, + val progress: Double, + val result: SubmitState, + val error: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitResponse.kt b/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitResponse.kt new file mode 100644 index 0000000..e77c5a1 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/dto/response/SubmitResponse.kt @@ -0,0 +1,16 @@ +package com.solve.domain.submit.dto.response + +import com.solve.domain.submit.domain.entity.Submit +import com.solve.domain.submit.domain.enums.SubmitState + +data class SubmitResponse( + val id: Long, + val result: SubmitState +) { + companion object { + fun of(submit: Submit) = SubmitResponse( + id = submit.id!!, + result = submit.state + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/error/SubmitError.kt b/src/main/kotlin/com/solve/domain/submit/error/SubmitError.kt new file mode 100644 index 0000000..cc5ddb4 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/error/SubmitError.kt @@ -0,0 +1,8 @@ +package com.solve.domain.submit.error + +import com.solve.global.error.CustomError +import org.springframework.http.HttpStatus + +enum class SubmitError(override val status: HttpStatus, override val message: String) : CustomError { + SUBMIT_NOT_FOUND(HttpStatus.NOT_FOUND, "해당 제출을 찾을 수 없습니다."), +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/repository/SubmitQueryRepository.kt b/src/main/kotlin/com/solve/domain/submit/repository/SubmitQueryRepository.kt new file mode 100644 index 0000000..d77251d --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/repository/SubmitQueryRepository.kt @@ -0,0 +1,65 @@ +package com.solve.domain.submit.repository + +import com.querydsl.jpa.impl.JPAQueryFactory +import com.solve.domain.problem.domain.entity.Problem +import com.solve.domain.submit.domain.entity.QSubmit +import com.solve.domain.submit.domain.entity.Submit +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.user.domain.entity.User +import com.solve.global.common.enums.ProgrammingLanguage +import com.solve.global.security.holder.SecurityHolder +import org.springframework.stereotype.Repository +import org.springframework.transaction.annotation.Transactional + +@Repository +class SubmitQueryRepository( + private val securityHolder: SecurityHolder, + private val queryFactory: JPAQueryFactory +) { + private val submit = QSubmit.submit + + @Transactional(readOnly = true) + fun getMySubmits(problem: Problem?, cursor: Submit?, size: Int): List { + val me = securityHolder.user + + return queryFactory + .selectFrom(submit) + .where( + problemEq(problem), + authorEq(me), + cursorLt(cursor) + ) + .orderBy(submit._createdAt.desc(), submit.id.desc()) + .limit(size.toLong()) + .fetch() ?: emptyList() + } + + @Transactional(readOnly = true) + fun searchSubmit( + problem: Problem?, + author: User?, + state: SubmitState?, + language: ProgrammingLanguage?, + cursor: Submit?, + size: Int + ): List { + return queryFactory + .selectFrom(submit) + .where( + problemEq(problem), + authorEq(author), + stateEq(state), + languageEq(language), + cursorLt(cursor) + ) + .orderBy(submit._createdAt.desc(), submit.id.desc()) + .limit(size.toLong()) + .fetch() ?: emptyList() + } + + private fun problemEq(problem: Problem?) = problem?.let { submit.problem.eq(it) } + private fun authorEq(user: User?) = user?.let { submit.author.eq(it) } + private fun stateEq(state: SubmitState?) = state?.let { submit.state.eq(it) } + private fun languageEq(language: ProgrammingLanguage?) = language?.let { submit.language.eq(it) } + private fun cursorLt(cursor: Submit?) = cursor?.id?.let { submit.id.lt(it) } +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemSubmitQueueRepositoryImpl.kt b/src/main/kotlin/com/solve/domain/submit/repository/SubmitQueueRepository.kt similarity index 60% rename from src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemSubmitQueueRepositoryImpl.kt rename to src/main/kotlin/com/solve/domain/submit/repository/SubmitQueueRepository.kt index 23f2703..e14cc0d 100644 --- a/src/main/kotlin/com/solve/domain/problem/repository/impl/ProblemSubmitQueueRepositoryImpl.kt +++ b/src/main/kotlin/com/solve/domain/submit/repository/SubmitQueueRepository.kt @@ -1,22 +1,21 @@ -package com.solve.domain.problem.repository.impl +package com.solve.domain.submit.repository -import com.solve.domain.problem.repository.ProblemSubmitQueueRepository import org.springframework.data.redis.core.RedisTemplate import org.springframework.stereotype.Repository @Repository -class ProblemSubmitQueueRepositoryImpl( +class SubmitQueueRepository( private val redisTemplate: RedisTemplate -) : ProblemSubmitQueueRepository { - override fun push(submitId: Long) { +) { + fun push(submitId: Long) { redisTemplate.opsForList().leftPush("problemSubmitQueue", submitId.toString()) } - override fun pop(): Long? { + fun pop(): Long? { return redisTemplate.opsForList().rightPop("problemSubmitQueue")?.toLong() } - override fun size(): Int { + fun size(): Int { return redisTemplate.opsForList().size("problemSubmitQueue")?.toInt() ?: 0 } } \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/submit/repository/SubmitRepository.kt b/src/main/kotlin/com/solve/domain/submit/repository/SubmitRepository.kt new file mode 100644 index 0000000..cc20492 --- /dev/null +++ b/src/main/kotlin/com/solve/domain/submit/repository/SubmitRepository.kt @@ -0,0 +1,11 @@ +package com.solve.domain.submit.repository + +import com.solve.domain.problem.domain.entity.Problem +import com.solve.domain.submit.domain.entity.Submit +import com.solve.domain.user.domain.entity.User +import org.springframework.data.jpa.repository.JpaRepository + +interface SubmitRepository : JpaRepository { + fun findAllByProblem(problem: Problem): List + fun findAllByProblemAndAuthor(problem: Problem, author: User): List +} \ No newline at end of file diff --git a/src/main/kotlin/com/solve/domain/problem/service/impl/ProblemSubmitServiceImpl.kt b/src/main/kotlin/com/solve/domain/submit/service/SubmitService.kt similarity index 54% rename from src/main/kotlin/com/solve/domain/problem/service/impl/ProblemSubmitServiceImpl.kt rename to src/main/kotlin/com/solve/domain/submit/service/SubmitService.kt index 9ac0155..d6646e9 100644 --- a/src/main/kotlin/com/solve/domain/problem/service/impl/ProblemSubmitServiceImpl.kt +++ b/src/main/kotlin/com/solve/domain/submit/service/SubmitService.kt @@ -1,23 +1,25 @@ -package com.solve.domain.problem.service.impl +package com.solve.domain.submit.service -import com.solve.domain.problem.domain.entity.ProblemSubmit -import com.solve.domain.problem.domain.enums.ProblemSubmitState -import com.solve.domain.problem.dto.request.ProblemSubmitRequest -import com.solve.domain.problem.dto.response.ProblemSubmitResponse import com.solve.domain.problem.error.ProblemError -import com.solve.domain.problem.error.ProblemSubmitError import com.solve.domain.problem.repository.ProblemRepository -import com.solve.domain.problem.repository.ProblemSubmitQueueRepository -import com.solve.domain.problem.repository.ProblemSubmitRepository import com.solve.domain.problem.repository.ProblemTestCaseRepository -import com.solve.domain.problem.service.ProblemSubmitService import com.solve.domain.problem.util.CodeExecutor +import com.solve.domain.submit.domain.entity.Submit +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.dto.request.SubmitRequest +import com.solve.domain.submit.dto.response.SubmitResponse +import com.solve.domain.submit.error.SubmitError +import com.solve.domain.submit.repository.SubmitQueryRepository +import com.solve.domain.submit.repository.SubmitQueueRepository +import com.solve.domain.submit.repository.SubmitRepository import com.solve.domain.user.domain.entity.UserSolved +import com.solve.domain.user.error.UserError import com.solve.domain.user.repository.UserRepository +import com.solve.global.common.enums.ProgrammingLanguage import com.solve.global.config.file.FileProperties -import com.solve.global.websocket.handler.ProgressWebSocketHandler import com.solve.global.error.CustomException import com.solve.global.security.holder.SecurityHolder +import com.solve.global.websocket.handler.ProgressWebSocketHandler import org.springframework.data.repository.findByIdOrNull import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Service @@ -25,48 +27,82 @@ import org.springframework.transaction.annotation.Transactional import java.time.LocalDate import java.util.concurrent.CompletableFuture - @Service -class ProblemSubmitServiceImpl( +class SubmitService( private val securityHolder: SecurityHolder, private val fileProperties: FileProperties, private val problemRepository: ProblemRepository, - private val problemSubmitRepository: ProblemSubmitRepository, - private val problemSubmitQueueRepository: ProblemSubmitQueueRepository, + private val submitRepository: SubmitRepository, private val userRepository: UserRepository, private val problemTestCaseRepository: ProblemTestCaseRepository, - private val progressWebSocketHandler: ProgressWebSocketHandler -) : ProblemSubmitService { + private val progressWebSocketHandler: ProgressWebSocketHandler, + private val submitQueueRepository: SubmitQueueRepository, + private val submitQueryRepository: SubmitQueryRepository +) { + @Transactional(readOnly = true) + fun getMySubmits(problemId: Long, cursorId: Long, size: Int): List { + val problem = problemRepository.findByIdOrNull(problemId) + ?: throw CustomException(ProblemError.PROBLEM_NOT_FOUND) + val cursor = submitRepository.findByIdOrNull(cursorId) + ?: throw CustomException(SubmitError.SUBMIT_NOT_FOUND) + + val submits = submitQueryRepository.getMySubmits(problem, cursor, size) + + return submits.map { SubmitResponse.of(it) } + } + + @Transactional(readOnly = true) + fun searchSubmit( + problemId: Long?, + username: String?, + state: SubmitState?, + language: ProgrammingLanguage?, + cursorId: Long?, + size: Int + ): List { + val problem = problemId?.let { + problemRepository.findByIdOrNull(it) ?: throw CustomException(ProblemError.PROBLEM_NOT_FOUND) + } + val user = username?.let { + userRepository.findByUsername(it) ?: throw CustomException(UserError.USER_NOT_FOUND_BY_USERNAME, it) + } + val cursor = + cursorId?.let { submitRepository.findByIdOrNull(it) ?: throw CustomException(SubmitError.SUBMIT_NOT_FOUND) } + val submits = submitQueryRepository.searchSubmit(problem, user, state, language, cursor, size) + + return submits.map { SubmitResponse.of(it) } + } + @Transactional - override fun submitProblem(problemId: Long, request: ProblemSubmitRequest): ProblemSubmitResponse { + fun submitProblem(problemId: Long, request: SubmitRequest): SubmitResponse { val author = securityHolder.user val problem = problemRepository.findByIdOrNull(problemId) ?: throw CustomException(ProblemError.PROBLEM_NOT_FOUND) - val submit = ProblemSubmit( + val submit = Submit( code = request.code, author = author, problem = problem, language = request.language, visibility = request.visibility, - state = ProblemSubmitState.PENDING + state = SubmitState.PENDING ) - problemSubmitRepository.save(submit) + submitRepository.save(submit) // problemSubmitQueueRepository.push(submit.id!!) - return ProblemSubmitResponse.of(submit) + return SubmitResponse.of(submit) } @Scheduled(fixedRate = 1000) @Transactional fun processQueue() { - if (problemSubmitQueueRepository.size() == 0) return + if (submitQueueRepository.size() == 0) return - val submitId = problemSubmitQueueRepository.pop() ?: return - val submit = problemSubmitRepository.findByIdOrNull(submitId) - ?: throw CustomException(ProblemSubmitError.PROBLEM_SUBMIT_NOT_FOUND) + val submitId = submitQueueRepository.pop() ?: return + val submit = submitRepository.findByIdOrNull(submitId) + ?: throw CustomException(SubmitError.SUBMIT_NOT_FOUND) - val request = ProblemSubmitRequest( + val request = SubmitRequest( code = submit.code, language = submit.language, visibility = submit.visibility @@ -78,7 +114,7 @@ class ProblemSubmitServiceImpl( } // @Transactional - fun processSubmit(submit: ProblemSubmit, request: ProblemSubmitRequest) { + fun processSubmit(submit: Submit, request: SubmitRequest) { val executor = CodeExecutor(submit, request, fileProperties) val problem = submit.problem val testCases = problemTestCaseRepository.findAllByProblem(problem) @@ -87,8 +123,8 @@ class ProblemSubmitServiceImpl( var maxTimeUsage = 0L // Long으로 변경 var maxMemoryUsage = 0L - submit.state = ProblemSubmitState.JUDGING - updateProgress(submit.id!!, progress, ProblemSubmitState.JUDGING) + submit.state = SubmitState.JUDGING + updateProgress(submit.id!!, progress, SubmitState.JUDGING) // executor.initializeJavaContainer() for (testCase in testCases) { @@ -100,32 +136,32 @@ class ProblemSubmitServiceImpl( submit.state = result.state!! submit.timeUsage = maxTimeUsage // timeUsage 필드 사용 submit.memoryUsage = maxMemoryUsage - if (result.state == ProblemSubmitState.COMPILE_ERROR) { + if (result.state == SubmitState.COMPILE_ERROR) { // submit.compileError = result.compilationOutput } - problemSubmitRepository.save(submit) + submitRepository.save(submit) updateProgress(submit.id, progress, result.state) return } progress += 100.0 / totalTestCases - updateProgress(submit.id, progress, ProblemSubmitState.JUDGING_IN_PROGRESS) + updateProgress(submit.id, progress, SubmitState.JUDGING_IN_PROGRESS) } - submit.state = ProblemSubmitState.ACCEPTED + submit.state = SubmitState.ACCEPTED submit.timeUsage = maxTimeUsage // timeUsage 필드 사용 submit.memoryUsage = maxMemoryUsage - problemSubmitRepository.save(submit) - updateProgress(submit.id, 100.0, ProblemSubmitState.ACCEPTED) + submitRepository.save(submit) + updateProgress(submit.id, 100.0, SubmitState.ACCEPTED) handleAcceptedSubmission(submit) } - private fun updateProgress(submitId: Long, progress: Double, state: ProblemSubmitState) { + private fun updateProgress(submitId: Long, progress: Double, state: SubmitState) { progressWebSocketHandler.sendProgressUpdate(submitId, progress, state) } - private fun handleAcceptedSubmission(submit: ProblemSubmit) { + private fun handleAcceptedSubmission(submit: Submit) { try { val user = submit.author val problemNotSolvedYet = user.solved.none { it.problem == submit.problem } diff --git a/src/main/kotlin/com/solve/global/websocket/handler/ProgressWebSocketHandler.kt b/src/main/kotlin/com/solve/global/websocket/handler/ProgressWebSocketHandler.kt index 45a530e..7c572ee 100644 --- a/src/main/kotlin/com/solve/global/websocket/handler/ProgressWebSocketHandler.kt +++ b/src/main/kotlin/com/solve/global/websocket/handler/ProgressWebSocketHandler.kt @@ -1,16 +1,16 @@ package com.solve.global.websocket.handler import com.fasterxml.jackson.databind.ObjectMapper -import com.solve.domain.problem.domain.enums.ProblemSubmitState -import com.solve.domain.problem.dto.response.ProblemSubmitProgressResponse -import com.solve.domain.problem.repository.ProblemSubmitQueueRepository +import com.solve.domain.submit.domain.enums.SubmitState +import com.solve.domain.submit.dto.response.SubmitProgressResponse +import com.solve.domain.submit.repository.SubmitQueueRepository import org.springframework.stereotype.Component import org.springframework.web.socket.* import java.util.concurrent.ConcurrentHashMap @Component class ProgressWebSocketHandler( - private val problemSubmitQueueRepository: ProblemSubmitQueueRepository + private val submitQueueRepository: SubmitQueueRepository ) : WebSocketHandler { private val sessions = ConcurrentHashMap() @@ -18,7 +18,7 @@ class ProgressWebSocketHandler( val submitId = session.uri?.path?.substringAfterLast("/")?.toLongOrNull() if (submitId != null) { sessions[submitId] = session - problemSubmitQueueRepository.push(submitId) + submitQueueRepository.push(submitId) } } @@ -37,9 +37,9 @@ class ProgressWebSocketHandler( override fun supportsPartialMessages(): Boolean = false - fun sendProgressUpdate(submitId: Long, progress: Double, state: ProblemSubmitState) { + fun sendProgressUpdate(submitId: Long, progress: Double, state: SubmitState) { val session = sessions[submitId] ?: return - val progressResponse = ProblemSubmitProgressResponse( + val progressResponse = SubmitProgressResponse( submitId = submitId, progress = progress, result = state