phpevent-sourcingprooph

How to solve incompatibility of InMemoryEventStore and PdoEventStore in Prooph?


I am testing my command handlers somehow like this:

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

    $this->whenHandleCommand($fooCommand);

    $this->thenFooEventIsPublished();
}

Basically, I am testing only happy scenario when there is no validation logic in command handler. I test it by checking that expected event was published to event bus. Before dispatching tested command into command bus in whenHandleCommand method, I start recording dispatched events, something like:

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

and in the end I just check recorded events and assert that it's what I have expected. But I have a problem with switching between MysqlEventStore and InMemoryEventStore, because MysqlEventStore is not transactional (and thus emitting events in saveAggregateRoot method), instead of InMemoryEventStore that is transactional (and thus emitting events in commit method).

My repository save method is as simple as:

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

How to make it so that I can change whatever eventstore (memory or pdo) I want to use and it will work? Should i have condition if($this->isTransactionalEventStore()) (then begin transaction and commit) in my repository for that? I dont like that. :(

Why there is only InMemoryEventStore that is transactional? Should not be better to have both InMemoryTransactionalEventStore and InMemoryEventStore? Because I want my tests run with InMemoryEventStore, while normally I use PdoEventStore.

EDIT: When I change line 100 in InMemoryEventStoreFactory to

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

and make InMemoryEventStore implements EventStore instead of TransactionalEventStore, everything works just fine. So either I am somehow not using prooph correctly and it is not needed, or it can be fixed easilly by PR with splitting ImMemoryEventStore to InMemoryTransactionalEventStore and InMemoryEventStore?


Solution

  • That's a very valid question. The problem is, that I didn't think about this use-case when working on the v7 event-store implementation. A workaround is to wrap with the ActionEventEmitterEventStore, as you described. A non transactional in memory event store however, would be the better alternative (which is not present at the time).

    Currently the InMemoryEventStore is transactional, so removing that functionality and put it into TransactionalInMemoryEventStore would be a BC break, that we cannot do without a new major version. That's why I think, we should create a new implementation called NonTransactionalInMemoryEventStore. I created a ticket here: https://github.com/prooph/event-store/issues/307. Wanna take it over and provide a PR?