Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: 토큰, 사용자, 포인트 엔티티 식별자 변경 및 비즈니스 로직 리팩토링 #18

Merged
merged 5 commits into from
Jun 1, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import io.ticketaka.api.user.domain.Token

interface TokenWaitingMap {
fun put(
key: String,
key: Long,
token: Token,
): Boolean

fun putAll(tokens: List<Token>): Boolean

fun get(key: String): Token?
fun get(key: Long): Token?

fun remove(key: String): Token?
fun remove(key: Long): Token?

fun size(): Long

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import java.util.concurrent.ConcurrentHashMap

@Component
class InMemoryWaitingMap : TokenWaitingMap {
private val tokenCache: MutableMap<String, Token> = ConcurrentHashMap()
private val tokenCache: MutableMap<Long, Token> = ConcurrentHashMap()

override fun put(
key: String,
key: Long,
token: Token,
): Boolean {
tokenCache[key] = token
return true
}

override fun putAll(tokens: List<Token>): Boolean {
tokenCache.putAll(tokens.map { it.tsid to it })
tokenCache.putAll(tokens.map { it.id to it })
return true
}

override fun get(key: String): Token? {
override fun get(key: Long): Token? {
return tokenCache[key]
}

Expand All @@ -34,7 +34,7 @@ class InMemoryWaitingMap : TokenWaitingMap {
tokenCache.clear()
}

override fun remove(key: String): Token? {
override fun remove(key: Long): Token? {
return tokenCache.remove(key)
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ class RequestMapAspect(
val requestAttributes = RequestContextHolder.getRequestAttributes() as ServletRequestAttributes?
val authorizationHeader =
requestAttributes?.request?.getHeader(
"tokenTsid",
"tokenId",
) ?: throw IllegalArgumentException("요청 헤더에 토큰이 존재하지 않습니다.")
val tokenId = authorizationHeader.toLongOrNull() ?: throw IllegalArgumentException("토큰 아이디가 올바르지 않습니다.")

val tokenFromQueue = tokenWaitingMap.get(authorizationHeader) ?: throw IllegalArgumentException("대기 중인 토큰이 존재하지 않습니다.")
val tokenFromQueue = tokenWaitingMap.get(tokenId) ?: throw IllegalArgumentException("대기 중인 토큰이 존재하지 않습니다.")

validateTokenIdentifier(tokenFromQueue, authorizationHeader)
validateTokenIdentifier(tokenFromQueue, tokenId)

validateTokenActive(tokenFromQueue)

Expand All @@ -45,7 +46,7 @@ class RequestMapAspect(
return joinPoint.proceed()
} finally {
tokenFromQueue.deactivate()
tokenWaitingMap.put(authorizationHeader, tokenFromQueue)
tokenWaitingMap.put(tokenId, tokenFromQueue)
}
}

Expand All @@ -69,9 +70,9 @@ class RequestMapAspect(

private fun validateTokenIdentifier(
firstToken: Token,
authorizationHeader: String,
authorizationHeader: Long,
) {
if (firstToken.tsid != authorizationHeader) {
if (firstToken.id != authorizationHeader) {
val errorMessage = "현재 대기 중인 토큰과 요청한 토큰이 일치하지 않습니다."
logger.debug(errorMessage)
throw IllegalArgumentException(errorMessage)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@ import java.util.concurrent.TimeUnit
@Configuration
@EnableCaching
class CaffeineCacheConfig {
@Bean
fun pointCache(): Cache<Any, Any> {
return Caffeine.newBuilder()
.initialCapacity(10)
.recordStats()
.expireAfterWrite(5, TimeUnit.MINUTES)
.expireAfterAccess(5, TimeUnit.MINUTES)
.maximumSize(100)
.build()
}

@Bean
fun userCache(): Cache<Any, Any> {
return Caffeine.newBuilder()
.initialCapacity(100)
.initialCapacity(10)
.recordStats()
.expireAfterWrite(5, TimeUnit.MINUTES)
.expireAfterAccess(5, TimeUnit.MINUTES)
Expand Down Expand Up @@ -49,6 +60,7 @@ class CaffeineCacheConfig {
caffeineCacheManager.registerCustomCache("seatNumbers", seatNumberCache())
caffeineCacheManager.registerCustomCache("concert", concertCache())
caffeineCacheManager.registerCustomCache("user", userCache())
caffeineCacheManager.registerCustomCache("point", pointCache())
return caffeineCacheManager
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.springframework.transaction.annotation.Transactional
@Transactional(readOnly = true)
class PaymentService(
private val paymentRepository: PaymentRepository,
private val pointService: PointService,
private val pointQueryService: PointQueryService,
private val applicationEventPublisher: ApplicationEventPublisher,
) {
@Transactional
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.ticketaka.api.point.application

import io.ticketaka.api.point.domain.Point
import io.ticketaka.api.point.domain.PointRepository
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional(readOnly = true)
class PointQueryService(
private val pointRepository: PointRepository,
) {
@Cacheable(value = ["point"], key = "#pointId")
fun getPoint(pointId: Long): Point {
return pointRepository.findById(pointId) ?: throw IllegalArgumentException("포인트를 찾을 수 없습니다.")
}
}
40 changes: 25 additions & 15 deletions src/main/kotlin/io/ticketaka/api/point/application/PointService.kt
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
package io.ticketaka.api.point.application

import io.ticketaka.api.common.exception.NotFoundException
import io.ticketaka.api.point.domain.Point
import io.ticketaka.api.point.domain.PointRepository
import io.ticketaka.api.user.domain.User
import io.ticketaka.api.point.application.dto.BalanceQueryModel
import io.ticketaka.api.point.application.dto.RechargeCommand
import io.ticketaka.api.point.domain.PointBalanceUpdater
import io.ticketaka.api.point.domain.PointRechargeEvent
import io.ticketaka.api.user.application.TokenUserQueryService
import org.springframework.context.ApplicationEventPublisher
import org.springframework.retry.annotation.Backoff
import org.springframework.retry.annotation.Retryable
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.math.BigDecimal

@Service
@Transactional(readOnly = true)
class PointService(
private val pointRepository: PointRepository,
private val tokenUserQueryService: TokenUserQueryService,
private val pointQueryService: PointQueryService,
private val pointBalanceUpdater: PointBalanceUpdater,
private val applicationEventPublisher: ApplicationEventPublisher,
) {
fun rollbackPoint(
pointId: Long,
amount: BigDecimal,
) {
val point = pointRepository.findById(pointId) ?: throw IllegalArgumentException("포인트를 찾을 수 없습니다.")
point.rollback(amount)
@Async
@Retryable(retryFor = [Exception::class], backoff = Backoff(delay = 1000, multiplier = 2.0, maxDelay = 10000))
@Transactional
fun recharge(rechargeCommand: RechargeCommand) {
val user = tokenUserQueryService.getUser(rechargeCommand.userId)
val userPoint = pointQueryService.getPoint(user.pointId)
pointBalanceUpdater.recharge(userPoint, rechargeCommand.amount)
applicationEventPublisher.publishEvent(PointRechargeEvent(user.id, userPoint.id, rechargeCommand.amount))
}

fun getPoint(user: User): Point {
val userPoint = user.point ?: throw NotFoundException("포인트를 찾을 수 없습니다.")
return pointRepository.findById(userPoint.id) ?: throw IllegalArgumentException("포인트를 찾을 수 없습니다.")
fun getBalance(userId: Long): BalanceQueryModel {
val user = tokenUserQueryService.getUser(userId)
val point = pointQueryService.getPoint(user.pointId)
return BalanceQueryModel(user.id, point.balance)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package io.ticketaka.api.point.application.dto
import java.math.BigDecimal

data class BalanceQueryModel(
val userTsid: String,
val userId: Long,
val balance: BigDecimal,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.ticketaka.api.point.application.dto
import java.math.BigDecimal

class RechargeCommand(
val userTsid: String,
val userId: Long,
val pointId: Long,
val amount: BigDecimal,
)
Loading
Loading