refactor: 不要なメソッドを削除、FollowQueryServiceの実体をRelationshipQueryServiceに

This commit is contained in:
usbharu 2023-12-10 15:55:09 +09:00
parent 30b190584a
commit a011d22587
7 changed files with 21 additions and 271 deletions

View File

@ -9,14 +9,12 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityType
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.relationship.RelationshipService import dev.usbharu.hideout.core.service.relationship.RelationshipService
import dev.usbharu.hideout.core.service.user.UserService
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@Service @Service
class ApAcceptProcessor( class ApAcceptProcessor(
transaction: Transaction, transaction: Transaction,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val userService: UserService,
private val relationshipService: RelationshipService private val relationshipService: RelationshipService
) : ) :
AbstractActivityPubProcessor<Accept>(transaction) { AbstractActivityPubProcessor<Accept>(transaction) {

View File

@ -10,9 +10,5 @@ interface UserRepository {
suspend fun delete(id: Long) suspend fun delete(id: Long)
suspend fun deleteFollowRequest(id: Long, follower: Long)
suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean
suspend fun nextId(): Long suspend fun nextId(): Long
} }

View File

@ -1,242 +1,23 @@
package dev.usbharu.hideout.core.infrastructure.exposedquery package dev.usbharu.hideout.core.infrastructure.exposedquery
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
import dev.usbharu.hideout.core.domain.model.user.User import dev.usbharu.hideout.core.domain.model.user.User
import dev.usbharu.hideout.core.infrastructure.exposedrepository.Users
import dev.usbharu.hideout.core.infrastructure.exposedrepository.UsersFollowers
import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.FollowerQueryService
import org.jetbrains.exposed.sql.* import dev.usbharu.hideout.core.query.RelationshipQueryService
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import dev.usbharu.hideout.core.query.UserQueryService
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.time.Instant
@Repository @Repository
class FollowerQueryServiceImpl(private val userBuilder: User.UserBuilder) : FollowerQueryService { class FollowerQueryServiceImpl(
private val relationshipQueryService: RelationshipQueryService,
private val userQueryService: UserQueryService,
private val relationshipRepository: RelationshipRepository
) : FollowerQueryService {
override suspend fun findFollowersById(id: Long): List<User> { override suspend fun findFollowersById(id: Long): List<User> {
val followers = Users.alias("FOLLOWERS") return userQueryService.findByIds(
return Users.innerJoin( relationshipQueryService.findByTargetIdAndFollowing(id, true).map { it.userId })
otherTable = UsersFollowers,
onColumn = { Users.id },
otherColumn = { userId }
)
.innerJoin(
otherTable = followers,
onColumn = { UsersFollowers.followerId },
otherColumn = { followers[Users.id] }
)
.slice(
followers[Users.id],
followers[Users.name],
followers[Users.domain],
followers[Users.screenName],
followers[Users.description],
followers[Users.password],
followers[Users.inbox],
followers[Users.outbox],
followers[Users.url],
followers[Users.publicKey],
followers[Users.privateKey],
followers[Users.createdAt],
followers[Users.keyId],
followers[Users.following],
followers[Users.followers],
followers[Users.instance]
)
.select { Users.id eq id }
.map {
userBuilder.of(
id = it[followers[Users.id]],
name = it[followers[Users.name]],
domain = it[followers[Users.domain]],
screenName = it[followers[Users.screenName]],
description = it[followers[Users.description]],
password = it[followers[Users.password]],
inbox = it[followers[Users.inbox]],
outbox = it[followers[Users.outbox]],
url = it[followers[Users.url]],
publicKey = it[followers[Users.publicKey]],
privateKey = it[followers[Users.privateKey]],
createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]),
keyId = it[followers[Users.keyId]],
followers = it[followers[Users.followers]],
following = it[followers[Users.following]],
instance = it[followers[Users.instance]]
)
}
} }
override suspend fun findFollowersByNameAndDomain(name: String, domain: String): List<User> { override suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean =
val followers = Users.alias("FOLLOWERS") relationshipRepository.findByUserIdAndTargetUserId(followerId, userId)?.following ?: false
return Users.innerJoin(
otherTable = UsersFollowers,
onColumn = { id },
otherColumn = { userId }
)
.innerJoin(
otherTable = followers,
onColumn = { UsersFollowers.followerId },
otherColumn = { followers[Users.id] }
)
.slice(
followers[Users.id],
followers[Users.name],
followers[Users.domain],
followers[Users.screenName],
followers[Users.description],
followers[Users.password],
followers[Users.inbox],
followers[Users.outbox],
followers[Users.url],
followers[Users.publicKey],
followers[Users.privateKey],
followers[Users.createdAt],
followers[Users.keyId],
followers[Users.following],
followers[Users.followers],
followers[Users.instance]
)
.select { Users.name eq name and (Users.domain eq domain) }
.map {
userBuilder.of(
id = it[followers[Users.id]],
name = it[followers[Users.name]],
domain = it[followers[Users.domain]],
screenName = it[followers[Users.screenName]],
description = it[followers[Users.description]],
password = it[followers[Users.password]],
inbox = it[followers[Users.inbox]],
outbox = it[followers[Users.outbox]],
url = it[followers[Users.url]],
publicKey = it[followers[Users.publicKey]],
privateKey = it[followers[Users.privateKey]],
createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]),
keyId = it[followers[Users.keyId]],
followers = it[followers[Users.followers]],
following = it[followers[Users.following]],
instance = it[followers[Users.instance]]
)
}
}
override suspend fun findFollowingById(id: Long): List<User> {
val followers = Users.alias("FOLLOWERS")
return Users.innerJoin(
otherTable = UsersFollowers,
onColumn = { Users.id },
otherColumn = { userId }
)
.innerJoin(
otherTable = followers,
onColumn = { UsersFollowers.followerId },
otherColumn = { followers[Users.id] }
)
.slice(
followers[Users.id],
followers[Users.name],
followers[Users.domain],
followers[Users.screenName],
followers[Users.description],
followers[Users.password],
followers[Users.inbox],
followers[Users.outbox],
followers[Users.url],
followers[Users.publicKey],
followers[Users.privateKey],
followers[Users.createdAt],
followers[Users.keyId],
followers[Users.following],
followers[Users.followers],
followers[Users.instance]
)
.select { followers[Users.id] eq id }
.map {
userBuilder.of(
id = it[followers[Users.id]],
name = it[followers[Users.name]],
domain = it[followers[Users.domain]],
screenName = it[followers[Users.screenName]],
description = it[followers[Users.description]],
password = it[followers[Users.password]],
inbox = it[followers[Users.inbox]],
outbox = it[followers[Users.outbox]],
url = it[followers[Users.url]],
publicKey = it[followers[Users.publicKey]],
privateKey = it[followers[Users.privateKey]],
createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]),
keyId = it[followers[Users.keyId]],
followers = it[followers[Users.followers]],
following = it[followers[Users.following]],
instance = it[followers[Users.instance]]
)
}
}
override suspend fun findFollowingByNameAndDomain(name: String, domain: String): List<User> {
val followers = Users.alias("FOLLOWERS")
return Users.innerJoin(
otherTable = UsersFollowers,
onColumn = { id },
otherColumn = { userId }
)
.innerJoin(
otherTable = followers,
onColumn = { UsersFollowers.followerId },
otherColumn = { followers[Users.id] }
)
.slice(
followers[Users.id],
followers[Users.name],
followers[Users.domain],
followers[Users.screenName],
followers[Users.description],
followers[Users.password],
followers[Users.inbox],
followers[Users.outbox],
followers[Users.url],
followers[Users.publicKey],
followers[Users.privateKey],
followers[Users.createdAt],
followers[Users.keyId],
followers[Users.following],
followers[Users.followers],
followers[Users.instance]
)
.select { followers[Users.name] eq name and (followers[Users.domain] eq domain) }
.map {
userBuilder.of(
id = it[followers[Users.id]],
name = it[followers[Users.name]],
domain = it[followers[Users.domain]],
screenName = it[followers[Users.screenName]],
description = it[followers[Users.description]],
password = it[followers[Users.password]],
inbox = it[followers[Users.inbox]],
outbox = it[followers[Users.outbox]],
url = it[followers[Users.url]],
publicKey = it[followers[Users.publicKey]],
privateKey = it[followers[Users.privateKey]],
createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]]),
keyId = it[followers[Users.keyId]],
followers = it[followers[Users.followers]],
following = it[followers[Users.following]],
instance = it[followers[Users.instance]]
)
}
}
override suspend fun appendFollower(user: Long, follower: Long) {
UsersFollowers.insert {
it[userId] = user
it[followerId] = follower
}
}
override suspend fun removeFollower(user: Long, follower: Long) {
UsersFollowers.deleteWhere { userId eq user and (followerId eq follower) }
}
override suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean {
return UsersFollowers.select { UsersFollowers.userId eq userId or (UsersFollowers.followerId eq followerId) }
.empty()
.not()
}
} }

View File

@ -4,7 +4,6 @@ import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper
import dev.usbharu.hideout.application.service.id.IdGenerateService import dev.usbharu.hideout.application.service.id.IdGenerateService
import dev.usbharu.hideout.core.domain.model.user.User import dev.usbharu.hideout.core.domain.model.user.User
import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.domain.model.user.UserRepository
import org.jetbrains.exposed.dao.id.LongIdTable
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
@ -62,15 +61,6 @@ class UserRepositoryImpl(
override suspend fun findById(id: Long): User? = override suspend fun findById(id: Long): User? =
Users.select { Users.id eq id }.singleOrNull()?.let(userResultRowMapper::map) Users.select { Users.id eq id }.singleOrNull()?.let(userResultRowMapper::map)
override suspend fun deleteFollowRequest(id: Long, follower: Long) {
FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) }
}
override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean {
return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) }
.singleOrNull() != null
}
override suspend fun delete(id: Long) { override suspend fun delete(id: Long) {
Users.deleteWhere { Users.id.eq(id) } Users.deleteWhere { Users.id.eq(id) }
} }
@ -108,21 +98,3 @@ object Users : Table("users") {
uniqueIndex(name, domain) uniqueIndex(name, domain)
} }
} }
object UsersFollowers : LongIdTable("users_followers") {
val userId: Column<Long> = long("user_id").references(Users.id).index()
val followerId: Column<Long> = long("follower_id").references(Users.id)
init {
uniqueIndex(userId, followerId)
}
}
object FollowRequests : LongIdTable("follow_requests") {
val userId: Column<Long> = long("user_id").references(Users.id)
val followerId: Column<Long> = long("follower_id").references(Users.id)
init {
uniqueIndex(userId, followerId)
}
}

View File

@ -2,12 +2,8 @@ package dev.usbharu.hideout.core.query
import dev.usbharu.hideout.core.domain.model.user.User import dev.usbharu.hideout.core.domain.model.user.User
@Deprecated("Use RelationshipQueryService")
interface FollowerQueryService { interface FollowerQueryService {
suspend fun findFollowersById(id: Long): List<User> suspend fun findFollowersById(id: Long): List<User>
suspend fun findFollowersByNameAndDomain(name: String, domain: String): List<User>
suspend fun findFollowingById(id: Long): List<User>
suspend fun findFollowingByNameAndDomain(name: String, domain: String): List<User>
suspend fun appendFollower(user: Long, follower: Long)
suspend fun removeFollower(user: Long, follower: Long)
suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean
} }

View File

@ -0,0 +1,8 @@
package dev.usbharu.hideout.core.query
import dev.usbharu.hideout.core.domain.model.relationship.Relationship
interface RelationshipQueryService {
suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List<Relationship>
}

View File

@ -305,7 +305,6 @@ class AccountApiServiceImplTest {
assertThat(relationships).hasSize(0) assertThat(relationships).hasSize(0)
verify(followerQueryService, never()).alreadyFollow(any(), any()) verify(followerQueryService, never()).alreadyFollow(any(), any())
verify(userRepository, never()).findFollowRequestsById(any(), any())
} }
@Test @Test