diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 334f3c06..c1c5988c 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -10,6 +10,7 @@
+
@@ -21,9 +22,12 @@
+
+
+
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index ae3f30ae..700886be 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,16 @@
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/application-admin/build.gradle.kts b/application-admin/build.gradle.kts
index 9ff8dbc6..f0bf675f 100644
--- a/application-admin/build.gradle.kts
+++ b/application-admin/build.gradle.kts
@@ -17,8 +17,10 @@ dependencies {
runtimeOnly(project(":infrastructure:store-redis"))
runtimeOnly(project(":infrastructure:order-postgres"))
runtimeOnly(project(":infrastructure:order-redis"))
+ runtimeOnly(project(":infrastructure:order-mongo"))
runtimeOnly(project(":infrastructure:payment-postgres"))
runtimeOnly(project(":infrastructure:review-postgres"))
+ runtimeOnly(project(":infrastructure:order-mongo"))
implementation(project(":common"))
implementation("io.github.oshai:kotlin-logging-jvm:7.0.3")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2")
@@ -29,4 +31,5 @@ dependencies {
implementation("com.auth0:java-jwt:4.2.1")
implementation("org.springframework.retry:spring-retry")
testImplementation("io.mockk:mockk:1.13.3")
+ testImplementation("org.mockito.kotlin:mockito-kotlin:5.4.0")
}
diff --git a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/ApplicationAdminApplication.kt b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/ApplicationAdminApplication.kt
index efa65616..f175b457 100644
--- a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/ApplicationAdminApplication.kt
+++ b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/ApplicationAdminApplication.kt
@@ -2,6 +2,7 @@ package org.fastcampus.applicationadmin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
+import org.springframework.scheduling.annotation.EnableScheduling
@SpringBootApplication(
scanBasePackages = [
@@ -13,6 +14,7 @@ import org.springframework.boot.runApplication
"org.fastcampus.review",
],
)
+@EnableScheduling
class ApplicationAdminApplication
fun main(args: Array) {
diff --git a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/config/AsyncConfig.kt b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/config/AsyncConfig.kt
new file mode 100644
index 00000000..fb34f81f
--- /dev/null
+++ b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/config/AsyncConfig.kt
@@ -0,0 +1,25 @@
+package org.fastcampus.applicationadmin.config
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.scheduling.annotation.AsyncConfigurer
+import org.springframework.scheduling.annotation.EnableAsync
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
+import java.util.concurrent.Executor
+
+@EnableAsync
+@Configuration
+class AsyncConfig : AsyncConfigurer {
+ @Bean
+ override fun getAsyncExecutor(): Executor? {
+ return ThreadPoolTaskExecutor().apply {
+ val cpuCoreCount = Runtime.getRuntime().availableProcessors()
+ corePoolSize = cpuCoreCount * 2
+ maxPoolSize = cpuCoreCount * 4
+ queueCapacity = 100
+ keepAliveSeconds = 60
+ setThreadNamePrefix("AsyncExecutor-")
+ initialize()
+ }
+ }
+}
diff --git a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/OrderService.kt b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/OrderService.kt
index 7bc58e6c..f4bdea94 100644
--- a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/OrderService.kt
+++ b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/OrderService.kt
@@ -4,6 +4,7 @@ import org.fastcampus.applicationadmin.order.controller.dto.OrderInquiryResponse
import org.fastcampus.applicationadmin.order.controller.dto.OrderMenuInquiryResponse
import org.fastcampus.applicationadmin.order.controller.dto.OrderMenuOptionGroupInquiryResponse
import org.fastcampus.applicationadmin.order.controller.dto.OrderMenuOptionInquiryResponse
+import org.fastcampus.applicationadmin.order.service.event.OrderDetailStatusEvent
import org.fastcampus.common.dto.OffSetBasedDTO
import org.fastcampus.member.entity.Member
import org.fastcampus.member.repository.MemberRepository
@@ -11,12 +12,14 @@ import org.fastcampus.order.entity.Order
import org.fastcampus.order.entity.OrderMenu
import org.fastcampus.order.entity.OrderMenuOptionGroup
import org.fastcampus.order.exception.OrderException
+import org.fastcampus.order.repository.OrderLockManager
import org.fastcampus.order.repository.OrderMenuOptionGroupRepository
import org.fastcampus.order.repository.OrderMenuOptionRepository
import org.fastcampus.order.repository.OrderMenuRepository
import org.fastcampus.order.repository.OrderRepository
import org.fastcampus.store.repository.StoreRepository
import org.slf4j.LoggerFactory
+import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
@@ -29,6 +32,8 @@ class OrderService(
private val orderMenuOptionRepository: OrderMenuOptionRepository,
private val storeRepository: StoreRepository,
private val memberRepository: MemberRepository,
+ private val eventPublisher: ApplicationEventPublisher,
+ private val orderLockManager: OrderLockManager,
) {
companion object {
private val logger = LoggerFactory.getLogger(OrderService::class.java)
@@ -77,8 +82,12 @@ class OrderService(
if (ownerId.toString() != store.ownerId) {
throw OrderException.OrderCanNotAccept(orderId)
}
- order.accept()
+ orderLockManager.lock(orderId) {
+ order.accept()
+ }
orderRepository.save(order)
+
+ eventPublisher.publishEvent(OrderDetailStatusEvent(orderId, order.status))
}
fun refuseOrder(orderId: String, ownerId: Long) {
@@ -88,8 +97,12 @@ class OrderService(
if (ownerId.toString() != store.ownerId) {
throw OrderException.OrderCanNotRefuse(orderId)
}
- order.refuse()
+ orderLockManager.lock(orderId) {
+ order.refuse()
+ }
orderRepository.save(order)
+
+ eventPublisher.publishEvent(OrderDetailStatusEvent(orderId, order.status))
}
fun completeOrder(orderId: String, ownerId: Long) {
@@ -101,6 +114,8 @@ class OrderService(
}
order.complete()
orderRepository.save(order)
+
+ eventPublisher.publishEvent(OrderDetailStatusEvent(orderId, order.status))
}
private fun convertIntoOrderInquiryResponse(order: Order): OrderInquiryResponse {
diff --git a/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/event/OrderCancellationReceiver.kt b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/event/OrderCancellationReceiver.kt
new file mode 100644
index 00000000..2adde9b9
--- /dev/null
+++ b/application-admin/src/main/kotlin/org/fastcampus/applicationadmin/order/service/event/OrderCancellationReceiver.kt
@@ -0,0 +1,33 @@
+package org.fastcampus.applicationadmin.order.service.event
+
+import com.fasterxml.jackson.core.type.TypeReference
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.fastcampus.applicationadmin.sse.SseManager
+import org.fastcampus.order.event.NotificationReceiver
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.springframework.stereotype.Component
+
+@Component("OrderCancellationReceiver")
+class OrderCancellationReceiver(
+ private val sseManager: SseManager,
+ private val objectMapper: ObjectMapper,
+) : NotificationReceiver {
+ override fun handleMessage(message: String) {
+ logger.debug("Received message {}", message)
+
+ val readValue = objectMapper.readValue(message, object : TypeReference