EventSourceHandler 被错误的事件触发?

EventSourceHandler being triggered by the wrong event?

我遇到了一个问题,触发了一个我认为不应该触发的事件。 我正在玩轴突,并且正在根据信件发送事件对信件发送服务进行建模。我的例子有点琐碎。

我设计了两个输入命令 ScheduleLetterCommand,它们将在几分钟内 "send a letter"...这允许用户在这段时间内发送另一个命令 CancelLetterCommand 时取消它期间。

我正在通过 REST API 控制器触发命令...

我希望看到的是日志语句,如果我要安排一封信并在接下来的五分钟内立即将其取消,则说明一封信已安排和取消。

令我好奇的是,这封信已成功安排,我看到以下日志语句:

Received schedule command for letter id e6e037be-3b6d-4ae3-80cd-12426adcd526
LetterScheduledEvent e6e037be-3b6d-4ae3-80cd-12426adcd526 SCHEDULED

但是当我取消这封信时,我看到了这个行为:

LetterScheduledEvent e6e037be-3b6d-4ae3-80cd-12426adcd526 SCHEDULED
Received cancel command for letter id e6e037be-3b6d-4ae3-80cd-12426adcd526
Letter e6e037be-3b6d-4ae3-80cd-12426adcd526 cancelled CANCELLED

我在这里错过了什么?为什么 LetterScheduledEvent 处理程序再次被触发?

这是我的汇总 -

public class Letter {

    @AggregateIdentifier
    private String letterId;
    private ScheduleToken scheduleToken;

    @SuppressWarnings("UnusedDeclaration")
    protected Letter() {
        // Default constructor required by Axon Framework
    }

    @CommandHandler
    public Letter(ScheduleLetterCommand cmd, EventScheduler scheduler) {
        String id = cmd.getLetterId();
        log.info("Received schedule command for letter id {}", letterId);
        AggregateLifecycle.apply(new LetterScheduledEvent(id, LetterEventType.SCHEDULED));
        this.scheduleToken = scheduler.schedule(Duration.ofMinutes(5), new BeginSendLetterEvent(id,LetterEventType.BEGIN_SEND));
    }

    @CommandHandler
    public void handle(CancelLetterCommand cmd, EventScheduler eventScheduler) {
        String letterId = cmd.getLetterId();
        log.info("Received cancel command for letter id {}", letterId);
        AggregateLifecycle.apply(new LetterCancelledEvent(letterId, LetterEventType.CANCELLED));
        eventScheduler.cancelSchedule(scheduleToken);
    }

    @EventSourcingHandler
    public void on(LetterScheduledEvent event) {
        log.info("LetterScheduledEvent {} {}", event.getLetterId(), event.getEventType());
        this.letterId = event.getLetterId();
    }

    @EventSourcingHandler
    public void on(LetterCancelledEvent event) {
        log.info("Letter {} cancelled {}", event.getLetterId(), event.getEventType());
        scheduleToken = null;
    }

    @EventSourcingHandler
    public void on(BeginSendLetterEvent event) {
        log.info("Letter sending process started {} {}", event.getLetterId(), event.getEventType());
        //complicated letter sending processes...
        AggregateLifecycle.apply(new LetterSentEvent(event.getLetterId(), LetterEventType.SENT));
    }

    @EventSourcingHandler
    public void on(LetterSentEvent event) {
        log.info("Letter sent {} {}", event.getLetterId(), event.getEventType());
    }
}

这是我的活动 ->

abstract class LetterMovementEvent(open val letterId: String, open val eventType: LetterEventType)

enum class LetterEventType {
    SCHEDULED,
    CANCELLED,
    BEGIN_SEND,
    SENT
}

data class LetterScheduledEvent(
        override val letterId: String,
        override val eventType: LetterEventType = LetterEventType.SCHEDULED
) : LetterMovementEvent(letterId, eventType)

data class LetterCancelledEvent(
        override val letterId: String,
        override val eventType: LetterEventType = LetterEventType.CANCELLED
) : LetterMovementEvent(letterId, eventType)

data class BeginSendLetterEvent(
        override val letterId: String,
        override val eventType: LetterEventType = LetterEventType.BEGIN_SEND
) : LetterMovementEvent(letterId, eventType)

data class LetterSentEvent(
        override val letterId: String,
        override val eventType: LetterEventType = LetterEventType.SENT
) : LetterMovementEvent(letterId, eventType)

您注意到的@GoldFish 是一个框架,它根据已发布的事件来获取您的聚合数据。 所以,简而言之,您会看到 "Event Sourcing in action".

通过 Letter 聚合中的 @EventSourcingHandler 注释,您已经有效地创建了用于基于事件重新创建聚合的方法。

因此,如果您发送命令取消此聚合的字母,它将首先从事件中重新创建聚合。只有解决此问题后,命令才会实际提​​供给 @CommandHandler 注释方法。

希望这能为你澄清@GoldFish!