Как решить проблему несовместимости InMemoryEventStore и PdoEventStore в Prooph?

Я тестирую свои обработчики команд как-то так:

public function testHandle_ShouldPublishFooEvent(): void
{
    $fooCommand = $this->givenFooCommand();

    $this->whenHandleCommand($fooCommand);

    $this->thenFooEventIsPublished();
}

По сути, я тестирую только счастливый сценарий, когда в обработчике команд нет логики проверки. Я проверяю это, проверяя, что ожидаемое событие было опубликовано в шине событий. Перед отправкой проверенной команды в командную шину в методе whenHandleCommand я начинаю записывать отправленные события, что-то вроде:

$eventBus->attach(
    EventBus::EVENT_DISPATCH,
    function (ActionEvent $actionEvent) use ($events): void {
        $event = $actionEvent->getParam(MessageBus::EVENT_PARAM_MESSAGE);
        $events->addEvent($event);
    },
    -1000
);

и в конце я просто проверяю записанные события и утверждаю, что это то, что я ожидал. Но у меня проблема с переключением между MysqlEventStore а также InMemoryEventStore, так как MysqlEventStore не является транзакционным (и, следовательно, saveAggregateRoot метод), а не InMemoryEventStore это транзакция (и, следовательно, передача событий в методе коммитов).

Мой метод сохранения в хранилище так же прост:

class ProophFooRepository extends AggregateRepository implements FooRepository
{
    public function save(FooAggregate $foo): void
    {
        $this->saveAggregateRoot($foo);
    }
    ...
}

Как сделать так, чтобы я мог изменить любое хранилище событий (память или pdo), которое я хочу использовать, и оно будет работать? Должен ли я иметь условие if($this->isTransactionalEventStore()) (затем начать транзакцию и зафиксировать) в моем хранилище для этого? Мне это не нравится:(

Почему существует только InMemoryEventStore, который является транзакционным? Не должно быть лучше иметь оба InMemoryTransactionalEventStore а также InMemoryEventStore? Потому что я хочу, чтобы мои тесты запускались с InMemoryEventStore, в то время как обычно я использую PdoEventStore.

РЕДАКТИРОВАТЬ: Когда я изменяю строку 100 в InMemoryEventStoreFactory на

$wrapper = new ActionEventEmitterEventStore($eventStore, $eventEmitter);

и сделать InMemoryEventStore инвентарь EventStore вместо TransactionalEventStore, все работает просто отлично. Так что либо я как-то не правильно использую prooph и это не нужно, либо это можно исправить с помощью PR с помощью расщепления. ImMemoryEventStore в InMemoryTransactionalEventStore а также InMemoryEventStore?

1 ответ

Решение

Это очень правильный вопрос. Проблема в том, что я не думал об этом сценарии использования при работе с реализацией хранилища событий v7. Обходной путь - обернуть с помощью ActionEventEmitterEventStore, как вы описали. Однако нетранзакционный в хранилище событий памяти будет лучшей альтернативой (которой нет в данный момент).

В настоящее время InMemoryEventStore является транзакционным, поэтому удаление этой функциональности и помещение ее в TransactionalInMemoryEventStore было бы разрывом BC, что мы не можем сделать без новой основной версии. Вот почему я думаю, что мы должны создать новую реализацию под названием NonTransactionalInMemoryEventStore. Я создал тикет здесь: https://github.com/prooph/event-store/issues/307. Хотите взять это на себя и обеспечить PR?

Другие вопросы по тегам