refactor: Postをリファクタリング

This commit is contained in:
usbharu 2023-05-05 16:04:48 +09:00
parent 1b6147db7f
commit 05ceab0379
16 changed files with 134 additions and 119 deletions

View File

@ -1,54 +0,0 @@
package dev.usbharu.hideout.domain.model
import dev.usbharu.hideout.repository.Users
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.Table
object Posts : Table() {
val id = long("id")
val userId = long("userId").references(Users.id)
val overview = varchar("overview", 100).nullable()
val text = varchar("text", 3000)
val createdAt = long("createdAt")
val visibility = integer("visibility").default(0)
val url = varchar("url", 500)
val repostId = long("repostId").references(id).nullable()
val replyId = long("replyId").references(id).nullable()
override val primaryKey: PrimaryKey = PrimaryKey(id)
}
data class Post(
val userId: Long,
val overview: String? = null,
val text: String,
val createdAt: Long,
val visibility: Int,
val repostId: Long? = null,
val replyId: Long? = null
)
data class PostEntity(
val id: Long,
val userId: Long,
val overview: String? = null,
val text: String,
val createdAt: Long,
val visibility: Int,
val url: String,
val repostId: Long? = null,
val replyId: Long? = null
)
fun ResultRow.toPost(): PostEntity {
return PostEntity(
id = this[Posts.id],
userId = this[Posts.userId],
overview = this[Posts.overview],
text = this[Posts.text],
createdAt = this[Posts.createdAt],
visibility = this[Posts.visibility],
url = this[Posts.url],
repostId = this[Posts.repostId],
replyId = this[Posts.replyId]
)
}

View File

@ -1,4 +1,4 @@
package dev.usbharu.hideout.domain.model.api package dev.usbharu.hideout.domain.model.api.mastodon
data class StatusForPost( data class StatusForPost(
val status: String, val status: String,

View File

@ -0,0 +1,3 @@
package dev.usbharu.hideout.domain.model.hideout.dto
data class PostCreateDto(val text:String,val username:String)

View File

@ -0,0 +1,13 @@
package dev.usbharu.hideout.domain.model.hideout.entity
data class Post(
val id:Long,
val userId: Long,
val overview:String? = null,
val text:String,
val createdAt:Long,
val visibility: Int,
val url:String,
val repostId:Long? = null,
val replyId:Long? = null
)

View File

@ -0,0 +1,3 @@
package dev.usbharu.hideout.domain.model.hideout.form
data class Post(val text:String)

View File

@ -3,7 +3,7 @@ package dev.usbharu.hideout.plugins
import dev.usbharu.hideout.routing.activitypub.inbox import dev.usbharu.hideout.routing.activitypub.inbox
import dev.usbharu.hideout.routing.activitypub.outbox import dev.usbharu.hideout.routing.activitypub.outbox
import dev.usbharu.hideout.routing.activitypub.usersAP import dev.usbharu.hideout.routing.activitypub.usersAP
import dev.usbharu.hideout.routing.api.v1.statuses import dev.usbharu.hideout.routing.api.mastodon.v1.statuses
import dev.usbharu.hideout.routing.wellknown.webfinger import dev.usbharu.hideout.routing.wellknown.webfinger
import dev.usbharu.hideout.service.IPostService import dev.usbharu.hideout.service.IPostService
import dev.usbharu.hideout.service.activitypub.ActivityPubService import dev.usbharu.hideout.service.activitypub.ActivityPubService

View File

@ -1,10 +1,10 @@
package dev.usbharu.hideout.repository package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.Post import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.PostEntity
interface IPostRepository { interface IPostRepository {
suspend fun insert(post: Post): PostEntity suspend fun generateId(): Long
suspend fun findOneById(id: Long): PostEntity suspend fun save(post: Post): Post
suspend fun findOneById(id: Long): Post
suspend fun delete(id: Long) suspend fun delete(id: Long)
} }

View File

@ -1,10 +1,7 @@
package dev.usbharu.hideout.repository package dev.usbharu.hideout.repository
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.Post import dev.usbharu.hideout.repository.toPost
import dev.usbharu.hideout.domain.model.PostEntity
import dev.usbharu.hideout.domain.model.Posts
import dev.usbharu.hideout.domain.model.toPost
import dev.usbharu.hideout.service.IdGenerateService import dev.usbharu.hideout.service.IdGenerateService
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
@ -22,41 +19,31 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
} }
} }
override suspend fun generateId(): Long = idGenerateService.generateId()
@Suppress("InjectDispatcher") @Suppress("InjectDispatcher")
suspend fun <T> query(block: suspend () -> T): T = suspend fun <T> query(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() } newSuspendedTransaction(Dispatchers.IO) { block() }
override suspend fun insert(post: Post): PostEntity {
override suspend fun save(post: Post): Post {
return query { return query {
val generateId = idGenerateService.generateId()
val name = Users.select { Users.id eq post.userId }.single().toUser().name
val postUrl = Config.configData.url + "/users/$name/posts/$generateId"
Posts.insert { Posts.insert {
it[id] = generateId it[id] = post.id
it[userId] = post.userId it[userId] = post.userId
it[overview] = post.overview it[overview] = post.overview
it[text] = post.text it[text] = post.text
it[createdAt] = post.createdAt it[createdAt] = post.createdAt
it[visibility] = post.visibility it[visibility] = post.visibility
it[url] = postUrl it[url] = post.url
it[repostId] = post.repostId it[repostId] = post.repostId
it[replyId] = post.replyId it[replyId] = post.replyId
} }
return@query PostEntity( return@query post
id = generateId,
userId = post.userId,
overview = post.overview,
text = post.text,
createdAt = post.createdAt,
visibility = post.visibility,
url = postUrl,
repostId = post.repostId,
replyId = post.replyId
)
} }
} }
override suspend fun findOneById(id: Long): PostEntity { override suspend fun findOneById(id: Long): Post {
return query { return query {
Posts.select { Posts.id eq id }.single().toPost() Posts.select { Posts.id eq id }.single().toPost()
} }
@ -68,3 +55,30 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe
} }
} }
} }
object Posts : Table() {
val id = long("id")
val userId = long("userId").references(Users.id)
val overview = varchar("overview", 100).nullable()
val text = varchar("text", 3000)
val createdAt = long("createdAt")
val visibility = integer("visibility").default(0)
val url = varchar("url", 500)
val repostId = long("repostId").references(id).nullable()
val replyId = long("replyId").references(id).nullable()
override val primaryKey: PrimaryKey = PrimaryKey(id)
}
fun ResultRow.toPost(): Post {
return Post(
id = this[Posts.id],
userId = this[Posts.userId],
overview = this[Posts.overview],
text = this[Posts.text],
createdAt = this[Posts.createdAt],
visibility = this[Posts.visibility],
url = this[Posts.url],
repostId = this[Posts.repostId],
replyId = this[Posts.replyId]
)
}

View File

@ -0,0 +1,25 @@
package dev.usbharu.hideout.routing.api.internal.v1
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
import dev.usbharu.hideout.domain.model.hideout.form.Post
import dev.usbharu.hideout.service.IPostService
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.routing.*
fun Route.posts(postService: IPostService){
route("/posts"){
authenticate(){
post{
val principal = call.principal<JWTPrincipal>() ?: throw RuntimeException("no principal")
val username = principal.payload.getClaim("username").asString()
val receive = call.receive<Post>()
val postCreateDto = PostCreateDto(receive.text,username)
postService.create(postCreateDto)
}
}
}
}

View File

@ -0,0 +1,20 @@
package dev.usbharu.hideout.routing.api.mastodon.v1
import dev.usbharu.hideout.service.IPostService
import io.ktor.server.routing.*
fun Route.statuses(postService: IPostService) {
// route("/statuses") {
// post {
// val status: StatusForPost = call.receive()
// val post = dev.usbharu.hideout.domain.model.hideout.form.Post(
// userId = status.userId,
// createdAt = System.currentTimeMillis(),
// text = status.status,
// visibility = 1
// )
// postService.create(post)
// call.respond(status)
// }
// }
}

View File

@ -1,25 +0,0 @@
package dev.usbharu.hideout.routing.api.v1
import dev.usbharu.hideout.domain.model.Post
import dev.usbharu.hideout.domain.model.api.StatusForPost
import dev.usbharu.hideout.service.IPostService
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun Route.statuses(postService: IPostService) {
route("/statuses") {
post {
val status: StatusForPost = call.receive()
val post = Post(
userId = status.userId,
createdAt = System.currentTimeMillis(),
text = status.status,
visibility = 1
)
postService.create(post)
call.respond(status)
}
}
}

View File

@ -1,7 +1,9 @@
package dev.usbharu.hideout.service package dev.usbharu.hideout.service
import dev.usbharu.hideout.domain.model.Post import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
import dev.usbharu.hideout.domain.model.hideout.entity.Post
interface IPostService { interface IPostService {
suspend fun create(post: Post) suspend fun create(post: Post)
suspend fun create(post: PostCreateDto)
} }

View File

@ -1,11 +1,11 @@
package dev.usbharu.hideout.service.activitypub package dev.usbharu.hideout.service.activitypub
import dev.usbharu.hideout.domain.model.PostEntity import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.job.DeliverPostJob import dev.usbharu.hideout.domain.model.job.DeliverPostJob
import kjob.core.job.JobProps import kjob.core.job.JobProps
interface ActivityPubNoteService { interface ActivityPubNoteService {
suspend fun createNote(post: PostEntity) suspend fun createNote(post: Post)
suspend fun createNoteJob(props: JobProps<DeliverPostJob>) suspend fun createNoteJob(props: JobProps<DeliverPostJob>)
} }

View File

@ -2,9 +2,9 @@ package dev.usbharu.hideout.service.activitypub
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.PostEntity
import dev.usbharu.hideout.domain.model.ap.Create import dev.usbharu.hideout.domain.model.ap.Create
import dev.usbharu.hideout.domain.model.ap.Note import dev.usbharu.hideout.domain.model.ap.Note
import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.job.DeliverPostJob import dev.usbharu.hideout.domain.model.job.DeliverPostJob
import dev.usbharu.hideout.plugins.postAp import dev.usbharu.hideout.plugins.postAp
import dev.usbharu.hideout.service.impl.IUserService import dev.usbharu.hideout.service.impl.IUserService
@ -24,7 +24,7 @@ class ActivityPubNoteServiceImpl(
private val logger = LoggerFactory.getLogger(this::class.java) private val logger = LoggerFactory.getLogger(this::class.java)
override suspend fun createNote(post: PostEntity) { override suspend fun createNote(post: Post) {
val followers = userService.findFollowersById(post.userId) val followers = userService.findFollowersById(post.userId)
val userEntity = userService.findById(post.userId) val userEntity = userService.findById(post.userId)
val note = Config.configData.objectMapper.writeValueAsString(post) val note = Config.configData.objectMapper.writeValueAsString(post)
@ -39,7 +39,7 @@ class ActivityPubNoteServiceImpl(
override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) { override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) {
val actor = props[DeliverPostJob.actor] val actor = props[DeliverPostJob.actor]
val postEntity = Config.configData.objectMapper.readValue<PostEntity>(props[DeliverPostJob.post]) val postEntity = Config.configData.objectMapper.readValue<Post>(props[DeliverPostJob.post])
val note = Note( val note = Note(
name = "Note", name = "Note",
id = postEntity.url, id = postEntity.url,

View File

@ -1,23 +1,37 @@
package dev.usbharu.hideout.service.impl package dev.usbharu.hideout.service.impl
import dev.usbharu.hideout.domain.model.Post import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.repository.IPostRepository
import dev.usbharu.hideout.service.IPostService import dev.usbharu.hideout.service.IPostService
import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.time.Instant
@Single @Single
class PostService( class PostService(
private val postRepository: IPostRepository, private val postRepository: IPostRepository,
private val activityPubNoteService: ActivityPubNoteService private val activityPubNoteService: ActivityPubNoteService,
private val userService: IUserService
) : IPostService { ) : IPostService {
private val logger = LoggerFactory.getLogger(this::class.java) private val logger = LoggerFactory.getLogger(this::class.java)
override suspend fun create(post: Post) { override suspend fun create(post: Post) {
logger.debug("create post={}", post) logger.debug("create post={}", post)
val postEntity = postRepository.insert(post) val postEntity = postRepository.save(post)
activityPubNoteService.createNote(postEntity) activityPubNoteService.createNote(postEntity)
} }
override suspend fun create(post: PostCreateDto) {
logger.debug("create post={}", post)
val user = userService.findByNameLocalUser(post.username)
val id = postRepository.generateId()
val postEntity = Post(
id, user.id, null, post.text,
Instant.now().toEpochMilli(), 0, "${user.url}/posts/$id", null, null
)
postRepository.save(postEntity)
}
} }

View File

@ -5,7 +5,7 @@ package dev.usbharu.hideout.service.activitypub
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.config.ConfigData import dev.usbharu.hideout.config.ConfigData
import dev.usbharu.hideout.domain.model.PostEntity import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.domain.model.job.DeliverPostJob import dev.usbharu.hideout.domain.model.job.DeliverPostJob
import dev.usbharu.hideout.service.impl.IUserService import dev.usbharu.hideout.service.impl.IUserService
@ -72,7 +72,7 @@ class ActivityPubNoteServiceImplTest {
} }
val jobQueueParentService = mock<JobQueueParentService>() val jobQueueParentService = mock<JobQueueParentService>()
val activityPubNoteService = ActivityPubNoteServiceImpl(mock(), jobQueueParentService, userService) val activityPubNoteService = ActivityPubNoteServiceImpl(mock(), jobQueueParentService, userService)
val postEntity = PostEntity( val postEntity = Post(
1L, 1L,
1L, 1L,
null, null,