Axon框架:在命令处理程序期间仅应用第一个事件

时间:2019-10-17 05:26:01

标签: axon

我正在尝试创建一个命令处理程序,将该命令视为许多子命令。每个子命令将生成一个事件(然后应更新聚合的状态)。每个子命令的处理都依赖于聚合的最新状态(来自上一个子命令)。

例如,考虑以下汇总:

package axon.poc

import org.axonframework.commandhandling.CommandHandler
import org.axonframework.eventsourcing.EventSourcingHandler
import org.axonframework.modelling.command.AggregateIdentifier
import org.axonframework.modelling.command.AggregateLifecycle
import org.axonframework.spring.stereotype.Aggregate
import org.slf4j.LoggerFactory
import java.util.UUID

@Aggregate
class Aggregate() {

    companion object {
        private val logger = LoggerFactory.getLogger(Aggregate::class.java)
    }

    @AggregateIdentifier
    internal var aggregateId: UUID? = null

    private var value: Int = 0

    @CommandHandler
    constructor(command: Command): this() {
        logger.info("generating create event")
        var applyMore = AggregateLifecycle.apply(CreatedEvent(command.aggregateId))
        for (i in 0 until command.value) {
            applyMore = applyMore.andThenApply {
                logger.info("generating update event: ${value+1}")
                UpdatedEvent(command.aggregateId, value+1)
            }
        }
        logger.info("completed command handler")
    }

    @EventSourcingHandler
    fun on(event: CreatedEvent) {
        logger.info("event sourcing handler: $event")
        this.aggregateId = event.aggregateId
        this.value = 0
    }

    @EventSourcingHandler
    fun on(event: UpdatedEvent) {
        logger.info("event sourcing handler: $event")
        this.value = event.value
    }

}

此代码处理Command(value = 2)时,它会生成

[main] INFO org.axonframework.spring.stereotype.Aggregate - generating create event
[main] INFO org.axonframework.spring.stereotype.Aggregate - completed command handler
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: CreatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a)
[main] INFO org.axonframework.spring.stereotype.Aggregate - generating update event: 1
[main] INFO org.axonframework.spring.stereotype.Aggregate - generating update event: 1
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: UpdatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a, value=1)
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: UpdatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a, value=1)

在执行applyMore之前,正在处理第一个事件(CreatedEvent)。但是,即使applyMore已被链接,事件生成处理程序也不会处理UpdatedEvent,直到两者都生成为止。

我期待(并希望):

[main] INFO org.axonframework.spring.stereotype.Aggregate - generating create event
[main] INFO org.axonframework.spring.stereotype.Aggregate - completed command handler
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: CreatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a)
[main] INFO org.axonframework.spring.stereotype.Aggregate - generating update event: 1
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: UpdatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a, value=1)
[main] INFO org.axonframework.spring.stereotype.Aggregate - generating update event: 2
[main] INFO org.axonframework.spring.stereotype.Aggregate - event sourcing handler: UpdatedEvent(aggregateId=65a7a461-61bb-451f-b2d9-8460994eeb1a, value=2)

这是Axon的错误吗?还是我对应如何使用有所误解?如何自动处理多个“命令”?即。全部通过或全部失败。

1 个答案:

答案 0 :(得分:2)

TLDR;这是一个错误。

您遇到了非常特殊的情况,仅在构造函数中发生。从Axon的角度来看,挑战是您需要一个实例来对其应用事件。但是,只有在构造函数完成后,该实例才可用。

andThenApply函数正是为此目的而提供的(并且您正在正确使用它)。但是,在您的情况下,代码(错误地)评估得太早了。我必须在本地运行您的代码并进行调试,以找出实际发生的情况。

根本原因是andThenApply的{​​{1}}实现调用AnnotatedAggregate而不是apply。前者将看到它当前正在执行延迟的任务,并在这些任务结束时安排实际的发布。下一个任务执行相同的操作。因此,两个事件最终都首先被创建,然后在它们都被创建之后再发布。

您是否有兴趣将此问题作为Axon issue tracker中的问题?这样,学分就可以归类。