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

How to use SingleStreamStrategy? #40

Open
enumag opened this issue Mar 12, 2018 · 6 comments
Open

How to use SingleStreamStrategy? #40

enumag opened this issue Mar 12, 2018 · 6 comments

Comments

@enumag
Copy link
Member

enumag commented Mar 12, 2018

I'm trying to enable SingleStreamStrategy to fix performance issues in projections (see proophsoftware/es-emergency-call#5 for details).

For now I'm unable to get it working. EventStore still makes one stream per aggregate instead of per aggregate type. Here is my current configuration:

services:
    Prooph\EventStore\Pdo\PostgresEventStore:
        arguments: ['@messageFactory', '@eventStoreConnection', '@stream_strategy']

    stream_strategy:
        class: Prooph\EventStore\Pdo\PersistenceStrategy\PostgresSingleStreamStrategy

In the documentation I found a link to this example to initialize the streams. This creates one more stream in the database but the EventStore is still creating new streams for every new aggregate. Also the example is confusing. Shouldn't I create one stream for each aggregate type instead of just one stream?

@enumag enumag changed the title How to use SingleStreamStrategy How to use SingleStreamStrategy? Mar 12, 2018
@enumag
Copy link
Member Author

enumag commented Mar 12, 2018

Ok it seems it needs to be configured on each repository definition as well:

prooph_event_store:
    stores:
        acme_store:
            event_store: Prooph\EventStore\Pdo\MysqlEventStore
            repositories:
                todo_list:
                    repository_class: Prooph\ProophessorDo\Infrastructure\Repository\EventStoreUserCollection
                    aggregate_type: Prooph\ProophessorDo\Model\User\User
                    aggregate_translator: prooph_event_sourcing.aggregate_translator
                    # I was missing this line.
                    one_stream_per_aggregate: false

Now however eventstore only uses that one stream I created based on the example script linked above. All events from all aggregate types are mixed in this stream. How can I separate them to one stream per aggregate type?

@enumag
Copy link
Member Author

enumag commented Mar 12, 2018

Ok more progress. Looks like I need to override AggregateRepository::determineEventStream with this:

	protected function determineStreamName(string $aggregateId): StreamName
	{
		return new StreamName($this->aggregateType->toString());
	}

Now I need to correctly initialize the event streams which means I need to somehow ask prooph for names of all aggregate types that exist throughout the application. How can I do that?

@UFOMelkor
Copy link
Member

UFOMelkor commented Mar 12, 2018

@enumag You don't need to overwrite AggregateRepository::determineEventStream.
It should be enough to set the stream_name in the event-store configuration.

prooph_event_store:
    stores:
        acme_store:
            event_store: Prooph\EventStore\Pdo\MysqlEventStore
            repositories:
                todo_list:
                    repository_class: Prooph\ProophessorDo\Infrastructure\Repository\EventStoreUserCollection
                    aggregate_type: Prooph\ProophessorDo\Model\User\User
                    aggregate_translator: prooph_event_sourcing.aggregate_translator
                    one_stream_per_aggregate: false
                    # Set the stream name
                    stream_name: "what-ever-you-want"

Initializing of the stream is – in my setup – currently part of the database migration. Automation of this sounds tricky. But of course you could get the config of the event store bundle, grab all repositories, filter to get just the one with one stream per aggregate type and create them. I'm just not sure whether this is worth the trouble …

@enumag
Copy link
Member Author

enumag commented Mar 12, 2018

@UFOMelkor I didn't realize I need to put that to database migrations. Thanks for pointing it out.

Well this pretty much resolves this issue for me. But it is probably a good idea to add some notes to the documentation about how to setup the SingleStreamStrategy. As you can see I've spent some time to get it working so it's not exactly clear.

@UFOMelkor
Copy link
Member

Definitely – I will let the issue open for the documentation 👍

@webdevilopers
Copy link

There is a command by @gquemener that comes with the symfony recipe:

You can adapt it to your needs e.g.:

use Prooph\EventStore\EventStore;
use Prooph\EventStore\Stream;
use Prooph\EventStore\StreamName;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

final class CreateEventStreamCommand extends Command
{
    protected static $defaultName = 'acme:create-event-streams';

    /** @var EventStore $eventStore */
    private $eventStore;

    public function __construct(EventStore $eventStore)
    {
        $this->eventStore = $eventStore;

        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->eventStore->create(new Stream(new StreamName('foo_stream'), new \ArrayIterator()));
        $this->eventStore->create(new Stream(new StreamName('bar_stream'), new \ArrayIterator()));
    }
}

And then call it via acme:create-event-streams instead of the original call event-store:event-stream:create.

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

No branches or pull requests

3 participants