Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events get published while rollback transaction is open #27

Open
wazum opened this issue Mar 14, 2022 · 3 comments
Open

Events get published while rollback transaction is open #27

wazum opened this issue Mar 14, 2022 · 3 comments

Comments

@wazum
Copy link
Contributor

wazum commented Mar 14, 2022

Dispatching domain events after a terminate event with an open rollback transaction might lead to dispatched events which aren't really persisted yet (which contradicts the outbox pattern).

I stumbled upon this by accident when I saw a failing command producing Symfony messenger entries and solved it with this modified version of \Headsnet\DomainEventsBundle\EventSubscriber\PublishDomainEventSubscriber::publishEvents
(an instance of EntityManager is additionally injected via constructor)

    private function publishEvents(): void
    {
        // We definitely should not publish events during an open transaction (as events might not be persisted yet)
        if ($this->entityManager->getConnection()->isTransactionActive()) {
            return;
        }

        foreach ($this->eventStore->allUnpublished() as $event) {
            $this->publishEvent($event);
        }
    }

Is this the correct solution, or are there any other drawbacks I didn't think about @benr77 ?

@wazum
Copy link
Contributor Author

wazum commented Mar 14, 2022

The first idea was to add ->setCacheMode(Cache::MODE_REFRESH) to the query, but that had no effect and I found no other nice way to force a query on the actual database.

    $qb = $this->em->createQueryBuilder()
            ->setCacheMode(Cache::MODE_REFRESH)
            ->select('e')
            ->from(StoredEvent::class, 'e')
            ->where('e.publishedOn IS NULL')
            ->andWhere('e.occurredOn < :now')
            ->setParameter('now', $now)
            ->orderBy('e.occurredOn');

@benr77
Copy link
Contributor

benr77 commented Mar 17, 2022

I'm really not sure - I'm not very familiar with any of this. Is this part of the docs describing the Doctrine behaviour you are trying to manage:

https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/transactions.html#transaction-nesting

@wazum
Copy link
Contributor Author

wazum commented Mar 18, 2022

Yes, let's see if I can come up with a test case for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants