feat: トランザクションの問題で正常にドメインイベントを受け取ったあとの処理を実行できなかった問題を修正

This commit is contained in:
usbharu 2024-08-16 14:25:26 +09:00
parent 8d244b74c1
commit e9d776f71a
Signed by: usbharu
GPG Key ID: 6556747BF94EEBC8
8 changed files with 74 additions and 22 deletions

View File

@ -2,16 +2,12 @@ package dev.usbharu.hideout.core.domain.shared.repository
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventPublisher import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventPublisher
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
@Repository @Repository
interface DomainEventPublishableRepository<T : DomainEventStorable> { interface DomainEventPublishableRepository<T : DomainEventStorable> {
val domainEventPublisher: DomainEventPublisher val domainEventPublisher: DomainEventPublisher
suspend fun update(entity: T) { suspend fun update(entity: T) {
println(entity.getDomainEvents().joinToString())
val current = TransactionManager.current()
current.registerInterceptor()
entity.getDomainEvents().distinctBy { entity.getDomainEvents().distinctBy {
if (it.collectable) { if (it.collectable) {
it.name it.name

View File

@ -17,6 +17,10 @@
package dev.usbharu.hideout.core.infrastructure.exposedrepository package dev.usbharu.hideout.core.infrastructure.exposedrepository
import dev.usbharu.hideout.core.domain.exception.SpringDataAccessExceptionSQLExceptionTranslator import dev.usbharu.hideout.core.domain.exception.SpringDataAccessExceptionSQLExceptionTranslator
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.slf4j.MDCContext
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.statements.StatementInterceptor
import org.jetbrains.exposed.sql.transactions.TransactionManager import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.slf4j.Logger import org.slf4j.Logger
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
@ -35,7 +39,20 @@ abstract class AbstractRepository {
@Value("\${hideout.debug.trace-query-call:false}") @Value("\${hideout.debug.trace-query-call:false}")
private var traceQueryCall: Boolean = false private var traceQueryCall: Boolean = false
protected suspend fun <T> query(block: () -> T): T = try { class TransactionInterceptor(private val transaction: Transaction) {
fun onComplete(block: suspend (transaction: Transaction) -> Unit) {
transaction.registerInterceptor(object : StatementInterceptor {
override fun afterCommit(transaction: Transaction) {
runBlocking(MDCContext()) {
block(transaction)
}
}
})
}
}
protected suspend fun <T> query(block: TransactionInterceptor.() -> T): T = try {
if (traceQueryCall) { if (traceQueryCall) {
@Suppress("ThrowingExceptionsWithoutMessageOrCause") @Suppress("ThrowingExceptionsWithoutMessageOrCause")
logger.trace( logger.trace(
@ -49,7 +66,7 @@ ${Throwable().stackTrace.joinToString("\n")}
) )
} }
block.invoke() block.invoke(TransactionInterceptor(TransactionManager.current()))
} catch (e: SQLException) { } catch (e: SQLException) {
if (traceQueryException) { if (traceQueryException) {
logger.trace("FAILED EXECUTE SQL", e) logger.trace("FAILED EXECUTE SQL", e)

View File

@ -45,8 +45,11 @@ class ExposedActorInstanceRelationshipRepository(override val domainEventPublish
it[muting] = actorInstanceRelationship.muting it[muting] = actorInstanceRelationship.muting
it[doNotSendPrivate] = actorInstanceRelationship.doNotSendPrivate it[doNotSendPrivate] = actorInstanceRelationship.doNotSendPrivate
} }
} onComplete {
update(actorInstanceRelationship) update(actorInstanceRelationship)
}
}
return actorInstanceRelationship return actorInstanceRelationship
} }
@ -56,9 +59,12 @@ class ExposedActorInstanceRelationshipRepository(override val domainEventPublish
actorId eq actorInstanceRelationship.actorId.id and actorId eq actorInstanceRelationship.actorId.id and
(instanceId eq actorInstanceRelationship.instanceId.instanceId) (instanceId eq actorInstanceRelationship.instanceId.instanceId)
} }
} onComplete {
update(actorInstanceRelationship) update(actorInstanceRelationship)
} }
}
}
override suspend fun findByActorIdAndInstanceId( override suspend fun findByActorIdAndInstanceId(
actorId: ActorId, actorId: ActorId,

View File

@ -59,8 +59,11 @@ class ExposedActorRepository(
this[ActorsAlsoKnownAs.actorId] = actor.id.id this[ActorsAlsoKnownAs.actorId] = actor.id.id
this[ActorsAlsoKnownAs.alsoKnownAs] = it.id this[ActorsAlsoKnownAs.alsoKnownAs] = it.id
} }
} onComplete {
update(actor) update(actor)
}
}
return actor return actor
} }
@ -68,9 +71,11 @@ class ExposedActorRepository(
query { query {
Actors.deleteWhere { id eq actor.id.id } Actors.deleteWhere { id eq actor.id.id }
ActorsAlsoKnownAs.deleteWhere { actorId eq actor.id.id } ActorsAlsoKnownAs.deleteWhere { actorId eq actor.id.id }
} onComplete {
update(actor) update(actor)
} }
}
}
override suspend fun findById(id: ActorId): Actor? { override suspend fun findById(id: ActorId): Actor? {
return query { return query {

View File

@ -98,8 +98,11 @@ class ExposedPostRepository(
this[PostsVisibleActors.postId] = post.id.id this[PostsVisibleActors.postId] = post.id.id
this[PostsVisibleActors.actorId] = it.id this[PostsVisibleActors.actorId] = it.id
} }
} onComplete {
update(post) update(post)
}
}
return post return post
} }
@ -148,10 +151,12 @@ class ExposedPostRepository(
this[PostsVisibleActors.postId] = it.first this[PostsVisibleActors.postId] = it.first
this[PostsVisibleActors.actorId] = it.second this[PostsVisibleActors.actorId] = it.second
} }
} onComplete {
posts.forEach { posts.forEach {
update(it) update(it)
} }
}
}
return posts return posts
} }
@ -195,9 +200,12 @@ class ExposedPostRepository(
Posts.deleteWhere { Posts.deleteWhere {
id eq post.id.id id eq post.id.id
} }
} onComplete {
update(post) update(post)
} }
}
}
override suspend fun findByActorIdAndVisibilityInList( override suspend fun findByActorIdAndVisibilityInList(
actorId: ActorId, actorId: ActorId,

View File

@ -47,8 +47,11 @@ class ExposedRelationshipRepository(override val domainEventPublisher: DomainEve
it[followRequesting] = relationship.followRequesting it[followRequesting] = relationship.followRequesting
it[mutingFollowRequest] = relationship.mutingFollowRequest it[mutingFollowRequest] = relationship.mutingFollowRequest
} }
} onComplete {
update(relationship) update(relationship)
}
}
return relationship return relationship
} }
@ -57,9 +60,12 @@ class ExposedRelationshipRepository(override val domainEventPublisher: DomainEve
Relationships.deleteWhere { Relationships.deleteWhere {
actorId eq relationship.actorId.id and (targetActorId eq relationship.targetActorId.id) actorId eq relationship.actorId.id and (targetActorId eq relationship.targetActorId.id)
} }
} onComplete {
update(relationship) update(relationship)
} }
}
}
override suspend fun findByActorIdAndTargetId(actorId: ActorId, targetId: ActorId): Relationship? = query { override suspend fun findByActorIdAndTargetId(actorId: ActorId, targetId: ActorId): Relationship? = query {
Relationships.selectAll().where { Relationships.selectAll().where {

View File

@ -24,8 +24,12 @@ class ExposedTimelineRepository(override val domainEventPublisher: DomainEventPu
it[visibility] = timeline.visibility.name it[visibility] = timeline.visibility.name
it[isSystem] = timeline.isSystem it[isSystem] = timeline.isSystem
} }
} onComplete {
update(timeline) update(timeline)
}
}
return timeline return timeline
} }
@ -34,9 +38,12 @@ class ExposedTimelineRepository(override val domainEventPublisher: DomainEventPu
Timelines.deleteWhere { Timelines.deleteWhere {
Timelines.id eq timeline.id.value Timelines.id eq timeline.id.value
} }
} onComplete {
update(timeline) update(timeline)
} }
}
}
override suspend fun findByIds(ids: List<TimelineId>): List<Timeline> { override suspend fun findByIds(ids: List<TimelineId>): List<Timeline> {
return query { return query {

View File

@ -48,6 +48,7 @@ class UserDetailRepositoryImpl(override val domainEventPublisher: DomainEventPub
it[password] = userDetail.password.password it[password] = userDetail.password.password
it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest
it[lastMigration] = userDetail.lastMigration it[lastMigration] = userDetail.lastMigration
it[homeTimelineId] = userDetail.homeTimelineId?.value
} }
} else { } else {
UserDetails.update({ UserDetails.id eq userDetail.id.id }) { UserDetails.update({ UserDetails.id eq userDetail.id.id }) {
@ -55,21 +56,27 @@ class UserDetailRepositoryImpl(override val domainEventPublisher: DomainEventPub
it[password] = userDetail.password.password it[password] = userDetail.password.password
it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest
it[lastMigration] = userDetail.lastMigration it[lastMigration] = userDetail.lastMigration
it[homeTimelineId] = userDetail.homeTimelineId?.value
} }
} }
onComplete {
update(userDetail)
}
userDetail userDetail
} }
update(userDetail)
return userDetail1 return userDetail1
} }
override suspend fun delete(userDetail: UserDetail): Unit { override suspend fun delete(userDetail: UserDetail): Unit {
query { query {
UserDetails.deleteWhere { id eq userDetail.id.id } UserDetails.deleteWhere { id eq userDetail.id.id }
} onComplete {
update(userDetail) update(userDetail)
} }
}
}
override suspend fun findByActorId(actorId: Long): UserDetail? = query { override suspend fun findByActorId(actorId: Long): UserDetail? = query {
return@query UserDetails return@query UserDetails