mirror of https://github.com/usbharu/Hideout.git
feat: ドメインイベントのサブスクライバー一覧を出力できるように
This commit is contained in:
parent
d74101a2b6
commit
1c80911365
|
@ -30,7 +30,6 @@ services:
|
|||
- "9200:9200"
|
||||
volumes:
|
||||
- elasticsearch-data:/usr/share/elasticsearch/data
|
||||
restart: always
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:7.17.24
|
||||
container_name: kibana
|
||||
|
@ -42,7 +41,6 @@ services:
|
|||
- ELASTICSEARCH_PASSWORD=Passw0rd
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
restart: always
|
||||
|
||||
fluentd:
|
||||
build: ./fluentd
|
||||
|
|
|
@ -5,6 +5,7 @@ import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
|||
|
||||
interface DomainEventSubscriber {
|
||||
fun <T : DomainEventBody> subscribe(eventName: String, domainEventConsumer: DomainEventConsumer<T>)
|
||||
fun getSubscribers(): Map<String, List<DomainEventConsumer<*>>>
|
||||
}
|
||||
|
||||
typealias DomainEventConsumer<T> = suspend (DomainEvent<T>) -> Unit
|
||||
|
|
|
@ -3,19 +3,22 @@ package dev.usbharu.hideout.core.application.domainevent.subscribers
|
|||
import dev.usbharu.hideout.core.domain.event.userdetail.UserDetailEvent
|
||||
import dev.usbharu.hideout.core.domain.event.userdetail.UserDetailEventBody
|
||||
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class RegisterLocalUserSetHomeTimelineSubscriber(
|
||||
private val domainEventSubscriber: DomainEventSubscriber,
|
||||
private val userRegisterHomeTimelineApplicationService: UserRegisterHomeTimelineApplicationService
|
||||
) : Subscriber {
|
||||
) : Subscriber, DomainEventConsumer<UserDetailEventBody> {
|
||||
override fun init() {
|
||||
domainEventSubscriber.subscribe<UserDetailEventBody>(UserDetailEvent.CREATE.eventName) {
|
||||
domainEventSubscriber.subscribe<UserDetailEventBody>(UserDetailEvent.CREATE.eventName, this)
|
||||
}
|
||||
|
||||
override suspend fun invoke(p1: DomainEvent<UserDetailEventBody>) {
|
||||
userRegisterHomeTimelineApplicationService.execute(
|
||||
RegisterHomeTimeline(it.body.getUserDetail().id),
|
||||
RegisterHomeTimeline(p1.body.getUserDetail().id),
|
||||
Anonymous
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,17 +5,20 @@ import dev.usbharu.hideout.core.application.timeline.SetTimleineStore
|
|||
import dev.usbharu.hideout.core.domain.event.timeline.TimelineEvent
|
||||
import dev.usbharu.hideout.core.domain.event.timeline.TimelineEventBody
|
||||
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class RegisterTimelineSetTimelineStoreSubscriber(
|
||||
private val domainEventSubscriber: DomainEventSubscriber,
|
||||
private val setTimelineToTimelineStoreApplicationService: SetTimelineToTimelineStoreApplicationService
|
||||
) : Subscriber {
|
||||
) : Subscriber, DomainEventConsumer<TimelineEventBody> {
|
||||
|
||||
override fun init() {
|
||||
domainEventSubscriber.subscribe<TimelineEventBody>(TimelineEvent.CREATE.eventName) {
|
||||
setTimelineToTimelineStoreApplicationService.execute(SetTimleineStore(it.body.getTimelineId()), Anonymous)
|
||||
}
|
||||
domainEventSubscriber.subscribe<TimelineEventBody>(TimelineEvent.CREATE.eventName, this)
|
||||
}
|
||||
|
||||
override suspend fun invoke(p1: DomainEvent<TimelineEventBody>) {
|
||||
setTimelineToTimelineStoreApplicationService.execute(SetTimleineStore(p1.body.getTimelineId()), Anonymous)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,47 @@
|
|||
package dev.usbharu.hideout.core.application.domainevent.subscribers
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.ApplicationArguments
|
||||
import org.springframework.boot.ApplicationRunner
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class SubscriberRunner(private val subscribers: List<Subscriber>) : ApplicationRunner {
|
||||
class SubscriberRunner(
|
||||
private val subscribers: List<Subscriber>,
|
||||
private val domainEventSubscriber: DomainEventSubscriber
|
||||
) : ApplicationRunner {
|
||||
override fun run(args: ApplicationArguments?) {
|
||||
subscribers.forEach { it.init() }
|
||||
|
||||
if (logger.isDebugEnabled) {
|
||||
val stringListMap = domainEventSubscriber.getSubscribers()
|
||||
|
||||
val header = """
|
||||
|====== Domain Event Subscribers Report =====
|
||||
|
|
||||
|
|
||||
|
|
||||
""".trimMargin()
|
||||
|
||||
val value = stringListMap.map {
|
||||
it.key + "\n\t" + it.value.joinToString("\n", "[", "]") { suspendFunction1 ->
|
||||
suspendFunction1::class.qualifiedName.orEmpty()
|
||||
}
|
||||
}.joinToString("\n\n\n")
|
||||
|
||||
val footer = """
|
||||
|
|
||||
|
|
||||
|
|
||||
|===== Domain Event Subscribers Report =====
|
||||
""".trimMargin()
|
||||
|
||||
logger.debug("{}{}{}", header, value, footer)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(SubscriberRunner::class.java)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,16 +5,19 @@ import dev.usbharu.hideout.core.application.timeline.TimelineAddPostApplicationS
|
|||
import dev.usbharu.hideout.core.domain.event.post.PostEvent
|
||||
import dev.usbharu.hideout.core.domain.event.post.PostEventBody
|
||||
import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TimelinePostCreateSubscriber(
|
||||
private val timelineAddPostApplicationService: TimelineAddPostApplicationService,
|
||||
private val domainEventSubscriber: DomainEventSubscriber,
|
||||
) : Subscriber {
|
||||
) : Subscriber, DomainEventConsumer<PostEventBody> {
|
||||
override fun init() {
|
||||
domainEventSubscriber.subscribe<PostEventBody>(PostEvent.CREATE.eventName) {
|
||||
timelineAddPostApplicationService.execute(AddPost(it.body.getPostId()), Anonymous)
|
||||
}
|
||||
domainEventSubscriber.subscribe<PostEventBody>(PostEvent.CREATE.eventName, this)
|
||||
}
|
||||
|
||||
override suspend fun invoke(p1: DomainEvent<PostEventBody>) {
|
||||
timelineAddPostApplicationService.execute(AddPost(p1.body.getPostId()), Anonymous)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent
|
|||
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody
|
||||
import dev.usbharu.hideout.core.domain.model.timelinerelationship.Visible
|
||||
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
@ -15,16 +16,20 @@ class TimelineRelationshipFollowSubscriber(
|
|||
private val userAddTimelineRelationshipApplicationService: UserAddTimelineRelationshipApplicationService,
|
||||
private val userDetailRepository: UserDetailRepository,
|
||||
private val domainEventSubscriber: DomainEventSubscriber
|
||||
) : Subscriber {
|
||||
) : Subscriber, DomainEventConsumer<RelationshipEventBody> {
|
||||
|
||||
override fun init() {
|
||||
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.ACCEPT_FOLLOW.eventName) {
|
||||
val relationship = it.body.getRelationship()
|
||||
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.ACCEPT_FOLLOW.eventName, this)
|
||||
}
|
||||
|
||||
|
||||
override suspend fun invoke(p1: DomainEvent<RelationshipEventBody>) {
|
||||
val relationship = p1.body.getRelationship()
|
||||
val userDetail = userDetailRepository.findByActorId(relationship.actorId.id)
|
||||
?: throw InternalServerException("Userdetail ${relationship.actorId} not found by actorid.")
|
||||
if (userDetail.homeTimelineId == null) {
|
||||
logger.warn("Home timeline for ${relationship.actorId} is not found")
|
||||
return@subscribe
|
||||
return
|
||||
}
|
||||
|
||||
@Suppress("UnsafeCallOnNullableType")
|
||||
|
@ -34,10 +39,9 @@ class TimelineRelationshipFollowSubscriber(
|
|||
relationship.targetActorId,
|
||||
Visible.FOLLOWERS
|
||||
),
|
||||
it.body.principal
|
||||
p1.body.principal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(TimelineRelationshipFollowSubscriber::class.java)
|
||||
|
|
|
@ -6,6 +6,7 @@ import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent
|
|||
import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody
|
||||
import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository
|
||||
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
@ -15,16 +16,19 @@ class TimelineRelationshipUnfollowSubscriber(
|
|||
private val userRemoveTimelineRelationshipApplicationService: UserRemoveTimelineRelationshipApplicationService,
|
||||
private val userDetailRepository: UserDetailRepository,
|
||||
private val timelineRelationshipRepository: TimelineRelationshipRepository,
|
||||
) : Subscriber {
|
||||
) : Subscriber, DomainEventConsumer<RelationshipEventBody> {
|
||||
override fun init() {
|
||||
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.UNFOLLOW.eventName) {
|
||||
val relationship = it.body.getRelationship()
|
||||
domainEventSubscriber.subscribe<RelationshipEventBody>(RelationshipEvent.UNFOLLOW.eventName, this)
|
||||
}
|
||||
|
||||
override suspend fun invoke(p1: DomainEvent<RelationshipEventBody>) {
|
||||
val relationship = p1.body.getRelationship()
|
||||
val userDetail = userDetailRepository.findByActorId(relationship.actorId.id) ?: throw IllegalStateException(
|
||||
"UserDetail ${relationship.actorId} not found by actorId."
|
||||
)
|
||||
if (userDetail.homeTimelineId == null) {
|
||||
logger.warn("HomeTimeline for ${userDetail.id} not found.")
|
||||
return@subscribe
|
||||
return
|
||||
}
|
||||
|
||||
val timelineRelationship = timelineRelationshipRepository.findByTimelineIdAndActorId(
|
||||
|
@ -35,10 +39,9 @@ class TimelineRelationshipUnfollowSubscriber(
|
|||
|
||||
userRemoveTimelineRelationshipApplicationService.execute(
|
||||
RemoveTimelineRelationship(timelineRelationship.id),
|
||||
it.body.principal
|
||||
p1.body.principal
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(TimelineRelationshipUnfollowSubscriber::class.java)
|
||||
|
|
|
@ -18,7 +18,9 @@ package dev.usbharu.hideout.core.infrastructure.springframework.domainevent
|
|||
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventPublisher
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.ApplicationRequestLogInterceptor
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.MDC
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
@ -27,10 +29,18 @@ class SpringFrameworkDomainEventPublisher(private val applicationEventPublisher:
|
|||
DomainEventPublisher {
|
||||
override suspend fun publishEvent(domainEvent: DomainEvent<*>) {
|
||||
logger.trace("Publish ${domainEvent.id} ${domainEvent.name}")
|
||||
applicationEventPublisher.publishEvent(domainEvent)
|
||||
|
||||
val requestId: String? = MDC.get(ApplicationRequestLogInterceptor.requestId)
|
||||
val springDomainEvent = SpringDomainEvent(
|
||||
requestId, domainEvent
|
||||
)
|
||||
|
||||
applicationEventPublisher.publishEvent(springDomainEvent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val logger = LoggerFactory.getLogger(SpringFrameworkDomainEventPublisher::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
data class SpringDomainEvent(val requestId: String?, val domainEvent: DomainEvent<*>)
|
|
@ -2,9 +2,14 @@ package dev.usbharu.hideout.core.infrastructure.springframework.domainevent
|
|||
|
||||
import dev.usbharu.hideout.core.application.domainevent.subscribers.DomainEventConsumer
|
||||
import dev.usbharu.hideout.core.application.domainevent.subscribers.DomainEventSubscriber
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent
|
||||
import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody
|
||||
import dev.usbharu.hideout.core.infrastructure.springframework.ApplicationRequestLogInterceptor.Companion.requestId
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.slf4j.MDCContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.MDC
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
|
@ -17,15 +22,35 @@ class SpringFrameworkDomainEventSubscriber : DomainEventSubscriber {
|
|||
map.getOrPut(eventName) { mutableListOf() }.add(domainEventConsumer as DomainEventConsumer<*>)
|
||||
}
|
||||
|
||||
@EventListener
|
||||
suspend fun onDomainEventPublished(domainEvent: DomainEvent<*>) {
|
||||
logger.trace("Domain Event Published: $domainEvent")
|
||||
map[domainEvent.name]?.forEach {
|
||||
try {
|
||||
it.invoke(domainEvent)
|
||||
} catch (@Suppress("TooGenericExceptionCaught") e: Exception) {
|
||||
logger.error("", e)
|
||||
override fun getSubscribers(): Map<String, List<DomainEventConsumer<*>>> {
|
||||
return map
|
||||
}
|
||||
|
||||
@EventListener
|
||||
suspend fun onDomainEventPublished(domainEvent: SpringDomainEvent) {
|
||||
|
||||
logger.debug(
|
||||
"Domain Event Published: {} id: {} requestId: {}",
|
||||
domainEvent.domainEvent.name,
|
||||
domainEvent.domainEvent.id,
|
||||
domainEvent.requestId
|
||||
)
|
||||
coroutineScope {
|
||||
|
||||
map[domainEvent.domainEvent.name]?.map {
|
||||
async(MDCContext()) {
|
||||
try {
|
||||
MDC.put(requestId, domainEvent.requestId)
|
||||
it.invoke(domainEvent.domainEvent)
|
||||
} catch (@Suppress("TooGenericExceptionCaught") e: Exception) {
|
||||
logger.warn("", e)
|
||||
null
|
||||
} finally {
|
||||
MDC.remove(requestId)
|
||||
}
|
||||
}
|
||||
}?.awaitAll()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue