diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt index 9685d383..b0807f48 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt @@ -5,12 +5,10 @@ import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl.Companion.public import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.infrastructure.exposedrepository.* -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.Query import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.select @@ -21,39 +19,38 @@ import java.time.Instant @Repository class NoteQueryServiceImpl(private val postRepository: PostRepository, private val postQueryMapper: QueryMapper) : NoteQueryService { - override suspend fun findById(id: Long): Pair { + override suspend fun findById(id: Long): Pair? { return Posts .leftJoin(Actors) .leftJoin(PostsMedia) .leftJoin(Media) .select { Posts.id eq id } .let { - it.toNote() to postQueryMapper.map(it) - .singleOr { FailedToGetResourcesException("id: $id does not exist.") } + (it.toNote() ?: return null) to (postQueryMapper.map(it) + .singleOrNull() ?: return null) } } - override suspend fun findByApid(apId: String): Pair { + override suspend fun findByApid(apId: String): Pair? { return Posts .leftJoin(Actors) .leftJoin(PostsMedia) .leftJoin(Media) .select { Posts.apId eq apId } .let { - it.toNote() to postQueryMapper.map(it) - .singleOr { FailedToGetResourcesException("apid: $apId does not exist.") } + (it.toNote() ?: return null) to (postQueryMapper.map(it) + .singleOrNull() ?: return null) } } private suspend fun ResultRow.toNote(mediaList: List): Note { val replyId = this[Posts.replyId] val replyTo = if (replyId != null) { - try { - postRepository.findById(replyId)?.url ?: throw FailedToGetResourcesException() - } catch (e: FailedToGetResourcesException) { - logger.warn("Failed to get replyId: $replyId", e) - null + val url = postRepository.findById(replyId)?.url + if (url == null) { + logger.warn("Failed to get replyId: $replyId") } + url } else { null } @@ -76,11 +73,11 @@ class NoteQueryServiceImpl(private val postRepository: PostRepository, private v ) } - private suspend fun Query.toNote(): Note { + private suspend fun Query.toNote(): Note? { return this.groupBy { it[Posts.id] } .map { it.value } .map { it.first().toNote(it.mapNotNull { resultRow -> resultRow.toMediaOrNull() }) } - .singleOr { FailedToGetResourcesException("resource does not exist.") } + .singleOrNull() } private fun visibility(visibility: Visibility, followers: String?): Pair, List> { diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImpl.kt index ea8ad508..df90a913 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImpl.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.activitypub.interfaces.api.actor import dev.usbharu.hideout.activitypub.domain.model.Person import dev.usbharu.hideout.activitypub.service.objects.user.APUserService -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RestController @@ -12,7 +12,7 @@ class UserAPControllerImpl(private val apUserService: APUserService) : UserAPCon override suspend fun userAp(username: String): ResponseEntity { val person = try { apUserService.getPersonByName(username) - } catch (_: FailedToGetResourcesException) { + } catch (_: UserNotFoundException) { return ResponseEntity.notFound().build() } person.context += listOf("https://www.w3.org/ns/activitystreams") diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/webfinger/WebFingerController.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/webfinger/WebFingerController.kt index 3a7bfdd8..39665c71 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/webfinger/WebFingerController.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/webfinger/WebFingerController.kt @@ -3,7 +3,7 @@ package dev.usbharu.hideout.activitypub.interfaces.api.webfinger import dev.usbharu.hideout.activitypub.domain.model.webfinger.WebFinger import dev.usbharu.hideout.activitypub.service.webfinger.WebFingerApiService import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.util.AcctUtil import kotlinx.coroutines.runBlocking import org.slf4j.LoggerFactory @@ -29,7 +29,7 @@ class WebFingerController( } val user = try { webFingerApiService.findByNameAndDomain(acct.username, acct.domain ?: applicationConfig.url.host) - } catch (_: FailedToGetResourcesException) { + } catch (_: UserNotFoundException) { return@runBlocking ResponseEntity.notFound().build() } val webFinger = WebFinger( diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/query/NoteQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/query/NoteQueryService.kt index f61b6992..4c57168c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/query/NoteQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/query/NoteQueryService.kt @@ -4,6 +4,6 @@ import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.core.domain.model.post.Post interface NoteQueryService { - suspend fun findById(id: Long): Pair - suspend fun findByApid(apId: String): Pair + suspend fun findById(id: Long): Pair? + suspend fun findByApid(apId: String): Pair? } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt index 7f6ea823..500a7c76 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import dev.usbharu.hideout.activitypub.domain.model.Create import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.application.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.exception.resource.PostNotFoundException import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post @@ -31,7 +32,7 @@ class ApSendCreateServiceImpl( logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.") val userEntity = actorRepository.findById(post.actorId) ?: throw UserNotFoundException.withId(post.actorId) - val note = noteQueryService.findById(post.id).first + val note = noteQueryService.findById(post.id)?.first ?: throw PostNotFoundException.withId(post.id) val create = Create( name = "Create Note", apObject = note, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt index f56f6018..8a3559d8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt @@ -8,9 +8,8 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.actor.ActorRepository -import dev.usbharu.hideout.core.query.PostQueryService +import dev.usbharu.hideout.core.domain.model.post.PostRepository import dev.usbharu.hideout.core.service.post.PostService import dev.usbharu.hideout.core.service.user.UserService import org.springframework.stereotype.Service @@ -18,10 +17,10 @@ import org.springframework.stereotype.Service @Service class APDeleteProcessor( transaction: Transaction, - private val postQueryService: PostQueryService, private val userService: UserService, private val postService: PostService, - private val actorRepository: ActorRepository + private val actorRepository: ActorRepository, + private val postRepository: PostRepository ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { @@ -38,12 +37,13 @@ class APDeleteProcessor( actor?.let { userService.deleteRemoteActor(it.id) } - try { - val post = postQueryService.findByApId(deleteId) - postService.deleteRemote(post) - } catch (e: FailedToGetResourcesException) { - logger.warn("FAILED delete id: {} is not found.", deleteId, e) + val post = postRepository.findByApId(deleteId) + if (post == null) { + logger.warn("FAILED Delete id: {} is not found.", deleteId) + return } + postService.deleteRemote(post) + } override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Delete diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APLikeProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APLikeProcessor.kt index ffa775e4..8ac309ed 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APLikeProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APLikeProcessor.kt @@ -8,7 +8,6 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.objects.note.APNoteService import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.reaction.ReactionService import org.springframework.stereotype.Service @@ -17,7 +16,6 @@ class APLikeProcessor( transaction: Transaction, private val apUserService: APUserService, private val apNoteService: APNoteService, - private val postQueryService: PostQueryService, private val reactionService: ReactionService ) : AbstractActivityPubProcessor(transaction) { @@ -30,23 +28,21 @@ class APLikeProcessor( val personWithEntity = apUserService.fetchPersonWithEntity(actor) try { - apNoteService.fetchNote(target) + val post = apNoteService.fetchNoteWithEntity(target).second + reactionService.receiveReaction( + content, + actor.substringAfter("://").substringBefore("/"), + personWithEntity.second.id, + post.id + ) + + logger.debug("SUCCESS Add Like($content) from ${personWithEntity.second.url} to ${post.url}") } catch (e: FailedToGetActivityPubResourceException) { logger.debug("FAILED failed to get {}", target) logger.trace("", e) return } - val post = postQueryService.findByUrl(target) - - reactionService.receiveReaction( - content, - actor.substringAfter("://").substringBefore("/"), - personWithEntity.second.id, - post.id - ) - - logger.debug("SUCCESS Add Like($content) from ${personWithEntity.second.url} to ${post.url}") } override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Like diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt index 94f67a4f..7e29a1e4 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt @@ -1,6 +1,7 @@ package dev.usbharu.hideout.activitypub.service.activity.like import com.fasterxml.jackson.databind.ObjectMapper +import dev.usbharu.hideout.core.domain.exception.resource.PostNotFoundException import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.reaction.Reaction @@ -29,7 +30,7 @@ class APReactionServiceImpl( val followers = followerQueryService.findFollowersById(like.actorId) val user = actorRepository.findById(like.actorId) ?: throw UserNotFoundException.withId(like.actorId) val post = - postQueryService.findById(like.postId) + postQueryService.findById(like.postId) ?: throw PostNotFoundException.withId(like.postId) followers.forEach { follower -> jobQueueParentService.schedule(DeliverReactionJob) { props[DeliverReactionJob.actor] = user.url @@ -45,7 +46,7 @@ class APReactionServiceImpl( val followers = followerQueryService.findFollowersById(like.actorId) val user = actorRepository.findById(like.actorId) ?: throw UserNotFoundException.withId(like.actorId) val post = - postQueryService.findById(like.postId) + postQueryService.findById(like.postId) ?: throw PostNotFoundException.withId(like.postId) followers.forEach { follower -> jobQueueParentService.schedule(DeliverRemoveReactionJob) { props[DeliverRemoveReactionJob.actor] = user.url diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt index afd9a721..84eed5fa 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt @@ -7,6 +7,7 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.exception.resource.PostNotFoundException import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.exception.resource.local.LocalUserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.ActorRepository @@ -79,7 +80,8 @@ class APUndoProcessor( "Like" -> { val like = undo.apObject as Like - val post = postQueryService.findByUrl(like.apObject) + val post = + postQueryService.findByUrl(like.apObject) ?: throw PostNotFoundException.withUrl(like.apObject) val signer = actorRepository.findById(post.actorId) ?: throw LocalUserNotFoundException.withId(post.actorId) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt index 48537741..18a32185 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt @@ -6,7 +6,6 @@ import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService import dev.usbharu.hideout.activitypub.service.common.resolve import dev.usbharu.hideout.activitypub.service.objects.user.APUserService -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository import dev.usbharu.hideout.core.domain.model.post.Visibility @@ -20,8 +19,9 @@ import org.springframework.stereotype.Service import java.time.Instant interface APNoteService { - suspend fun fetchNote(url: String, targetActor: String? = null): Note + suspend fun fetchNote(url: String, targetActor: String? = null): Note = fetchNoteWithEntity(url, targetActor).first suspend fun fetchNote(note: Note, targetActor: String? = null): Note + suspend fun fetchNoteWithEntity(url: String, targetActor: String? = null): Pair } @Service @@ -40,13 +40,14 @@ class APNoteServiceImpl( private val logger = LoggerFactory.getLogger(APNoteServiceImpl::class.java) - override suspend fun fetchNote(url: String, targetActor: String?): Note { + override suspend fun fetchNoteWithEntity(url: String, targetActor: String?): Pair { logger.debug("START Fetch Note url: {}", url) - try { - val post = noteQueryService.findByApid(url) + + val post = noteQueryService.findByApid(url) + + if (post != null) { logger.debug("SUCCESS Found in local url: {}", url) - return post.first - } catch (_: FailedToGetResourcesException) { + return post } logger.info("AP GET url: {}", url) @@ -54,9 +55,7 @@ class APNoteServiceImpl( apResourceResolveService.resolve(url, null as Long?) } catch (e: ClientRequestException) { logger.warn( - "FAILED Failed to retrieve ActivityPub resource. HTTP Status Code: {} url: {}", - e.response.status, - url + "FAILED Failed to retrieve ActivityPub resource. HTTP Status Code: {} url: {}", e.response.status, url ) throw FailedToGetActivityPubResourceException("Could not retrieve $url.", e) } @@ -66,45 +65,33 @@ class APNoteServiceImpl( } private suspend fun saveIfMissing( - note: Note, - targetActor: String?, - url: String - ): Note { - requireNotNull(note.id) { "id is null" } - - - - return try { - noteQueryService.findByApid(note.id).first - } catch (e: FailedToGetResourcesException) { - saveNote(note, targetActor, url) - } - - + note: Note, targetActor: String?, url: String + ): Pair { + return noteQueryService.findByApid(note.id) ?: saveNote(note, targetActor, url) } - private suspend fun saveNote(note: Note, targetActor: String?, url: String): Note { + private suspend fun saveNote(note: Note, targetActor: String?, url: String): Pair { val person = apUserService.fetchPersonWithEntity( - note.attributedTo, - targetActor + note.attributedTo, targetActor ) - if (postRepository.existByApIdWithLock(note.id)) { - return note + val post = postRepository.findByApId(note.id) + + if (post != null) { + return note to post } logger.debug("VISIBILITY url: {} to: {} cc: {}", note.id, note.to, note.cc) - val visibility = - if (note.to.contains(public)) { - Visibility.PUBLIC - } else if (note.to.contains(person.second.followers) && note.cc.contains(public)) { - Visibility.UNLISTED - } else if (note.to.contains(person.second.followers)) { - Visibility.FOLLOWERS - } else { - Visibility.DIRECT - } + val visibility = if (note.to.contains(public)) { + Visibility.PUBLIC + } else if (note.to.contains(person.second.followers) && note.cc.contains(public)) { + Visibility.UNLISTED + } else if (note.to.contains(person.second.followers)) { + Visibility.FOLLOWERS + } else { + Visibility.DIRECT + } logger.debug("VISIBILITY is {} url: {}", visibility.name, note.id) @@ -113,22 +100,15 @@ class APNoteServiceImpl( postQueryService.findByUrl(it) } - val mediaList = note.attachment - .filter { it.url != null } - .map { - mediaService.uploadRemoteMedia( - RemoteMedia( - it.name, - it.url, - it.mediaType, - description = it.name - ) + val mediaList = note.attachment.map { + mediaService.uploadRemoteMedia( + RemoteMedia( + it.name, it.url, it.mediaType, description = it.name ) - } - .map { it.id } + ) + }.map { it.id } - // TODO: リモートのメディア処理を追加 - postService.createRemote( + val createRemote = postService.createRemote( postBuilder.of( id = postRepository.generateId(), actorId = person.second.id, @@ -142,11 +122,11 @@ class APNoteServiceImpl( mediaIds = mediaList ) ) - return note + return note to createRemote } override suspend fun fetchNote(note: Note, targetActor: String?): Note = - saveIfMissing(note, targetActor, note.id) + saveIfMissing(note, targetActor, note.id).first companion object { const val public: String = "https://www.w3.org/ns/activitystreams#Public" diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt index 4420ceb0..e6dc9ca0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt @@ -3,7 +3,6 @@ package dev.usbharu.hideout.activitypub.service.objects.note import dev.usbharu.hideout.activitypub.domain.model.Note import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.query.FollowerQueryService @@ -17,12 +16,13 @@ class NoteApApiServiceImpl( private val transaction: Transaction ) : NoteApApiService { override suspend fun getNote(postId: Long, userId: Long?): Note? = transaction.transaction { - val findById = try { - noteQueryService.findById(postId) - } catch (e: FailedToGetResourcesException) { - logger.warn("Note not found.", e) + val findById = noteQueryService.findById(postId) + + if (findById == null) { + logger.warn("Note not found. $postId $userId") return@transaction null } + when (findById.second.visibility) { Visibility.PUBLIC, Visibility.UNLISTED -> { return@transaction findById.first diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/PostNotFoundException.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/PostNotFoundException.kt index f66c41d8..cae271aa 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/PostNotFoundException.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/PostNotFoundException.kt @@ -19,5 +19,9 @@ class PostNotFoundException : NotFoundException { private const val serialVersionUID: Long = 1315818410686905717L fun withApId(apId: String): PostNotFoundException = PostNotFoundException("apId: $apId was not found.") + + fun withId(id: Long): PostNotFoundException = PostNotFoundException("id: $id was not found.") + + fun withUrl(url: String): PostNotFoundException = PostNotFoundException("url: $url was not found.") } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/deletedActor/DeletedActorRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/deletedActor/DeletedActorRepository.kt index f2d18368..1c5a291e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/deletedActor/DeletedActorRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/deletedActor/DeletedActorRepository.kt @@ -3,5 +3,5 @@ package dev.usbharu.hideout.core.domain.model.deletedActor interface DeletedActorRepository { suspend fun save(deletedActor: DeletedActor): DeletedActor suspend fun delete(deletedActor: DeletedActor) - suspend fun findById(id: Long): DeletedActor + suspend fun findById(id: Long): DeletedActor? } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/InstanceRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/InstanceRepository.kt index 35b6026e..9883cb35 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/InstanceRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/instance/InstanceRepository.kt @@ -3,6 +3,6 @@ package dev.usbharu.hideout.core.domain.model.instance interface InstanceRepository { suspend fun generateId(): Long suspend fun save(instance: Instance): Instance - suspend fun findById(id: Long): Instance + suspend fun findById(id: Long): Instance? suspend fun delete(instance: Instance) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/media/MediaRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/media/MediaRepository.kt index 1e18f68b..b5e2abb2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/media/MediaRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/media/MediaRepository.kt @@ -3,6 +3,6 @@ package dev.usbharu.hideout.core.domain.model.media interface MediaRepository { suspend fun generateId(): Long suspend fun save(media: Media): Media - suspend fun findById(id: Long): Media + suspend fun findById(id: Long): Media? suspend fun delete(id: Long) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/DeletedActorQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/DeletedActorQueryServiceImpl.kt index f412b310..a5518867 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/DeletedActorQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/DeletedActorQueryServiceImpl.kt @@ -1,23 +1,19 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor import dev.usbharu.hideout.core.infrastructure.exposedrepository.DeletedActors import dev.usbharu.hideout.core.infrastructure.exposedrepository.toDeletedActor import dev.usbharu.hideout.core.query.DeletedActorQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @Repository class DeletedActorQueryServiceImpl : DeletedActorQueryService { - override suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor { + override suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor? { return DeletedActors .select { DeletedActors.name eq name and (DeletedActors.domain eq domain) } - .singleOr { - FailedToGetResourcesException("name: $name domain: $domain was not exist or duplicate.", it) - } - .toDeletedActor() + .singleOrNull() + ?.toDeletedActor() } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/InstanceQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/InstanceQueryServiceImpl.kt index c7d276ef..9c518904 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/InstanceQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/InstanceQueryServiceImpl.kt @@ -1,16 +1,14 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.infrastructure.exposedrepository.Instance import dev.usbharu.hideout.core.infrastructure.exposedrepository.toInstance import dev.usbharu.hideout.core.query.InstanceQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository import dev.usbharu.hideout.core.domain.model.instance.Instance as InstanceEntity @Repository class InstanceQueryServiceImpl : InstanceQueryService { - override suspend fun findByUrl(url: String): InstanceEntity = Instance.select { Instance.url eq url } - .singleOr { FailedToGetResourcesException("$url is doesn't exist", it) }.toInstance() + override suspend fun findByUrl(url: String): InstanceEntity? = Instance.select { Instance.url eq url } + .singleOrNull()?.toInstance() } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/MediaQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/MediaQueryServiceImpl.kt index df87d4c9..f4b777aa 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/MediaQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/MediaQueryServiceImpl.kt @@ -1,11 +1,9 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.infrastructure.exposedrepository.Media import dev.usbharu.hideout.core.infrastructure.exposedrepository.PostsMedia import dev.usbharu.hideout.core.infrastructure.exposedrepository.toMedia import dev.usbharu.hideout.core.query.MediaQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.innerJoin import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @@ -23,9 +21,9 @@ class MediaQueryServiceImpl : MediaQueryService { .map { it.toMedia() } } - override suspend fun findByRemoteUrl(remoteUrl: String): MediaEntity { + override suspend fun findByRemoteUrl(remoteUrl: String): MediaEntity? { return Media.select { Media.remoteUrl eq remoteUrl }.forUpdate() - .singleOr { FailedToGetResourcesException("remoteUrl: $remoteUrl is duplicate or not exist.", it) } - .toMedia() + .singleOrNull() + ?.toMedia() } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/PostQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/PostQueryServiceImpl.kt index 65d8d492..c69027e9 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/PostQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/PostQueryServiceImpl.kt @@ -2,12 +2,10 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.infrastructure.exposedrepository.Posts import dev.usbharu.hideout.core.infrastructure.exposedrepository.PostsMedia import dev.usbharu.hideout.core.query.PostQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @@ -16,23 +14,23 @@ class PostQueryServiceImpl( private val postResultRowMapper: ResultRowMapper, private val postQueryMapper: QueryMapper ) : PostQueryService { - override suspend fun findById(id: Long): Post = + override suspend fun findById(id: Long): Post? = Posts.leftJoin(PostsMedia) .select { Posts.id eq id } - .singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) } - .let(postResultRowMapper::map) + .singleOrNull() + ?.let(postResultRowMapper::map) - override suspend fun findByUrl(url: String): Post = + override suspend fun findByUrl(url: String): Post? = Posts.leftJoin(PostsMedia) .select { Posts.url eq url } .let(postQueryMapper::map) - .singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) } + .singleOrNull() - override suspend fun findByApId(string: String): Post = + override suspend fun findByApId(string: String): Post? = Posts.leftJoin(PostsMedia) .select { Posts.apId eq string } .let(postQueryMapper::map) - .singleOr { FailedToGetResourcesException("apId: $string is duplicate or does not exist.", it) } + .singleOrNull() override suspend fun findByActorId(actorId: Long): List = Posts.leftJoin(PostsMedia).select { Posts.actorId eq actorId }.let(postQueryMapper::map) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt index 8e51e2e6..349de146 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt @@ -1,11 +1,9 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.reaction.Reaction import dev.usbharu.hideout.core.infrastructure.exposedrepository.Reactions import dev.usbharu.hideout.core.infrastructure.exposedrepository.toReaction import dev.usbharu.hideout.core.query.ReactionQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @@ -19,20 +17,15 @@ class ReactionQueryServiceImpl : ReactionQueryService { } @Suppress("FunctionMaxLength") - override suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction { + override suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction? { return Reactions .select { Reactions.postId.eq(postId).and(Reactions.actorId.eq(actorId)).and( Reactions.emojiId.eq(emojiId) ) } - .singleOr { - FailedToGetResourcesException( - "postId: $postId,userId: $actorId,emojiId: $emojiId is duplicate or does not exist.", - it - ) - } - .toReaction() + .singleOrNull() + ?.toReaction() } override suspend fun reactionAlreadyExist(postId: Long, actorId: Long, emojiId: Long): Boolean { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/DeletedActorRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/DeletedActorRepositoryImpl.kt index 440c1a36..31246dbd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/DeletedActorRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/DeletedActorRepositoryImpl.kt @@ -1,18 +1,18 @@ package dev.usbharu.hideout.core.infrastructure.exposedrepository -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActorRepository -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.javatime.timestamp +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Repository @Repository -class DeletedActorRepositoryImpl : DeletedActorRepository { - override suspend fun save(deletedActor: DeletedActor): DeletedActor { - val singleOrNull = DeletedActors.select { DeletedActors.id eq deletedActor.id }.singleOrNull() +class DeletedActorRepositoryImpl : DeletedActorRepository, AbstractRepository() { + override suspend fun save(deletedActor: DeletedActor): DeletedActor = query { + val singleOrNull = DeletedActors.select { DeletedActors.id eq deletedActor.id }.forUpdate().singleOrNull() if (singleOrNull == null) { DeletedActors.insert { @@ -30,18 +30,24 @@ class DeletedActorRepositoryImpl : DeletedActorRepository { it[DeletedActors.deletedAt] = deletedActor.deletedAt } } - return deletedActor + return@query deletedActor } - override suspend fun delete(deletedActor: DeletedActor) { + override suspend fun delete(deletedActor: DeletedActor): Unit = query { DeletedActors.deleteWhere { DeletedActors.id eq deletedActor.id } } - override suspend fun findById(id: Long): DeletedActor { - val singleOr = DeletedActors.select { DeletedActors.id eq id } - .singleOr { FailedToGetResourcesException("id: $id was not exist or duplicate", it) } + override suspend fun findById(id: Long): DeletedActor? = query { + return@query DeletedActors.select { DeletedActors.id eq id } + .singleOrNull() + ?.let { it.toDeletedActor() } + } - return deletedActor(singleOr) + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(DeletedActorRepositoryImpl::class.java) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/InstanceRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/InstanceRepositoryImpl.kt index 883a5b48..41aa2535 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/InstanceRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/InstanceRepositoryImpl.kt @@ -1,9 +1,7 @@ package dev.usbharu.hideout.core.infrastructure.exposedrepository import dev.usbharu.hideout.application.service.id.IdGenerateService -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.javatime.timestamp @@ -48,9 +46,9 @@ class InstanceRepositoryImpl(private val idGenerateService: IdGenerateService) : return instance } - override suspend fun findById(id: Long): InstanceEntity { + override suspend fun findById(id: Long): InstanceEntity? { return Instance.select { Instance.id eq id } - .singleOr { FailedToGetResourcesException("id: $id doesn't exist.") }.toInstance() + .singleOrNull()?.toInstance() } override suspend fun delete(instance: InstanceEntity) { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt index 6e056286..3039dc77 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt @@ -1,12 +1,10 @@ package dev.usbharu.hideout.core.infrastructure.exposedrepository import dev.usbharu.hideout.application.service.id.IdGenerateService -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.media.MediaRepository import dev.usbharu.hideout.core.infrastructure.exposedrepository.Media.mimeType import dev.usbharu.hideout.core.service.media.FileType import dev.usbharu.hideout.core.service.media.MimeType -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.springframework.stereotype.Repository @@ -47,14 +45,13 @@ class MediaRepositoryImpl(private val idGenerateService: IdGenerateService) : Me return media } - override suspend fun findById(id: Long): EntityMedia { + override suspend fun findById(id: Long): EntityMedia? { return Media .select { Media.id eq id } - .singleOr { - FailedToGetResourcesException("id: $id was not found.") - }.toMedia() + .singleOrNull() + ?.toMedia() } override suspend fun delete(id: Long) { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/DeletedActorQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/DeletedActorQueryService.kt index de7fcc53..e7dd164d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/DeletedActorQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/DeletedActorQueryService.kt @@ -3,5 +3,5 @@ package dev.usbharu.hideout.core.query import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor interface DeletedActorQueryService { - suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor + suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor? } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/InstanceQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/InstanceQueryService.kt index 79e6b213..b735273b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/InstanceQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/InstanceQueryService.kt @@ -3,5 +3,5 @@ package dev.usbharu.hideout.core.query import dev.usbharu.hideout.core.domain.model.instance.Instance interface InstanceQueryService { - suspend fun findByUrl(url: String): Instance + suspend fun findByUrl(url: String): Instance? } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/MediaQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/MediaQueryService.kt index 876c2f1e..1a0e5e2b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/MediaQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/MediaQueryService.kt @@ -4,5 +4,5 @@ import dev.usbharu.hideout.core.domain.model.media.Media interface MediaQueryService { suspend fun findByPostId(postId: Long): List - suspend fun findByRemoteUrl(remoteUrl: String): Media + suspend fun findByRemoteUrl(remoteUrl: String): Media? } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/PostQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/PostQueryService.kt index 64999e89..dcf7d6b1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/PostQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/PostQueryService.kt @@ -5,8 +5,8 @@ import org.springframework.stereotype.Repository @Repository interface PostQueryService { - suspend fun findById(id: Long): Post - suspend fun findByUrl(url: String): Post - suspend fun findByApId(string: String): Post + suspend fun findById(id: Long): Post? + suspend fun findByUrl(url: String): Post? + suspend fun findByApId(string: String): Post? suspend fun findByActorId(actorId: Long): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt index ece7b040..091af139 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt @@ -8,7 +8,7 @@ interface ReactionQueryService { suspend fun findByPostId(postId: Long, actorId: Long? = null): List @Suppress("FunctionMaxLength") - suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction + suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction? suspend fun reactionAlreadyExist(postId: Long, actorId: Long, emojiId: Long): Boolean 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 d06e53ad..a3e4cecb 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,7 +1,6 @@ package dev.usbharu.hideout.core.service.instance import com.fasterxml.jackson.databind.ObjectMapper -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException 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 @@ -30,13 +29,14 @@ class InstanceServiceImpl( val u = URL(url) val resolveInstanceUrl = u.protocol + "://" + u.host - try { - return instanceQueryService.findByUrl(resolveInstanceUrl) - } catch (e: FailedToGetResourcesException) { - logger.info("Instance not found. try fetch instance info. url: {}", resolveInstanceUrl) - logger.debug("Failed to get resources. url: {}", resolveInstanceUrl, e) + val instance = instanceQueryService.findByUrl(resolveInstanceUrl) + + if (instance != null) { + return instance } + logger.info("Instance not found. try fetch instance info. url: {}", resolveInstanceUrl) + val nodeinfoJson = resourceResolveService.resolve("$resolveInstanceUrl/.well-known/nodeinfo").bodyAsText() val nodeinfo = objectMapper.readValue(nodeinfoJson, Nodeinfo::class.java) val nodeinfoPathMap = nodeinfo.links.associate { it.rel to it.href } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/media/MediaServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/media/MediaServiceImpl.kt index 80d26318..cf6a1113 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/media/MediaServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/media/MediaServiceImpl.kt @@ -1,6 +1,5 @@ package dev.usbharu.hideout.core.service.media -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.exception.media.MediaSaveException import dev.usbharu.hideout.core.domain.exception.media.UnsupportedMediaException import dev.usbharu.hideout.core.domain.model.media.Media @@ -102,11 +101,11 @@ class MediaServiceImpl( override suspend fun uploadRemoteMedia(remoteMedia: RemoteMedia): Media { logger.info("MEDIA Remote media. filename:${remoteMedia.name} url:${remoteMedia.url}") - try { - val findByRemoteUrl = mediaQueryService.findByRemoteUrl(remoteMedia.url) + + val findByRemoteUrl = mediaQueryService.findByRemoteUrl(remoteMedia.url) + if (findByRemoteUrl != null) { logger.warn("DUPLICATED Remote media is duplicated. url: {}", remoteMedia.url) return findByRemoteUrl - } catch (_: FailedToGetResourcesException) { } remoteMediaDownloadService.download(remoteMedia.url).withDelete().use { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt index 0323dc97..a49099bf 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt @@ -1,7 +1,6 @@ package dev.usbharu.hideout.core.service.reaction import dev.usbharu.hideout.activitypub.service.activity.like.APReactionService -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.reaction.Reaction import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository import dev.usbharu.hideout.core.query.ReactionQueryService @@ -29,30 +28,38 @@ class ReactionServiceImpl( override suspend fun receiveRemoveReaction(actorId: Long, postId: Long) { val reaction = reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) + if (reaction == null) { + LOGGER.warn("FAILED receive Remove Reaction. $actorId $postId") + return + } reactionRepository.delete(reaction) } override suspend fun sendReaction(name: String, actorId: Long, postId: Long) { - try { - val findByPostIdAndUserIdAndEmojiId = - reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) - apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) - reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) - } catch (_: FailedToGetResourcesException) { + val findByPostIdAndUserIdAndEmojiId = + reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) + + if (findByPostIdAndUserIdAndEmojiId == null) { + LOGGER.warn("FAILED Send reaction. $postId $actorId") + return } + + apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) + reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) val reaction = Reaction(reactionRepository.generateId(), 0, postId, actorId) reactionRepository.save(reaction) apReactionService.reaction(reaction) } override suspend fun removeReaction(actorId: Long, postId: Long) { - try { - val findByPostIdAndUserIdAndEmojiId = - reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) - reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) - apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) - } catch (_: FailedToGetResourcesException) { + val findByPostIdAndUserIdAndEmojiId = + reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) + if (findByPostIdAndUserIdAndEmojiId == null) { + LOGGER.warn("FAILED Remove reaction. actorId: $actorId postId: $postId") + return } + reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) + apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) } companion object { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt index f51f5485..6e97f028 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt @@ -2,7 +2,6 @@ package dev.usbharu.hideout.core.service.user import dev.usbharu.hideout.activitypub.service.activity.delete.APSendDeleteService import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.exception.resource.DuplicateException import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor @@ -74,11 +73,11 @@ class UserServiceImpl( override suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor { logger.info("START Create New remote user. name: {} url: {}", user.name, user.url) - try { - deletedActorQueryService.findByNameAndDomain(user.name, user.domain) + val deletedActor = deletedActorQueryService.findByNameAndDomain(user.name, user.domain) + + if (deletedActor != null) { logger.warn("FAILED Deleted actor. user: ${user.name} domain: ${user.domain}") throw IllegalStateException("Cannot create Deleted actor.") - } catch (_: FailedToGetResourcesException) { } @Suppress("TooGenericExceptionCaught") diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt index 92f38f09..4cd4ed55 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt @@ -1,11 +1,9 @@ package dev.usbharu.hideout.mastodon.infrastructure.exposedquery import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors import dev.usbharu.hideout.domain.mastodon.model.generated.Account import dev.usbharu.hideout.mastodon.query.AccountQueryService -import dev.usbharu.hideout.util.singleOr import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @@ -13,12 +11,12 @@ import java.time.Instant @Repository class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) : AccountQueryService { - override suspend fun findById(accountId: Long): Account { + override suspend fun findById(accountId: Long): Account? { val query = Actors.select { Actors.id eq accountId } return query - .singleOr { FailedToGetResourcesException("accountId: $accountId wad not exist or duplicate", it) } - .let { toAccount(it) } + .singleOrNull() + ?.let { toAccount(it) } } override suspend fun findByIds(accountIds: List): List { diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt index 37eb2d98..eab3b746 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt @@ -3,6 +3,6 @@ package dev.usbharu.hideout.mastodon.query import dev.usbharu.hideout.domain.mastodon.model.generated.Account interface AccountQueryService { - suspend fun findById(accountId: Long): Account + suspend fun findById(accountId: Long): Account? suspend fun findByIds(accountIds: List): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt index b3f57aaf..09b55cbd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt @@ -14,7 +14,8 @@ interface AccountService { class AccountServiceImpl( private val accountQueryService: AccountQueryService ) : AccountService { - override suspend fun findById(id: Long): Account = accountQueryService.findById(id) + override suspend fun findById(id: Long): Account = + accountQueryService.findById(id) ?: throw IllegalArgumentException("Account $id not found.") override suspend fun findByIds(ids: List): List = accountQueryService.findByIds(ids) } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt index 53c4326b..ac5a150d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt @@ -53,13 +53,19 @@ class StatsesApiServiceImpl( val account = accountService.findById(userId) val replyUser = if (post.replyId != null) { - actorRepository.findById(postQueryService.findById(post.replyId).actorId)?.id + val findById = postQueryService.findById(post.replyId) + if (findById == null) { + null + } else { + actorRepository.findById(findById.actorId)?.id + } + } else { null } // TODO: n+1解消 - val mediaAttachment = post.mediaIds.map { mediaId -> + val mediaAttachment = post.mediaIds.mapNotNull { mediaId -> mediaRepository.findById(mediaId) }.map { it.toMediaAttachments()