diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt index 8dea030a..ab4278de 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt @@ -1,20 +1,23 @@ package dev.usbharu.hideout.core.domain.model.relationship +import dev.usbharu.hideout.core.infrastructure.exposedrepository.AbstractRepository import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors import org.jetbrains.exposed.dao.id.LongIdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service -class RelationshipRepositoryImpl : RelationshipRepository { - override suspend fun save(relationship: Relationship): Relationship { +class RelationshipRepositoryImpl : RelationshipRepository, AbstractRepository() { + override suspend fun save(relationship: Relationship): Relationship = query { val singleOrNull = Relationships .select { (Relationships.actorId eq relationship.actorId) .and(Relationships.targetActorId eq relationship.targetActorId) - } + }.forUpdate() .singleOrNull() if (singleOrNull == null) { @@ -40,32 +43,32 @@ class RelationshipRepositoryImpl : RelationshipRepository { it[ignoreFollowRequestFromTarget] = relationship.ignoreFollowRequestToTarget } } - return relationship + return@query relationship } - override suspend fun delete(relationship: Relationship) { + override suspend fun delete(relationship: Relationship): Unit = query { Relationships.deleteWhere { (Relationships.actorId eq relationship.actorId) .and(Relationships.targetActorId eq relationship.targetActorId) } } - override suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? { - return Relationships.select { + override suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? = query { + return@query Relationships.select { (Relationships.actorId eq actorId) .and(Relationships.targetActorId eq targetActorId) }.singleOrNull() ?.toRelationships() } - override suspend fun deleteByActorIdOrTargetActorId(actorId: Long, targetActorId: Long) { + override suspend fun deleteByActorIdOrTargetActorId(actorId: Long, targetActorId: Long): Unit = query { Relationships.deleteWhere { Relationships.actorId.eq(actorId).or(Relationships.targetActorId.eq(targetActorId)) } } - override suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List { - return Relationships.select { Relationships.targetActorId eq targetId and (Relationships.following eq following) } + override suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List = query { + return@query Relationships.select { Relationships.targetActorId eq targetId and (Relationships.following eq following) } .map { it.toRelationships() } } @@ -76,7 +79,7 @@ class RelationshipRepositoryImpl : RelationshipRepository { targetId: Long, followRequest: Boolean, ignoreFollowRequest: Boolean - ): List { + ): List = query { val query = Relationships.select { Relationships.targetActorId.eq(targetId) .and(Relationships.followRequest.eq(followRequest)) @@ -91,7 +94,14 @@ class RelationshipRepositoryImpl : RelationshipRepository { query.andWhere { Relationships.id greaterEq sinceId } } - return query.map { it.toRelationships() } + return@query query.map { it.toRelationships() } + } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(RelationshipRepositoryImpl::class.java) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt index f8b36460..e90a63e0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt @@ -5,6 +5,8 @@ import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.timeline.Timeline import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository import org.jetbrains.exposed.sql.* +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.stereotype.Repository @@ -12,11 +14,12 @@ import org.springframework.stereotype.Repository @Repository @Qualifier("jdbc") @ConditionalOnProperty("hideout.use-mongodb", havingValue = "false", matchIfMissing = true) -class ExposedTimelineRepository(private val idGenerateService: IdGenerateService) : TimelineRepository { +class ExposedTimelineRepository(private val idGenerateService: IdGenerateService) : TimelineRepository, + AbstractRepository() { override suspend fun generateId(): Long = idGenerateService.generateId() - override suspend fun save(timeline: Timeline): Timeline { - if (Timelines.select { Timelines.id eq timeline.id }.singleOrNull() == null) { + override suspend fun save(timeline: Timeline): Timeline = query { + if (Timelines.select { Timelines.id eq timeline.id }.forUpdate().singleOrNull() == null) { Timelines.insert { it[id] = timeline.id it[userId] = timeline.userId @@ -48,10 +51,10 @@ class ExposedTimelineRepository(private val idGenerateService: IdGenerateService it[mediaIds] = timeline.mediaIds.joinToString(",") } } - return timeline + return@query timeline } - override suspend fun saveAll(timelines: List): List { + override suspend fun saveAll(timelines: List): List = query { Timelines.batchInsert(timelines, true, false) { this[Timelines.id] = it.id this[Timelines.userId] = it.userId @@ -67,20 +70,28 @@ class ExposedTimelineRepository(private val idGenerateService: IdGenerateService this[Timelines.isPureRepost] = it.isPureRepost this[Timelines.mediaIds] = it.mediaIds.joinToString(",") } - return timelines + return@query timelines } - override suspend fun findByUserId(id: Long): List = - Timelines.select { Timelines.userId eq id }.map { it.toTimeline() } + override suspend fun findByUserId(id: Long): List = query { + return@query Timelines.select { Timelines.userId eq id }.map { it.toTimeline() } + } - override suspend fun findByUserIdAndTimelineId(userId: Long, timelineId: Long): List = - Timelines.select { Timelines.userId eq userId and (Timelines.timelineId eq timelineId) } + override suspend fun findByUserIdAndTimelineId(userId: Long, timelineId: Long): List = query { + return@query Timelines.select { Timelines.userId eq userId and (Timelines.timelineId eq timelineId) } .map { it.toTimeline() } + } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(ExposedTimelineRepository::class.java) + } } fun ResultRow.toTimeline(): Timeline { - return Timeline( - id = this[Timelines.id], + return Timeline(id = this[Timelines.id], userId = this[Timelines.userId], timelineId = this[Timelines.timelineId], postId = this[Timelines.postId], @@ -92,8 +103,7 @@ fun ResultRow.toTimeline(): Timeline { sensitive = this[Timelines.sensitive], isLocal = this[Timelines.isLocal], isPureRepost = this[Timelines.isPureRepost], - mediaIds = this[Timelines.mediaIds].split(",").mapNotNull { it.toLongOrNull() } - ) + mediaIds = this[Timelines.mediaIds].split(",").mapNotNull { it.toLongOrNull() }) } object Timelines : Table("timelines") { 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 e375dfe8..2a49c939 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 @@ -5,15 +5,18 @@ import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository 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 import dev.usbharu.hideout.core.domain.model.instance.Instance as InstanceEntity @Repository -class InstanceRepositoryImpl(private val idGenerateService: IdGenerateService) : InstanceRepository { +class InstanceRepositoryImpl(private val idGenerateService: IdGenerateService) : InstanceRepository, + AbstractRepository() { override suspend fun generateId(): Long = idGenerateService.generateId() - override suspend fun save(instance: InstanceEntity): InstanceEntity { - if (Instance.select { Instance.id.eq(instance.id) }.empty()) { + override suspend fun save(instance: InstanceEntity): InstanceEntity = query { + if (Instance.select { Instance.id.eq(instance.id) }.forUpdate().empty()) { Instance.insert { it[id] = instance.id it[name] = instance.name @@ -43,20 +46,27 @@ class InstanceRepositoryImpl(private val idGenerateService: IdGenerateService) : it[createdAt] = instance.createdAt } } - return instance + return@query instance } - override suspend fun findById(id: Long): InstanceEntity? { - return Instance.select { Instance.id eq id } + override suspend fun findById(id: Long): InstanceEntity? = query { + return@query Instance.select { Instance.id eq id } .singleOrNull()?.toInstance() } - override suspend fun delete(instance: InstanceEntity) { + override suspend fun delete(instance: InstanceEntity): Unit = query { Instance.deleteWhere { id eq instance.id } } - override suspend fun findByUrl(url: String): dev.usbharu.hideout.core.domain.model.instance.Instance? { - return Instance.select { Instance.url eq url }.singleOrNull()?.toInstance() + override suspend fun findByUrl(url: String): dev.usbharu.hideout.core.domain.model.instance.Instance? = query { + return@query Instance.select { Instance.url eq url }.singleOrNull()?.toInstance() + } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(InstanceRepositoryImpl::class.java) } } 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 19012f6c..979c4a76 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 @@ -7,14 +7,16 @@ import dev.usbharu.hideout.core.service.media.FileType import dev.usbharu.hideout.core.service.media.MimeType import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Repository import dev.usbharu.hideout.core.domain.model.media.Media as EntityMedia @Repository -class MediaRepositoryImpl(private val idGenerateService: IdGenerateService) : MediaRepository { +class MediaRepositoryImpl(private val idGenerateService: IdGenerateService) : MediaRepository, AbstractRepository() { override suspend fun generateId(): Long = idGenerateService.generateId() - override suspend fun save(media: EntityMedia): EntityMedia { + override suspend fun save(media: EntityMedia): EntityMedia = query { if (Media.select { Media.id eq media.id }.forUpdate().singleOrNull() != null @@ -42,11 +44,11 @@ class MediaRepositoryImpl(private val idGenerateService: IdGenerateService) : Me it[description] = media.description } } - return media + return@query media } - override suspend fun findById(id: Long): EntityMedia? { - return Media + override suspend fun findById(id: Long): EntityMedia? = query { + return@query Media .select { Media.id eq id } @@ -54,14 +56,22 @@ class MediaRepositoryImpl(private val idGenerateService: IdGenerateService) : Me ?.toMedia() } - override suspend fun delete(id: Long) { + override suspend fun delete(id: Long): Unit = query { Media.deleteWhere { Media.id eq id } } - override suspend fun findByRemoteUrl(remoteUrl: String): dev.usbharu.hideout.core.domain.model.media.Media? { - return Media.select { Media.remoteUrl eq remoteUrl }.singleOrNull()?.toMedia() + override suspend fun findByRemoteUrl(remoteUrl: String): dev.usbharu.hideout.core.domain.model.media.Media? = + query { + return@query Media.select { Media.remoteUrl eq remoteUrl }.singleOrNull()?.toMedia() + } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(MediaRepositoryImpl::class.java) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt index d39f996d..e1ead404 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt @@ -6,17 +6,19 @@ import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository import org.jetbrains.exposed.dao.id.LongIdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Repository @Repository class ReactionRepositoryImpl( private val idGenerateService: IdGenerateService -) : ReactionRepository { +) : ReactionRepository, AbstractRepository() { override suspend fun generateId(): Long = idGenerateService.generateId() - override suspend fun save(reaction: Reaction): Reaction { - if (Reactions.select { Reactions.id eq reaction.id }.empty()) { + override suspend fun save(reaction: Reaction): Reaction = query { + if (Reactions.select { Reactions.id eq reaction.id }.forUpdate().empty()) { Reactions.insert { it[id] = reaction.id it[emojiId] = reaction.emojiId @@ -30,69 +32,79 @@ class ReactionRepositoryImpl( it[actorId] = reaction.actorId } } - return reaction + return@query reaction } - override suspend fun delete(reaction: Reaction): Reaction { + override suspend fun delete(reaction: Reaction): Reaction = query { Reactions.deleteWhere { - id.eq(reaction.id) - .and(postId.eq(reaction.postId)) - .and(actorId.eq(reaction.actorId)) + id.eq(reaction.id).and(postId.eq(reaction.postId)).and(actorId.eq(reaction.actorId)) .and(emojiId.eq(reaction.emojiId)) } - return reaction + return@query reaction } - override suspend fun deleteByPostId(postId: Long): Int { - return Reactions.deleteWhere { + override suspend fun deleteByPostId(postId: Long): Int = query { + return@query Reactions.deleteWhere { Reactions.postId eq postId } } - override suspend fun deleteByActorId(actorId: Long): Int { - return Reactions.deleteWhere { + override suspend fun deleteByActorId(actorId: Long): Int = query { + return@query Reactions.deleteWhere { Reactions.actorId eq actorId } } - override suspend fun findByPostId(postId: Long): List { - return Reactions.select { Reactions.postId eq postId }.map { it.toReaction() } + override suspend fun findByPostId(postId: Long): List = query { + return@query Reactions.select { Reactions.postId eq postId }.map { it.toReaction() } } - 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 + override suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction? = + query { + return@query Reactions.select { + Reactions.postId eq postId and (Reactions.actorId eq actorId).and( + Reactions.emojiId.eq( + emojiId + ) ) - ) - }.singleOrNull()?.toReaction() + }.singleOrNull()?.toReaction() + } + + override suspend fun existByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Boolean = + query { + return@query Reactions.select { + Reactions.postId + .eq(postId) + .and(Reactions.actorId.eq(actorId)) + .and(Reactions.emojiId.eq(emojiId)) + }.empty().not() + } + + override suspend fun findByPostIdAndActorId(postId: Long, actorId: Long): List = query { + return@query Reactions.select { Reactions.postId eq postId and (Reactions.actorId eq actorId) } + .map { it.toReaction() } } - override suspend fun existByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Boolean { - TODO("Not yet implemented") - } + override val logger: Logger + get() = Companion.logger - override suspend fun findByPostIdAndActorId(postId: Long, actorId: Long): List { - TODO("Not yet implemented") + companion object { + private val logger = LoggerFactory.getLogger(ReactionRepositoryImpl::class.java) } } fun ResultRow.toReaction(): Reaction { return Reaction( - this[Reactions.id].value, - this[Reactions.emojiId], - this[Reactions.postId], - this[Reactions.actorId] + this[Reactions.id].value, this[Reactions.emojiId], this[Reactions.postId], this[Reactions.actorId] ) } object Reactions : LongIdTable("reactions") { val emojiId: Column = long("emoji_id") - val postId: Column = long("post_id") - .references(Posts.id, onDelete = ReferenceOption.CASCADE, onUpdate = ReferenceOption.CASCADE) - val actorId: Column = long("actor_id") - .references(Actors.id, onDelete = ReferenceOption.CASCADE, onUpdate = ReferenceOption.CASCADE) + val postId: Column = + long("post_id").references(Posts.id, onDelete = ReferenceOption.CASCADE, onUpdate = ReferenceOption.CASCADE) + val actorId: Column = + long("actor_id").references(Actors.id, onDelete = ReferenceOption.CASCADE, onUpdate = ReferenceOption.CASCADE) init { uniqueIndex(emojiId, postId, actorId) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt index 4fb7b9c5..b64008dd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt @@ -8,12 +8,14 @@ import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.update +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.stereotype.Repository @Repository -class UserDetailRepositoryImpl : UserDetailRepository { - override suspend fun save(userDetail: UserDetail): UserDetail { - val singleOrNull = UserDetails.select { UserDetails.actorId eq userDetail.actorId }.singleOrNull() +class UserDetailRepositoryImpl : UserDetailRepository, AbstractRepository() { + override suspend fun save(userDetail: UserDetail): UserDetail = query { + val singleOrNull = UserDetails.select { UserDetails.actorId eq userDetail.actorId }.forUpdate().singleOrNull() if (singleOrNull == null) { UserDetails.insert { it[actorId] = userDetail.actorId @@ -26,15 +28,15 @@ class UserDetailRepositoryImpl : UserDetailRepository { it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest } } - return userDetail + return@query userDetail } - override suspend fun delete(userDetail: UserDetail) { + override suspend fun delete(userDetail: UserDetail): Unit = query { UserDetails.deleteWhere { UserDetails.actorId eq userDetail.actorId } } - override suspend fun findByActorId(actorId: Long): UserDetail? { - return UserDetails + override suspend fun findByActorId(actorId: Long): UserDetail? = query { + return@query UserDetails .select { UserDetails.actorId eq actorId } .singleOrNull() ?.let { @@ -45,6 +47,13 @@ class UserDetailRepositoryImpl : UserDetailRepository { ) } } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(UserDetailRepositoryImpl::class.java) + } } object UserDetails : LongIdTable("user_details") {