| @@ -26,6 +26,7 @@ repositories { | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     implementation("org.redisson:redisson-spring-data-27:3.19.2") | ||||
|     implementation("org.springframework.boot:spring-boot-starter-aop") | ||||
|     implementation("org.springframework.boot:spring-boot-starter-data-jpa") | ||||
|     implementation("org.springframework.boot:spring-boot-starter-data-redis") | ||||
|   | ||||
| @@ -1,5 +1,8 @@ | ||||
| package kr.co.vividnext.sodalive.configs | ||||
|  | ||||
| import org.redisson.Redisson | ||||
| import org.redisson.api.RedissonClient | ||||
| import org.redisson.config.Config | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.cache.annotation.EnableCaching | ||||
| import org.springframework.context.annotation.Bean | ||||
| @@ -26,6 +29,19 @@ class RedisConfig( | ||||
|     @Value("\${spring.redis.port}") | ||||
|     private val port: Int | ||||
| ) { | ||||
|     @Bean(destroyMethod = "shutdown") | ||||
|     fun redissonClient(): RedissonClient { | ||||
|         val config = Config() | ||||
|         config.useSingleServer() | ||||
|             .setAddress("rediss://$host:$port") | ||||
|             .setSslEnableEndpointIdentification(true) | ||||
|             .setSslTruststore(null) | ||||
|             .setDnsMonitoringInterval(30000) | ||||
|             .setConnectionMinimumIdleSize(0) | ||||
|             .setConnectionPoolSize(5) | ||||
|         return Redisson.create(config) | ||||
|     } | ||||
|  | ||||
|     @Bean | ||||
|     fun redisConnectionFactory(): RedisConnectionFactory { | ||||
|         val clientConfiguration = LettuceClientConfiguration.builder() | ||||
|   | ||||
| @@ -1,17 +1,20 @@ | ||||
| package kr.co.vividnext.sodalive.scheduler | ||||
|  | ||||
| import kr.co.vividnext.sodalive.content.AudioContentService | ||||
| import org.redisson.api.RedissonClient | ||||
| import org.springframework.beans.factory.annotation.Qualifier | ||||
| import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler | ||||
| import org.springframework.scheduling.support.CronTrigger | ||||
| import org.springframework.stereotype.Component | ||||
| import java.util.concurrent.ScheduledFuture | ||||
| import java.util.concurrent.TimeUnit | ||||
| import javax.annotation.PostConstruct | ||||
| import javax.annotation.PreDestroy | ||||
|  | ||||
| @Component | ||||
| class AudioContentReleaseScheduledTask( | ||||
|     private val audioContentService: AudioContentService, | ||||
|     private val redissonClient: RedissonClient, | ||||
|     @Qualifier("audioContentReleaseScheduler") private val audioContentReleaseScheduler: ThreadPoolTaskScheduler | ||||
| ) { | ||||
|     private var scheduledTask: ScheduledFuture<*>? = null | ||||
| @@ -19,7 +22,25 @@ class AudioContentReleaseScheduledTask( | ||||
|     @PostConstruct | ||||
|     fun release() { | ||||
|         scheduledTask = audioContentReleaseScheduler.schedule( | ||||
|             { audioContentService.releaseContent() }, | ||||
|             { | ||||
|                 val lockName = "lock:audioContentRelease" | ||||
|                 val lock = redissonClient.getLock(lockName) | ||||
|  | ||||
|                 try { | ||||
|                     // 5초 동안 락을 시도하고, Watchdog 활성화 (-1 설정) | ||||
|                     if (lock.tryLock(5, -1, TimeUnit.SECONDS)) { | ||||
|                         println("acquired : $lockName") | ||||
|                         audioContentService.releaseContent() | ||||
|                     } else { | ||||
|                         println("Failed to acquire lock : $lockName") | ||||
|                     } | ||||
|                 } finally { | ||||
|                     if (lock.isHeldByCurrentThread) { | ||||
|                         lock.unlock() | ||||
|                         println("release : $lockName") | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             CronTrigger("0 0/15 * * * *") | ||||
|         ) | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user