diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/event/listener/ApplicationEventListener.kt b/src/main/kotlin/com/dcd/server/core/domain/application/event/listener/ApplicationEventListener.kt index 6df9cf58..7887428c 100644 --- a/src/main/kotlin/com/dcd/server/core/domain/application/event/listener/ApplicationEventListener.kt +++ b/src/main/kotlin/com/dcd/server/core/domain/application/event/listener/ApplicationEventListener.kt @@ -5,13 +5,9 @@ import com.dcd.server.core.domain.application.event.ChangeApplicationStatusEvent import com.dcd.server.core.domain.application.event.DeployApplicationEvent import com.dcd.server.core.domain.application.model.DeploymentResult import com.dcd.server.core.domain.application.model.enums.ApplicationStatus -import com.dcd.server.core.domain.application.model.enums.ApplicationType -import com.dcd.server.core.domain.application.service.DeleteApplicationDirectoryService -import com.dcd.server.core.domain.application.spi.ApplicationRemoteRepoPort -import com.dcd.server.core.domain.application.spi.ApplicationImageFilePort +import com.dcd.server.core.domain.application.service.RefreshApplicationService import com.dcd.server.core.domain.application.spi.CommandApplicationPort import com.dcd.server.core.domain.application.spi.QueryApplicationPort -import com.dcd.server.core.domain.volume.spi.QueryVolumePort import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -23,13 +19,10 @@ import org.springframework.transaction.event.TransactionalEventListener @Component class ApplicationEventListener( + private val refreshApplicationService: RefreshApplicationService, private val commandApplicationPort: CommandApplicationPort, - private val applicationRemoteRepoPort: ApplicationRemoteRepoPort, - private val applicationImageFilePort: ApplicationImageFilePort, - private val deleteApplicationDirectoryService: DeleteApplicationDirectoryService, private val containerPort: ContainerPort, - private val queryApplicationPort: QueryApplicationPort, - private val queryVolumePort: QueryVolumePort + private val queryApplicationPort: QueryApplicationPort ) { @EventListener @Transactional(rollbackFor = [Exception::class]) @@ -53,20 +46,7 @@ class ApplicationEventListener( } CoroutineScope(Dispatchers.IO).launch { - val applicationType = application.applicationType - when(applicationType) { - ApplicationType.SPRING_BOOT, ApplicationType.NEST_JS, ApplicationType.GIN -> { - applicationRemoteRepoPort.cloneApplicationRemoteRepo(application) - } - else -> {} - } - applicationImageFilePort.createImageFile(application) - - containerPort.execute { - buildImage(application) - val volumeMounts = queryVolumePort.findAllMountByApplication(application) - createContainer(application, volumeMounts) - } + refreshApplicationService.refresh(application) val updatedApplication = application.copy(status = ApplicationStatus.STOPPED) commandApplicationPort.save(updatedApplication) diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/service/RefreshApplicationService.kt b/src/main/kotlin/com/dcd/server/core/domain/application/service/RefreshApplicationService.kt new file mode 100644 index 00000000..b63d32b4 --- /dev/null +++ b/src/main/kotlin/com/dcd/server/core/domain/application/service/RefreshApplicationService.kt @@ -0,0 +1,7 @@ +package com.dcd.server.core.domain.application.service + +import com.dcd.server.core.domain.application.model.Application + +interface RefreshApplicationService { + suspend fun refresh(application: Application) +} \ No newline at end of file diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/service/impl/RefreshApplicationServiceImpl.kt b/src/main/kotlin/com/dcd/server/core/domain/application/service/impl/RefreshApplicationServiceImpl.kt new file mode 100644 index 00000000..e5d99960 --- /dev/null +++ b/src/main/kotlin/com/dcd/server/core/domain/application/service/impl/RefreshApplicationServiceImpl.kt @@ -0,0 +1,42 @@ +package com.dcd.server.core.domain.application.service.impl + +import com.dcd.server.core.common.annotation.Lock +import com.dcd.server.core.common.spi.ContainerPort +import com.dcd.server.core.domain.application.model.Application +import com.dcd.server.core.domain.application.model.enums.ApplicationType +import com.dcd.server.core.domain.application.spi.ApplicationImageFilePort +import com.dcd.server.core.domain.application.spi.ApplicationRemoteRepoPort +import com.dcd.server.core.domain.application.service.DeleteApplicationDirectoryService +import com.dcd.server.core.domain.application.service.RefreshApplicationService +import com.dcd.server.core.domain.volume.spi.QueryVolumePort +import org.springframework.stereotype.Service + +@Service +class RefreshApplicationServiceImpl( + private val containerPort: ContainerPort, + private val applicationRemoteRepoPort: ApplicationRemoteRepoPort, + private val applicationImageFilePort: ApplicationImageFilePort, + private val deleteApplicationDirectoryService: DeleteApplicationDirectoryService, + private val queryVolumePort: QueryVolumePort +) : RefreshApplicationService { + @Lock("#application.id", waitTime = 1000 * 10, leaseTime = 1000 * 60 * 3) + override suspend fun refresh(application: Application) { + val applicationType = application.applicationType + when(applicationType) { + ApplicationType.SPRING_BOOT, ApplicationType.NEST_JS, ApplicationType.GIN -> { + applicationRemoteRepoPort.cloneApplicationRemoteRepo(application) + } + else -> {} + } + + applicationImageFilePort.createImageFile(application) + + containerPort.execute { + buildImage(application) + val volumeMounts = queryVolumePort.findAllMountByApplication(application) + createContainer(application, volumeMounts) + } + + deleteApplicationDirectoryService.deleteApplicationDirectory(application) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/CreateApplicationUseCase.kt b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/CreateApplicationUseCase.kt index 3641b74f..08d9edc8 100644 --- a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/CreateApplicationUseCase.kt +++ b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/CreateApplicationUseCase.kt @@ -8,15 +8,12 @@ import com.dcd.server.core.domain.application.dto.request.CreateApplicationReqDt import com.dcd.server.core.domain.application.dto.response.CreateApplicationResDto import com.dcd.server.core.domain.application.exception.AlreadyExistsApplicationException import com.dcd.server.core.domain.application.model.enums.ApplicationType -import com.dcd.server.core.domain.application.service.DeleteApplicationDirectoryService import com.dcd.server.core.domain.application.service.GetExternalPortService +import com.dcd.server.core.domain.application.service.RefreshApplicationService import com.dcd.server.core.domain.application.service.InitialScriptService -import com.dcd.server.core.domain.application.spi.ApplicationRemoteRepoPort -import com.dcd.server.core.domain.application.spi.ApplicationImageFilePort import com.dcd.server.core.domain.application.spi.CommandApplicationPort import com.dcd.server.core.domain.application.spi.QueryApplicationPort import com.dcd.server.core.domain.env.service.EnvAutoMatchService -import com.dcd.server.core.domain.volume.spi.QueryVolumePort import com.dcd.server.core.domain.workspace.exception.WorkspaceNotFoundException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -27,12 +24,8 @@ class CreateApplicationUseCase( private val commandApplicationPort: CommandApplicationPort, private val queryApplicationPort: QueryApplicationPort, private val workspaceInfo: WorkspaceInfo, - private val containerPort: ContainerPort, - private val queryVolumePort: QueryVolumePort, - private val applicationRemoteRepoPort: ApplicationRemoteRepoPort, - private val applicationImageFilePort: ApplicationImageFilePort, private val getExternalPortService: GetExternalPortService, - private val deleteApplicationDirectoryService: DeleteApplicationDirectoryService, + private val refreshApplicationService: RefreshApplicationService, private val envAutoMatchService: EnvAutoMatchService, private val initialScriptService: InitialScriptService ) : CoroutineScope by CoroutineScope(Dispatchers.IO) { @@ -52,23 +45,7 @@ class CreateApplicationUseCase( initialScriptService.write(application, createApplicationReqDto.initialScripts) launch { - val applicationType = application.applicationType - when(applicationType) { - ApplicationType.SPRING_BOOT, ApplicationType.NEST_JS, ApplicationType.GIN -> { - applicationRemoteRepoPort.cloneApplicationRemoteRepo(application) - } - else -> {} - } - - applicationImageFilePort.createImageFile(application) - - containerPort.execute { - buildImage(application) - val volumeMounts = queryVolumePort.findAllMountByApplication(application) - createContainer(application, volumeMounts) - } - - deleteApplicationDirectoryService.deleteApplicationDirectory(application) + refreshApplicationService.refresh(application) } return CreateApplicationResDto(application.id) diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/DeployApplicationUseCase.kt b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/DeployApplicationUseCase.kt index c62953da..0259068c 100644 --- a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/DeployApplicationUseCase.kt +++ b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/DeployApplicationUseCase.kt @@ -10,11 +10,8 @@ import com.dcd.server.core.domain.application.exception.CanNotDeployApplicationE import com.dcd.server.core.domain.application.model.Application import com.dcd.server.core.domain.application.model.enums.ApplicationStatus import com.dcd.server.core.domain.application.model.enums.ApplicationType -import com.dcd.server.core.domain.application.service.DeleteApplicationDirectoryService -import com.dcd.server.core.domain.application.spi.ApplicationRemoteRepoPort -import com.dcd.server.core.domain.application.spi.ApplicationImageFilePort +import com.dcd.server.core.domain.application.service.RefreshApplicationService import com.dcd.server.core.domain.application.spi.QueryApplicationPort -import com.dcd.server.core.domain.volume.spi.QueryVolumePort import com.dcd.server.core.domain.workspace.exception.WorkspaceNotFoundException import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel @@ -24,10 +21,7 @@ import org.springframework.context.ApplicationEventPublisher class DeployApplicationUseCase( private val queryApplicationPort: QueryApplicationPort, private val containerPort: ContainerPort, - private val queryVolumePort: QueryVolumePort, - private val applicationRemoteRepoPort: ApplicationRemoteRepoPort, - private val applicationImageFilePort: ApplicationImageFilePort, - private val deleteApplicationDirectoryService: DeleteApplicationDirectoryService, + private val refreshApplicationService: RefreshApplicationService, private val lockPort: LockPort, private val eventPublisher: ApplicationEventPublisher, private val workspaceInfo: WorkspaceInfo @@ -83,28 +77,14 @@ class DeployApplicationUseCase( } private suspend fun deployApplication(application: Application) { - containerPort.execute { - deleteContainer(application) - deleteImage(application) - - runBlocking { - val applicationType = application.applicationType - when(applicationType) { - ApplicationType.SPRING_BOOT, ApplicationType.NEST_JS, ApplicationType.GIN -> { - applicationRemoteRepoPort.cloneApplicationRemoteRepo(application) - } - else -> {} - } - applicationImageFilePort.createImageFile(application) + runBlocking { + containerPort.execute { + deleteContainer(application) + deleteImage(application) } - buildImage(application) - val volumeMounts = queryVolumePort.findAllMountByApplication(application) - createContainer(application, volumeMounts) + refreshApplicationService.refresh(application) - runBlocking { - deleteApplicationDirectoryService.deleteApplicationDirectory(application) - } eventPublisher.publishEvent(ChangeApplicationStatusEvent(ApplicationStatus.STOPPED, application)) } } diff --git a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/UpdateApplicationUseCase.kt b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/UpdateApplicationUseCase.kt index 94c0832b..bc1ae6c4 100644 --- a/src/main/kotlin/com/dcd/server/core/domain/application/usecase/UpdateApplicationUseCase.kt +++ b/src/main/kotlin/com/dcd/server/core/domain/application/usecase/UpdateApplicationUseCase.kt @@ -8,14 +8,10 @@ import com.dcd.server.core.domain.application.event.ChangeApplicationStatusEvent import com.dcd.server.core.domain.application.exception.AlreadyRunningException import com.dcd.server.core.domain.application.exception.ApplicationNotFoundException import com.dcd.server.core.domain.application.model.enums.ApplicationStatus -import com.dcd.server.core.domain.application.model.enums.ApplicationType import com.dcd.server.core.domain.application.service.InitialScriptService -import com.dcd.server.core.domain.application.service.DeleteApplicationDirectoryService -import com.dcd.server.core.domain.application.spi.ApplicationImageFilePort -import com.dcd.server.core.domain.application.spi.ApplicationRemoteRepoPort +import com.dcd.server.core.domain.application.service.RefreshApplicationService import com.dcd.server.core.domain.application.spi.CommandApplicationPort import com.dcd.server.core.domain.application.spi.QueryApplicationPort -import com.dcd.server.core.domain.volume.spi.QueryVolumePort import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking @@ -26,10 +22,7 @@ import org.springframework.context.ApplicationEventPublisher class UpdateApplicationUseCase( private val queryApplicationPort: QueryApplicationPort, private val commandApplicationPort: CommandApplicationPort, - private val applicationRemoteRepoPort: ApplicationRemoteRepoPort, - private val applicationImageFilePort: ApplicationImageFilePort, - private val deleteApplicationDirectoryService: DeleteApplicationDirectoryService, - private val queryVolumePort: QueryVolumePort, + private val refreshApplicationService: RefreshApplicationService, private val containerPort: ContainerPort, private val eventPublisher: ApplicationEventPublisher, private val initialScriptService: InitialScriptService @@ -56,27 +49,9 @@ class UpdateApplicationUseCase( initialScriptService.write(updatedApplication, updateApplicationReqDto.initialScripts) if (application.name != updateApplicationReqDto.name) { + eventPublisher.publishEvent(ChangeApplicationStatusEvent(ApplicationStatus.PENDING, updatedApplication)) launch { - eventPublisher.publishEvent(ChangeApplicationStatusEvent(ApplicationStatus.PENDING, updatedApplication)) - - // 이름이 변경된 애플리케이션의 이미지및, 컨테이너 생성 - val applicationType = updatedApplication.applicationType - when(applicationType) { - ApplicationType.SPRING_BOOT, ApplicationType.NEST_JS, ApplicationType.GIN -> { - applicationRemoteRepoPort.cloneApplicationRemoteRepo(updatedApplication) - } - else -> {} - } - - applicationImageFilePort.createImageFile(updatedApplication) - - containerPort.execute { - buildImage(updatedApplication) - val volumeMounts = queryVolumePort.findAllMountByApplication(updatedApplication) - createContainer(updatedApplication, volumeMounts) - } - - deleteApplicationDirectoryService.deleteApplicationDirectory(updatedApplication) + refreshApplicationService.refresh(updatedApplication) // 이름이 변경되기 전 애플리케이션의 이미지및, 컨테이너 제거 containerPort.execute {