错误事件触发了EventSourceHandler?

时间:2020-01-20 02:52:46

标签: java spring-boot axon

我遇到了一个触发事件的问题,我认为这是不应该的。 我正在与轴突一起玩,并且正在基于发信事件对发信服务进行建模。我的例子很简单。

我设计了两个输入命令ScheduleLetterCommand,它们将在几分钟内“发送一个字母” ...如果在该时间段内发送另一个命令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)

1 个答案:

答案 0 :(得分:3)

@GoldFish是您要注意的框架,它根据发布的事件来采购您的聚合。 因此,简而言之,您会看到“活动中的事件源”。

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

因此,如果您发送命令取消此汇总的字母,它将首先根据事件重新创建汇总。仅在解决此问题后,该命令才实际分配给带有注释的@CommandHandler方法。

希望这可以为您@GoldFish澄清一下!