feat(recommend): 추천 스냅샷 lock을 적용한다
This commit is contained in:
@@ -10,11 +10,14 @@ import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.mockito.Mockito
|
||||
import org.redisson.api.RLock
|
||||
import org.redisson.api.RedissonClient
|
||||
import org.springframework.boot.test.system.CapturedOutput
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension
|
||||
import org.springframework.scheduling.annotation.Scheduled
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
import java.time.LocalDateTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@ExtendWith(OutputCaptureExtension::class)
|
||||
class RecommendationSnapshotRefreshServiceTest {
|
||||
@@ -170,7 +173,12 @@ class RecommendationSnapshotRefreshServiceTest {
|
||||
.getDeclaredMethod("refreshDailySnapshots")
|
||||
.getAnnotation(Scheduled::class.java)
|
||||
val service = Mockito.mock(RecommendationSnapshotRefreshService::class.java)
|
||||
val scheduler = RecommendationSnapshotScheduler(service)
|
||||
val redissonClient = Mockito.mock(RedissonClient::class.java)
|
||||
val lock = Mockito.mock(RLock::class.java)
|
||||
Mockito.`when`(redissonClient.getLock("lock:recommendation-snapshot-refresh")).thenReturn(lock)
|
||||
Mockito.`when`(lock.tryLock(0, -1, TimeUnit.SECONDS)).thenReturn(true)
|
||||
Mockito.`when`(lock.isHeldByCurrentThread).thenReturn(true)
|
||||
val scheduler = RecommendationSnapshotScheduler(service, redissonClient)
|
||||
|
||||
scheduler.refreshDailySnapshots()
|
||||
|
||||
@@ -179,6 +187,44 @@ class RecommendationSnapshotRefreshServiceTest {
|
||||
Mockito.verify(service).refreshDailySnapshots()
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 스냅샷 스케줄러는 Redisson lock을 획득한 인스턴스만 갱신을 실행한다")
|
||||
fun shouldRefreshDailySnapshotsOnlyWhenRedissonLockAcquired() {
|
||||
val service = Mockito.mock(RecommendationSnapshotRefreshService::class.java)
|
||||
val redissonClient = Mockito.mock(RedissonClient::class.java)
|
||||
val lock = Mockito.mock(RLock::class.java)
|
||||
Mockito.`when`(redissonClient.getLock("lock:recommendation-snapshot-refresh")).thenReturn(lock)
|
||||
Mockito.`when`(lock.tryLock(0, -1, TimeUnit.SECONDS)).thenReturn(true)
|
||||
Mockito.`when`(lock.isHeldByCurrentThread).thenReturn(true)
|
||||
val scheduler = RecommendationSnapshotScheduler(service, redissonClient)
|
||||
|
||||
scheduler.refreshDailySnapshots()
|
||||
|
||||
Mockito.verify(redissonClient).getLock("lock:recommendation-snapshot-refresh")
|
||||
Mockito.verify(lock).tryLock(0, -1, TimeUnit.SECONDS)
|
||||
Mockito.verify(service).refreshDailySnapshots()
|
||||
Mockito.verify(lock).unlock()
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("추천 스냅샷 스케줄러는 Redisson lock 획득 실패 시 갱신을 건너뛴다")
|
||||
fun shouldSkipDailySnapshotRefreshWhenRedissonLockNotAcquired() {
|
||||
val service = Mockito.mock(RecommendationSnapshotRefreshService::class.java)
|
||||
val redissonClient = Mockito.mock(RedissonClient::class.java)
|
||||
val lock = Mockito.mock(RLock::class.java)
|
||||
Mockito.`when`(redissonClient.getLock("lock:recommendation-snapshot-refresh")).thenReturn(lock)
|
||||
Mockito.`when`(lock.tryLock(0, -1, TimeUnit.SECONDS)).thenReturn(false)
|
||||
Mockito.`when`(lock.isHeldByCurrentThread).thenReturn(false)
|
||||
val scheduler = RecommendationSnapshotScheduler(service, redissonClient)
|
||||
|
||||
scheduler.refreshDailySnapshots()
|
||||
|
||||
Mockito.verify(redissonClient).getLock("lock:recommendation-snapshot-refresh")
|
||||
Mockito.verify(lock).tryLock(0, -1, TimeUnit.SECONDS)
|
||||
Mockito.verify(service, Mockito.never()).refreshDailySnapshots()
|
||||
Mockito.verify(lock, Mockito.never()).unlock()
|
||||
}
|
||||
|
||||
private fun service(
|
||||
snapshotPort: RecommendationSnapshotPort = FakeRecommendationSnapshotPort(),
|
||||
queryPort: HomeRecommendationQueryPort = Mockito.mock(HomeRecommendationQueryPort::class.java)
|
||||
|
||||
Reference in New Issue
Block a user