From 656db6d0db42cea79402d89546f47f2f9c459e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A7=80=ED=9B=88?= Date: Sun, 21 Jul 2024 20:49:34 +0900 Subject: [PATCH] =?UTF-8?q?[Feat/#224]=20=EB=A1=9C=EC=BB=AC=20=EC=BA=90?= =?UTF-8?q?=EC=8B=9C(EHCache)=20=EB=8F=84=EC=9E=85=20=EB=B0=8F=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EB=8B=A8=EA=B1=B4=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=BA=90=EC=8B=9C=20=EC=A0=81=EC=9A=A9=20(#226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 로컬 캐시(EHCache) 디펜던시 추가 In api-repo 모듈 * feat: EHCache 설정 적용 및 신규 캐시 키(selectArticleRecordCache) 추가 * refactor: ehcache 설정 xml -> javaconfig 변경 * feat: SelectArticleRecord에 Serializable 추가 * feat: LocalCacheConfig의 상수 활용하는 방법으로 수정 * refactor: EHCache에서 event.newValue, oldValue 로깅하지 않도록 변경 * refactor: localCacheProvider 선언 * refactor: EhcacheCachingProvider로 수정 --------- Co-authored-by: belljun3395 <195850@jnu.ac.kr> --- api-repo/build.gradle.kts | 4 ++ .../api/repo/common/LocalCacheEventLogger.kt | 13 ++++ .../few/api/repo/config/LocalCacheConfig.kt | 60 +++++++++++++++++++ .../few/api/repo/dao/article/ArticleDao.kt | 5 ++ .../dao/article/record/SelectArticleRecord.kt | 3 +- buildSrc/src/main/kotlin/DependencyVersion.kt | 3 + 6 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 api-repo/src/main/kotlin/com/few/api/repo/common/LocalCacheEventLogger.kt create mode 100644 api-repo/src/main/kotlin/com/few/api/repo/config/LocalCacheConfig.kt diff --git a/api-repo/build.gradle.kts b/api-repo/build.gradle.kts index e8fd7bc26..2b8b18d10 100644 --- a/api-repo/build.gradle.kts +++ b/api-repo/build.gradle.kts @@ -28,4 +28,8 @@ dependencies { /** test container */ implementation(platform("org.testcontainers:testcontainers-bom:${DependencyVersion.TEST_CONTAINER}")) testImplementation("org.testcontainers:mysql") + + /** Local Cache **/ + implementation("org.ehcache:ehcache:${DependencyVersion.EHCACHE}") + implementation("org.springframework.boot:spring-boot-starter-cache") } \ No newline at end of file diff --git a/api-repo/src/main/kotlin/com/few/api/repo/common/LocalCacheEventLogger.kt b/api-repo/src/main/kotlin/com/few/api/repo/common/LocalCacheEventLogger.kt new file mode 100644 index 000000000..4f28df241 --- /dev/null +++ b/api-repo/src/main/kotlin/com/few/api/repo/common/LocalCacheEventLogger.kt @@ -0,0 +1,13 @@ +package com.few.api.repo.common + +import io.github.oshai.kotlinlogging.KotlinLogging +import org.ehcache.event.CacheEvent +import org.ehcache.event.CacheEventListener + +class LocalCacheEventLogger : CacheEventListener { + private val log = KotlinLogging.logger {} + + override fun onEvent(event: CacheEvent) { + log.debug { "Local Cache event: ${event.type} for item with key: ${event.key}. " } + } +} \ No newline at end of file diff --git a/api-repo/src/main/kotlin/com/few/api/repo/config/LocalCacheConfig.kt b/api-repo/src/main/kotlin/com/few/api/repo/config/LocalCacheConfig.kt new file mode 100644 index 000000000..05179bfb2 --- /dev/null +++ b/api-repo/src/main/kotlin/com/few/api/repo/config/LocalCacheConfig.kt @@ -0,0 +1,60 @@ +package com.few.api.repo.config + +import com.few.api.repo.common.LocalCacheEventLogger +import io.github.oshai.kotlinlogging.KotlinLogging +import org.ehcache.config.builders.CacheConfigurationBuilder +import org.ehcache.config.builders.ResourcePoolsBuilder +import org.ehcache.config.units.EntryUnit +import org.ehcache.event.EventType +import org.ehcache.impl.config.event.DefaultCacheEventListenerConfiguration +import org.ehcache.jsr107.Eh107Configuration +import org.ehcache.jsr107.EhcacheCachingProvider +import org.springframework.cache.CacheManager +import org.springframework.cache.annotation.EnableCaching +import org.springframework.cache.jcache.JCacheCacheManager +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +@EnableCaching +class LocalCacheConfig { + private val log = KotlinLogging.logger {} + + companion object { + const val LOCAL_CM = "localCacheManager" + const val SELECT_ARTICLE_RECORD_CACHE = "selectArticleRecordCache" + } + + @Bean(LOCAL_CM) + fun localCacheManager(): CacheManager { + val cacheEventListenerConfigurationConfig = DefaultCacheEventListenerConfiguration( + setOf( + EventType.CREATED, + EventType.EXPIRED, + EventType.REMOVED, + EventType.UPDATED + ), + LocalCacheEventLogger::class.java + ) + val cacheManager = EhcacheCachingProvider().cacheManager + + val cacheConfigurationBuilder = CacheConfigurationBuilder.newCacheConfigurationBuilder( + Any::class.java, + Any::class.java, + ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap(50, EntryUnit.ENTRIES) + ) + .withService(cacheEventListenerConfigurationConfig) + .build() + + val selectArticleRecordCacheConfig: javax.cache.configuration.Configuration = + Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfigurationBuilder) + runCatching { + cacheManager.createCache(SELECT_ARTICLE_RECORD_CACHE, selectArticleRecordCacheConfig) + }.onFailure { + log.error(it) { "Failed to create cache" } + } + + return JCacheCacheManager(cacheManager) + } +} \ No newline at end of file diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/article/ArticleDao.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/article/ArticleDao.kt index 9a01f0ee0..a87e0cc0b 100644 --- a/api-repo/src/main/kotlin/com/few/api/repo/dao/article/ArticleDao.kt +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/article/ArticleDao.kt @@ -1,5 +1,7 @@ package com.few.api.repo.dao.article +import com.few.api.repo.config.LocalCacheConfig.Companion.LOCAL_CM +import com.few.api.repo.config.LocalCacheConfig.Companion.SELECT_ARTICLE_RECORD_CACHE import com.few.api.repo.dao.article.command.InsertFullArticleRecordCommand import com.few.api.repo.dao.article.query.SelectArticleRecordQuery import com.few.api.repo.dao.article.query.SelectWorkBookArticleRecordQuery @@ -11,12 +13,15 @@ import jooq.jooq_dsl.tables.ArticleIfo import jooq.jooq_dsl.tables.ArticleMst import jooq.jooq_dsl.tables.MappingWorkbookArticle import org.jooq.DSLContext +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Repository @Repository class ArticleDao( private val dslContext: DSLContext, ) { + + @Cacheable(key = "#query.articleId", cacheManager = LOCAL_CM, cacheNames = [SELECT_ARTICLE_RECORD_CACHE]) fun selectArticleRecord(query: SelectArticleRecordQuery): SelectArticleRecord? { val articleId = query.articleId diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/article/record/SelectArticleRecord.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/article/record/SelectArticleRecord.kt index 28e828279..dc80ccbde 100644 --- a/api-repo/src/main/kotlin/com/few/api/repo/dao/article/record/SelectArticleRecord.kt +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/article/record/SelectArticleRecord.kt @@ -1,5 +1,6 @@ package com.few.api.repo.dao.article.record +import java.io.Serializable import java.net.URL import java.time.LocalDateTime @@ -11,4 +12,4 @@ data class SelectArticleRecord( val category: Byte, val content: String, val createdAt: LocalDateTime, -) \ No newline at end of file +) : Serializable \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/DependencyVersion.kt b/buildSrc/src/main/kotlin/DependencyVersion.kt index 92943253a..689a4f58f 100644 --- a/buildSrc/src/main/kotlin/DependencyVersion.kt +++ b/buildSrc/src/main/kotlin/DependencyVersion.kt @@ -44,4 +44,7 @@ object DependencyVersion { /** Logger **/ const val KOTLIN_LOGGING = "7.0.0" + + /** Local Cache **/ + const val EHCACHE = "3.10.0" }