重建Read Side DB时事件发生故障

时间:2018-07-13 21:57:13

标签: asynchronous messaging cqrs event-sourcing mediatr

我有一个事件源系统,现在正在实现一个端点,该端点将从事件存储事件中重建读取侧数据存储。但是,我现在在处理事件方面遇到了似乎并发的问题。

我决定在重建过程中使用事件处理程序代码来处理事件。在系统的正常状态下(不是读取侧db重建),我的事件处理程序侦听它们订阅的事件并相应地更新投影。但是,当通过它们的事件处理程序在线处理这些事件时,我看到读取侧数据库的最终状态不一致的结果(即使它到达那里,有时也不会)。 我想这意味着他们的执行顺序混乱。

我不应该以这种方式使用事件处理程序吗?我认为由于我正在处理事件,因此以这种方式重用事件处理程序将是非常合适的。


我正在使用 MediatR 进行服务消息传递。所有事件处理程序都实现INotificationHandler

以下是代码示例:

IEnumerable<IEvent> events = await _eventRepo.GetAllAggregateEvents(aggId);
int eventNumber = 0;
foreach (var e in events)
{
    if (e.Version != eventNumber + 1)
        throw new EventsOutOfOrderException("Events were out of order while rebuilding DB");

    var ev = e as Event;
    // publish different historic events to event handlers which work with read DBs

    switch (e.Type)
    {
        case EventType.WarehouseCreated:
            WarehouseCreated w = new WarehouseCreated(ev);
            await _mediator.Publish(w);
            break;
        case EventType.BoxCreated:
            BoxCreated b = new BoxCreated(ev);
            await _mediator.Publish(b);
            break;
        case EventType.BoxLocationChanged:
            BoxLocationChanged l = new BoxLocationChanged(ev);
            await _mediator.Publish(l);
            break;
    }
    eventNumber++;    
}

我已经尝试将await关键字替换为对Wait()的调用。

类似_mediator.Publish(bcc).Wait()。 但这似乎不是一个好主意,因为它背后有异步代码。也不起作用。

我还尝试了排队事件的版本,让事件类型的案例在发布事件之前一直等到其版本位于队列的顶部。

类似的东西:

    case EventType.BoxContentsChanged:
        BoxContentsChanged bcc = new BoxContentsChanged(ev);
        while (eventQueue.Peek() != bcc.Version)
            continue;
        await _mediator.Publish(bcc);
        eventQueue.Dequeue();
        break;

这也不起作用。


无论如何-如果有人对如何解决此问题有任何想法,我将非常感激。我不希望以同步的方式复制所有异步事件处理程序代码。

1 个答案:

答案 0 :(得分:0)

我想最好的方法是同步,以确保一致性。这要求我在Replay服务中复制一些事件处理程序逻辑,并创建同步存储库方法。现在没有比赛条件,这很好。