prooph / snapshotter

Take aggregate snapshots with ease
http://getprooph.org
BSD 3-Clause "New" or "Revised" License
19 stars 11 forks source link

Not working with one stream for all #34

Open prolic opened 6 years ago

prolic commented 6 years ago

See https://github.com/prooph/proophessor-do/issues/158

basz commented 3 years ago

Hi!

I think I'm hitting this too. I recently introduced multiple aggregate types in one stream and noticed some snapshotters are not running. I have created a patch that seems to solve it. But as this package is deprecated (and my patch isn't backwards compatible) what are the changes this would get merged and released?

The gist of it is; instead of CustomerRepository accepting a single aggregateRepository and multiple types I tweaked it into accepting multiple repositories.

SnapshotReadModelFactory

public function __invoke(ContainerInterface $container): SnapshotReadModel
{
    return new SnapshotReadModel(
        [
            $container->get(CustomerRepository::class),
            $container->get(OrderLeadRepository::class)
        ],
        new AggregateTranslator(),
        $snapshotStore,
        [
            \HF\Api\Domain\Customer\Aggregate\Customer::class,
            \HF\Api\Domain\Customer\Aggregate\OrderLead::class,
        ]
    );
}

and the changed the persist method to try all repositories

SnapshotReadModel::persist

public function persist(): void
    {
        foreach (\array_unique($this->aggregateCache) as $aggregateId) {
            foreach($this->aggregateRepositories as $aggregateRepository) {
                $aggregateRoot = $aggregateRepository->getAggregateRoot($aggregateId);

                if ($aggregateRoot) {
                    break;
                }
            }

            $this->snapshotStore->save(new Snapshot(
                (string) AggregateType::fromAggregateRoot($aggregateRoot),
                $aggregateId,
                $aggregateRoot,
                $this->aggregateTranslator->extractAggregateVersion($aggregateRoot),
                new \DateTimeImmutable('now', new \DateTimeZone('UTC'))
            ));
        }

        foreach($this->aggregateRepositories as $aggregateRepository) {
            $aggregateRepository->clearIdentityMap();
        }

        $this->aggregateCache = [];
    }
prolic commented 3 years ago

instead of going

[
    $container->get(CustomerRepository::class),
    $container->get(OrderLeadRepository::class)
]

can we use a AggregateRepository implementation that wraps multiple repository inside itself?