-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from Tiketeer/feat/DEV-243
[DEV-243] Waiting 서버 유즈케이스 작성
- Loading branch information
Showing
16 changed files
with
309 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: Check PR | ||
|
||
on: | ||
pull_request | ||
|
||
permissions: | ||
checks: write | ||
pull-requests: write | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up JDK 21 | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: 21 | ||
distribution: 'temurin' | ||
cache: 'gradle' | ||
|
||
- name: Check Build | ||
run: ./gradlew clean build -x test | ||
|
||
- name: Run test | ||
run: ./gradlew test | ||
|
||
- name: Publish Test Results | ||
uses: EnricoMi/publish-unit-test-result-action@v2 | ||
if: always() | ||
with: | ||
junit_files: '**/build/test-results/test/TEST-*.xml' | ||
comment_mode: off | ||
|
||
- name: Add coverage to PR | ||
id: jacoco | ||
uses: madrapps/[email protected] | ||
with: | ||
paths: ${{ github.workspace }}/build/reports/jacoco/test/jacocoTestReport.xml | ||
token: ${{ secrets.GITHUB_TOKEN }} | ||
min-coverage-overall: 40 | ||
min-coverage-changed-files: 60 | ||
update-comment: true | ||
title: Test Coverage | ||
pass-emoji: ':green_circle:' | ||
fail-emoji: ':red_circle:' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,7 @@ out/ | |
|
||
### Kotlin ### | ||
.kotlin | ||
|
||
### Secret ### | ||
.env | ||
src/main/resources/application* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,18 @@ | ||
# Tiketeer-Waiting | ||
티켓팅 시스템에서 트래픽 제어를 위한 대기 큐 레포지토리 | ||
|
||
```dtd | ||
spring: | ||
application: | ||
name: TiketeerWaiting | ||
data: | ||
redis: | ||
repositories: | ||
enabled: false | ||
redis: | ||
host: | ||
port: | ||
waiting: | ||
entry-size: | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/main/kotlin/com/tiketeer/TiketeerWaiting/configuration/RedisConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.tiketeer.TiketeerWaiting.configuration | ||
|
||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.context.annotation.Primary | ||
import org.springframework.context.annotation.Profile | ||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory | ||
import org.springframework.data.redis.connection.RedisConfiguration | ||
import org.springframework.data.redis.connection.RedisConnectionFactory | ||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration | ||
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory | ||
import org.springframework.data.redis.core.ReactiveRedisOperations | ||
import org.springframework.data.redis.core.ReactiveRedisTemplate | ||
import org.springframework.data.redis.core.RedisTemplate | ||
import org.springframework.data.redis.serializer.RedisSerializationContext | ||
|
||
@Configuration | ||
@Profile("!test") | ||
class RedisConfig { | ||
@Value("\${spring.redis.host}") | ||
private lateinit var host: String | ||
|
||
@Value("\${spring.redis.port}") | ||
private lateinit var port: Number | ||
|
||
@Value("\${spring.redis.password}") | ||
private lateinit var password: String | ||
|
||
@Bean | ||
fun redisConnectionFactory() : LettuceConnectionFactory { | ||
val redisStandaloneConfiguration = RedisStandaloneConfiguration(host, port.toInt()) | ||
redisStandaloneConfiguration.setPassword(password) | ||
return LettuceConnectionFactory(redisStandaloneConfiguration) | ||
} | ||
|
||
@Bean | ||
fun redisTemplate(connectionFactory: ReactiveRedisConnectionFactory) : ReactiveRedisTemplate<String, String> { | ||
return ReactiveRedisTemplate(connectionFactory, RedisSerializationContext.string()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.GetMapping | |
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RequestParam | ||
import org.springframework.web.bind.annotation.RestController | ||
import reactor.core.publisher.Mono | ||
import java.util.UUID | ||
|
||
@RestController | ||
|
@@ -15,10 +16,10 @@ class WaitingController( | |
private val getRankAndTokenUseCase: GetRankAndToken | ||
) { | ||
@GetMapping | ||
fun getRankAndToken(@RequestParam(required = true) ticketingId: UUID): GetRankAndTokenResponseDto { | ||
fun getRankAndToken(@RequestParam(required = true) ticketingId: UUID): Mono<GetRankAndTokenResponseDto> { | ||
// TODO: JWT 디코딩 필터 적용 후 JWT 내에서 가져오도록 수정 | ||
val email = "[email protected]" | ||
val result = getRankAndTokenUseCase.getRankAndToken(GetRankAndTokenCommandDto(email, ticketingId)) | ||
val result = getRankAndTokenUseCase.getRankAndToken(GetRankAndTokenCommandDto(email, ticketingId, System.currentTimeMillis())) | ||
return GetRankAndTokenResponseDto.convertFromDto(result) | ||
} | ||
} |
9 changes: 6 additions & 3 deletions
9
.../com/tiketeer/TiketeerWaiting/domain/waiting/controller/dto/GetRankAndTokenResponseDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,17 @@ | ||
package com.tiketeer.TiketeerWaiting.domain.waiting.controller.dto | ||
|
||
import com.tiketeer.TiketeerWaiting.domain.waiting.usecase.dto.GetRankAndTokenResultDto | ||
import reactor.core.publisher.Mono | ||
|
||
data class GetRankAndTokenResponseDto( | ||
val rank: Int, | ||
val rank: Long, | ||
val token: String? = null, | ||
) { | ||
companion object { | ||
fun convertFromDto(dto: GetRankAndTokenResultDto): GetRankAndTokenResponseDto { | ||
return GetRankAndTokenResponseDto(dto.rank, dto.token) | ||
fun convertFromDto(dto: Mono<GetRankAndTokenResultDto>): Mono<GetRankAndTokenResponseDto> { | ||
return dto.flatMap { r -> | ||
Mono.just(GetRankAndTokenResponseDto(r.rank, r.token)) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...otlin/com/tiketeer/TiketeerWaiting/domain/waiting/usecase/dto/GetRankAndTokenResultDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
package com.tiketeer.TiketeerWaiting.domain.waiting.usecase.dto | ||
|
||
data class GetRankAndTokenResultDto( | ||
val rank: Int, | ||
val rank: Long, | ||
val token: String? = null, | ||
) |
This file was deleted.
Oops, something went wrong.
62 changes: 62 additions & 0 deletions
62
src/test/kotlin/com/tiketeer/TiketeerWaiting/configuration/EmbeddedRedisConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.tiketeer.TiketeerWaiting.configuration | ||
|
||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
import jakarta.annotation.PostConstruct | ||
import jakarta.annotation.PreDestroy | ||
import org.junit.jupiter.api.DisplayName | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.boot.test.context.TestConfiguration | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory | ||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration | ||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory | ||
import org.springframework.data.redis.core.ReactiveRedisTemplate | ||
import org.springframework.data.redis.serializer.RedisSerializationContext | ||
import redis.embedded.RedisServer | ||
import java.io.IOException | ||
|
||
private val logger = KotlinLogging.logger {} | ||
|
||
@DisplayName("Embedded Redis 설정") | ||
@TestConfiguration | ||
class EmbeddedRedisConfig { | ||
@Value("\${spring.data.redis.host}") | ||
private lateinit var host: String | ||
|
||
@Value("\${spring.data.redis.port}") | ||
private lateinit var port: Number | ||
|
||
@Value("\${spring.redis.maxmemory}") | ||
private lateinit var maxmemorySize: Number | ||
|
||
private lateinit var redisServer: RedisServer | ||
|
||
@PostConstruct | ||
@Throws(IOException::class) | ||
fun startRedis() { | ||
this.redisServer = RedisServer.builder().port(port.toInt()).setting("maxmemory " + maxmemorySize + "M").build() | ||
try { | ||
this.redisServer.start() | ||
logger.info {"레디스 서버 시작 성공" } | ||
} catch (e: Exception) { | ||
logger.error (e) { "레디스 서버 시작 실패: ${e.message}" } | ||
} | ||
} | ||
|
||
@PreDestroy | ||
fun stopRedis() { | ||
redisServer.stop() | ||
} | ||
|
||
@Bean | ||
fun redisConnectionFactory() : LettuceConnectionFactory { | ||
val redisStandaloneConfiguration = RedisStandaloneConfiguration(host, port.toInt()) | ||
return LettuceConnectionFactory(redisStandaloneConfiguration) | ||
} | ||
|
||
@Bean | ||
fun redisTemplate(connectionFactory: ReactiveRedisConnectionFactory) : ReactiveRedisTemplate<String, String> { | ||
return ReactiveRedisTemplate(connectionFactory, RedisSerializationContext.string()) | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
.../kotlin/com/tiketeer/TiketeerWaiting/domain/waiting/usecase/GetRankAndTokenUseCaseTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package com.tiketeer.TiketeerWaiting.domain.waiting.usecase | ||
|
||
import com.tiketeer.TiketeerWaiting.configuration.EmbeddedRedisConfig | ||
import com.tiketeer.TiketeerWaiting.domain.waiting.usecase.dto.GetRankAndTokenCommandDto | ||
import com.tiketeer.TiketeerWaiting.domain.waiting.usecase.dto.GetRankAndTokenResultDto | ||
import org.junit.jupiter.api.BeforeEach | ||
|
||
import org.junit.jupiter.api.Test | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.boot.test.context.SpringBootTest | ||
import org.springframework.context.annotation.Import | ||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory | ||
import reactor.test.StepVerifier | ||
import java.util.UUID | ||
|
||
@Import(EmbeddedRedisConfig::class) | ||
@SpringBootTest | ||
class GetRankAndTokenUseCaseTest { | ||
@Autowired | ||
lateinit var getRankAndTokenUseCase: GetRankAndTokenUseCase | ||
|
||
@Autowired | ||
lateinit var redisConnectionFactory: ReactiveRedisConnectionFactory | ||
|
||
@Value("\${waiting.entry-size}") | ||
lateinit var entrySize: Number | ||
|
||
@BeforeEach | ||
fun init() { | ||
val flushDb = redisConnectionFactory.reactiveConnection.serverCommands().flushDb() | ||
flushDb.block() | ||
} | ||
|
||
@Test | ||
fun `유저 정보 생성 - 빈 대기열에 요청 - 결과 검증`() { | ||
val email = "[email protected]" | ||
val ticketingId = UUID.randomUUID() | ||
val entryTime = System.currentTimeMillis() | ||
val result = getRankAndTokenUseCase.getRankAndToken(GetRankAndTokenCommandDto(email, ticketingId, entryTime)) | ||
|
||
StepVerifier.create(result) | ||
.expectNext(GetRankAndTokenResultDto(0, "${email}:${ticketingId}")) | ||
.expectComplete() | ||
.verify() | ||
} | ||
|
||
@Test | ||
fun `대기열 길이만큼 유저 생성 - 대기열을 모두 채우도록 요청 후 한 명 더 요청 - 빈 토큰 결과 반환`() { | ||
val ticketingId = UUID.randomUUID() | ||
for (i in 1..entrySize.toInt()) { | ||
val email = "test${i}@test.com" | ||
val entryTime = System.currentTimeMillis() | ||
val result = getRankAndTokenUseCase.getRankAndToken(GetRankAndTokenCommandDto(email, ticketingId, entryTime)) | ||
result.block() | ||
} | ||
|
||
val email = "[email protected]" | ||
val entryTime = System.currentTimeMillis() | ||
val result = getRankAndTokenUseCase.getRankAndToken(GetRankAndTokenCommandDto(email, ticketingId, entryTime)) | ||
|
||
StepVerifier.create(result) | ||
.expectNext(GetRankAndTokenResultDto(entrySize.toLong())) | ||
.expectComplete() | ||
.verify() | ||
} | ||
} |
Oops, something went wrong.