mirror of https://github.com/usbharu/Hideout.git
feat: 汎用ResourceResolverを追加
This commit is contained in:
parent
1db8f31b5f
commit
bb87cab45f
|
@ -0,0 +1,6 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
interface CacheManager {
|
||||
suspend fun putCache(key: String, block: suspend () -> ResolveResponse)
|
||||
suspend fun getOrWait(key: String): ResolveResponse
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
import dev.usbharu.hideout.util.LruCache
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.Instant
|
||||
|
||||
@Service
|
||||
class InMemoryCacheManager : CacheManager {
|
||||
private val cacheKey = LruCache<String, Long>(15)
|
||||
private val valueStore = mutableMapOf<String, ResolveResponse>()
|
||||
private val keyMutex = Mutex()
|
||||
|
||||
override suspend fun putCache(key: String, block: suspend () -> ResolveResponse) {
|
||||
val needRunBlock: Boolean
|
||||
keyMutex.withLock {
|
||||
cacheKey.filter { Instant.ofEpochMilli(it.value).plusSeconds(300) <= Instant.now() }
|
||||
|
||||
val cached = cacheKey.get(key)
|
||||
if (cached == null) {
|
||||
needRunBlock = true
|
||||
cacheKey[key] = Instant.now().toEpochMilli()
|
||||
|
||||
valueStore.remove(key)
|
||||
} else {
|
||||
needRunBlock = false
|
||||
}
|
||||
}
|
||||
if (needRunBlock) {
|
||||
val processed = block()
|
||||
|
||||
if (cacheKey.containsKey(key)) {
|
||||
valueStore[key] = processed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getOrWait(key: String): ResolveResponse {
|
||||
while (valueStore.contains(key).not()) {
|
||||
if (cacheKey.containsKey(key).not()) {
|
||||
throw IllegalStateException("Invalid cache key.")
|
||||
}
|
||||
delay(1)
|
||||
}
|
||||
return valueStore.getValue(key)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.utils.io.jvm.javaio.*
|
||||
import java.io.InputStream
|
||||
|
||||
class KtorResolveResponse(val ktorHttpResponse: HttpResponse) : ResolveResponse {
|
||||
|
||||
override suspend fun body(): InputStream = ktorHttpResponse.bodyAsChannel().toInputStream()
|
||||
override suspend fun header(): Map<String, List<String>> = ktorHttpResponse.headers.toMap()
|
||||
override suspend fun status(): Int = ktorHttpResponse.status.value
|
||||
override suspend fun statusMessage(): String = ktorHttpResponse.status.description
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.request.*
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Service
|
||||
open class KtorResourceResolveService(private val httpClient: HttpClient, private val cacheManager: CacheManager) :
|
||||
ResourceResolveService {
|
||||
override suspend fun resolve(url: String): ResolveResponse {
|
||||
cacheManager.putCache(getCacheKey(url)) {
|
||||
runResolve(url)
|
||||
}
|
||||
return cacheManager.getOrWait(getCacheKey(url))
|
||||
}
|
||||
|
||||
protected suspend fun runResolve(url: String): ResolveResponse {
|
||||
val httpResponse = httpClient.get(url)
|
||||
|
||||
return KtorResolveResponse(httpResponse)
|
||||
}
|
||||
|
||||
protected suspend fun getCacheKey(url: String) = url
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
import java.io.InputStream
|
||||
|
||||
interface ResolveResponse {
|
||||
suspend fun body(): InputStream
|
||||
suspend fun header(): Map<String, List<String>>
|
||||
suspend fun status(): Int
|
||||
suspend fun statusMessage(): String
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package dev.usbharu.hideout.core.service.resource
|
||||
|
||||
interface ResourceResolveService {
|
||||
suspend fun resolve(url: String): ResolveResponse
|
||||
}
|
Loading…
Reference in New Issue