From ee56adcf27ddd677e8d8fac94c5aaa9e82e20b16 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 18 Nov 2023 12:02:40 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Nodeinfo=E3=81=AE=E3=83=87=E3=82=B7?= =?UTF-8?q?=E3=83=AA=E3=82=A2=E3=83=A9=E3=82=A4=E3=82=BA=E7=94=A8=E3=82=AF?= =?UTF-8?q?=E3=83=A9=E3=82=B9=E3=82=92=E5=88=A5=E3=81=AB=E6=BA=96=E5=82=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/APResourceResolveServiceImpl.kt | 38 ++++++++++++-- .../service/common/CacheManager.kt | 9 ---- .../service/common/InMemoryCacheManager.kt | 50 ------------------- .../core/domain/model/instance/Nodeinfo.kt | 16 ++++++ .../core/service/instance/InstanceService.kt | 9 ++-- 5 files changed, 55 insertions(+), 67 deletions(-) delete mode 100644 src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/CacheManager.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/InMemoryCacheManager.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/Nodeinfo.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt index 49906265..81b7aec3 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt @@ -3,7 +3,10 @@ package dev.usbharu.hideout.activitypub.service.common import dev.usbharu.hideout.activitypub.domain.model.objects.Object import dev.usbharu.hideout.core.domain.model.user.User import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.service.resource.CacheManager +import dev.usbharu.hideout.core.service.resource.ResolveResponse import org.springframework.stereotype.Service +import java.io.InputStream @Service class APResourceResolveServiceImpl( @@ -25,7 +28,7 @@ class APResourceResolveServiceImpl( cacheManager.putCache(key) { runResolve(url, singerId?.let { userRepository.findById(it) }, clazz) } - return cacheManager.getOrWait(key) as T + return (cacheManager.getOrWait(key) as APResolveResponse).objects } private suspend fun internalResolve(url: String, singer: User?, clazz: Class): T { @@ -33,11 +36,12 @@ class APResourceResolveServiceImpl( cacheManager.putCache(key) { runResolve(url, singer, clazz) } - return cacheManager.getOrWait(key) as T + return (cacheManager.getOrWait(key) as APResolveResponse).objects } - private suspend fun runResolve(url: String, singer: User?, clazz: Class): Object = - apRequestService.apGet(url, singer, clazz) + private suspend fun runResolve(url: String, singer: User?, clazz: Class): ResolveResponse { + return APResolveResponse(apRequestService.apGet(url, singer, clazz)) + } private fun genCacheKey(url: String, singerId: Long?): String { if (singerId != null) { @@ -45,4 +49,30 @@ class APResourceResolveServiceImpl( } return url } + + private class APResolveResponse(val objects: T) : ResolveResponse { + override suspend fun body(): InputStream { + TODO("Not yet implemented") + } + + override suspend fun bodyAsText(): String { + TODO("Not yet implemented") + } + + override suspend fun bodyAsBytes(): ByteArray { + TODO("Not yet implemented") + } + + override suspend fun header(): Map> { + TODO("Not yet implemented") + } + + override suspend fun status(): Int { + TODO("Not yet implemented") + } + + override suspend fun statusMessage(): String { + TODO("Not yet implemented") + } + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/CacheManager.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/CacheManager.kt deleted file mode 100644 index 83ae4f9d..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/CacheManager.kt +++ /dev/null @@ -1,9 +0,0 @@ -package dev.usbharu.hideout.activitypub.service.common - -import dev.usbharu.hideout.activitypub.domain.model.objects.Object - -interface CacheManager { - - suspend fun putCache(key: String, block: suspend () -> Object) - suspend fun getOrWait(key: String): Object -} diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/InMemoryCacheManager.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/InMemoryCacheManager.kt deleted file mode 100644 index 3c8320db..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/InMemoryCacheManager.kt +++ /dev/null @@ -1,50 +0,0 @@ -package dev.usbharu.hideout.activitypub.service.common - -import dev.usbharu.hideout.activitypub.domain.model.objects.Object -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(15) - private val valueStore = mutableMapOf() - private val keyMutex = Mutex() - - override suspend fun putCache(key: String, block: suspend () -> Object) { - 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): Object { - while (valueStore.contains(key).not()) { - if (cacheKey.containsKey(key).not()) { - throw IllegalStateException("Invalid cache key.") - } - delay(1) - } - return valueStore.getValue(key) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/Nodeinfo.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/Nodeinfo.kt new file mode 100644 index 00000000..4aa53126 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/Nodeinfo.kt @@ -0,0 +1,16 @@ +package dev.usbharu.hideout.core.domain.model.instance + +class Nodeinfo { + + var links: List = emptyList() + + protected constructor() +} + + +class Links { + var rel: String? = null + var href: String? = null + + protected constructor() +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt index bb4a2a0c..5b54054e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/instance/InstanceService.kt @@ -1,11 +1,12 @@ package dev.usbharu.hideout.core.service.instance import com.fasterxml.jackson.databind.ObjectMapper -import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo import dev.usbharu.hideout.activitypub.domain.model.nodeinfo.Nodeinfo2_0 import dev.usbharu.hideout.core.domain.model.instance.Instance import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository +import dev.usbharu.hideout.core.domain.model.instance.Nodeinfo import dev.usbharu.hideout.core.service.resource.ResourceResolveService +import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import java.net.URL import java.time.Instant @@ -20,21 +21,21 @@ interface InstanceService { class InstanceServiceImpl( private val instanceRepository: InstanceRepository, private val resourceResolveService: ResourceResolveService, - private val objectMapper: ObjectMapper + @Qualifier("activitypub") private val objectMapper: ObjectMapper ) : InstanceService { override suspend fun fetchInstance(url: String): Instance { val u = URL(url) val resolveInstanceUrl = u.protocol + "://" + u.host val nodeinfoJson = resourceResolveService.resolve("$resolveInstanceUrl/.well-known/nodeinfo").bodyAsText() val nodeinfo = objectMapper.readValue(nodeinfoJson, Nodeinfo::class.java) - val nodeinfoPathMap = nodeinfo.links.map { it.rel to it.href }.toMap() + val nodeinfoPathMap = nodeinfo.links.associate { it.rel to it.href } for ((key, value) in nodeinfoPathMap) { when (key) { "http://nodeinfo.diaspora.software/ns/schema/2.0" -> { val nodeinfo20 = objectMapper.readValue( - resourceResolveService.resolve(value).bodyAsText(), + resourceResolveService.resolve(value!!).bodyAsText(), Nodeinfo2_0::class.java )