From ed296637d9c88ab215ddc1a984f7c0ecfb8f0d5b Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:22:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8C=E3=81=98=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=81=AE=E3=83=AA=E3=82=AF=E3=82=A8=E3=82=B9=E3=83=88=E3=81=8C?= =?UTF-8?q?=E5=90=8C=E6=99=82=E5=A4=9A=E7=99=BA=E7=9A=84=E3=81=AB=E7=99=BA?= =?UTF-8?q?=E7=94=9F=E3=81=97=E3=81=AA=E3=81=84=E4=BB=95=E7=B5=84=E3=81=BF?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ap/resource/APResourceResolveService.kt | 9 +++ .../resource/APResourceResolveServiceImpl.kt | 70 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveService.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveService.kt new file mode 100644 index 00000000..20459fba --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveService.kt @@ -0,0 +1,9 @@ +package dev.usbharu.hideout.service.ap.resource + +import dev.usbharu.hideout.domain.model.ap.Object +import dev.usbharu.hideout.domain.model.hideout.entity.User + +interface APResourceResolveService { + suspend fun resolve(url: String, singerId: Long?): Object + suspend fun resolve(url: String, singer: User?): Object +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveServiceImpl.kt new file mode 100644 index 00000000..304c10da --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/resource/APResourceResolveServiceImpl.kt @@ -0,0 +1,70 @@ +package dev.usbharu.hideout.service.ap.resource + +import dev.usbharu.hideout.domain.model.ap.Object +import dev.usbharu.hideout.domain.model.hideout.entity.User +import dev.usbharu.hideout.repository.UserRepository +import io.ktor.client.* +import io.ktor.client.call.* +import io.ktor.client.request.* +import kotlinx.coroutines.delay +import java.time.Instant +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class APResourceResolveServiceImpl(private val httpClient: HttpClient, private val userRepository: UserRepository) : + APResourceResolveService { + + override suspend fun resolve(url: String, singerId: Long?): Object { + return internalResolve(url, singerId) + } + + override suspend fun resolve(url: String, singer: User?): Object { + return internalResolve(url, singer) + } + + private suspend fun internalResolve(url: String, singerId: Long?): Object { + + val key = genCacheKey(url, singerId) + val ifAbsent = cacheKey.putIfAbsent(key, Instant.now().toEpochMilli()) + if (ifAbsent == null) { + val resolve = runResolve(url, singerId?.let { userRepository.findById(it) }) + valueStore.putIfAbsent(key, resolve) + return resolve + } + return wait(key) + } + + private suspend fun internalResolve(url: String, singer: User?): Object { + val key = genCacheKey(url, singer?.id) + val ifAbsent = cacheKey.putIfAbsent(key, Instant.now().toEpochMilli()) + if (ifAbsent == null) { + val resolve = runResolve(url, singer) + valueStore.putIfAbsent(key, resolve) + return resolve + } + return wait(key) + } + + private suspend fun wait(key: String): Object { + while (valueStore.containsKey(key).not()) { + delay(1) + } + return valueStore.getValue(key) as Object + } + + private suspend fun runResolve(url: String, singer: User?): Object { + return httpClient.get(url).body() + } + + private fun genCacheKey(url: String, singerId: Long?): String { + if (singerId != null) { + return "$url-$singerId" + } + return url + } + + companion object { + private val cacheKey = ConcurrentHashMap() + private val valueStore = Collections.synchronizedMap(mutableMapOf()) + } +}