From b36cf0a0e231bd8bdd8172b6360faaa84dacc10d Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 30 Oct 2017 09:18:29 +0100 Subject: [PATCH 01/10] Add initial documentation structure --- doc/bookdown.json | 12 +++++---- doc/configuration_reference.md | 20 +++++++++++++++ doc/event_store.md | 1 + doc/getting_started.md | 47 ++++++++++++++++++++++++++++++++++ doc/projection_manager.md | 1 + 5 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 doc/configuration_reference.md create mode 100644 doc/event_store.md create mode 100644 doc/getting_started.md create mode 100644 doc/projection_manager.md diff --git a/doc/bookdown.json b/doc/bookdown.json index f20ce2d..f4adf6e 100644 --- a/doc/bookdown.json +++ b/doc/bookdown.json @@ -1,12 +1,14 @@ { "title": "prooph event-store Symfony bundle", "content": [ - {"getting-started": "book/getting-started/bookdown.json"}, - {"reference": "book/reference/bookdown.json"}, - {"contribute": "book/contribute/bookdown.json"} + {"intro": "../README.md"}, + {"getting_started": "getting_started.md"}, + {"event_store": "event_store.md"}, + {"projection_manager": "projection_manager.md"}, + {"configuration_reference": "configuration_reference.md"} ], "target": "./html", "tocDepth": 2, - "template": "../vendor/tobiju/bookdown-bootswatch-templates/templates/main.php", - "copyright": "Copyright (c) 2016 prooph software GmbH
Powered by Bookdown Bootswatch Templates" + "template": "../vendor/prooph/bookdown-template/templates/main.php", + "copyright": "Copyright (c) 2017 prooph software GmbH
Powered by Bookdown Bootswatch Templates" } diff --git a/doc/configuration_reference.md b/doc/configuration_reference.md new file mode 100644 index 0000000..5628322 --- /dev/null +++ b/doc/configuration_reference.md @@ -0,0 +1,20 @@ +# Configuration Reference + +```yaml +prooph_event_store: + stores: + acme_store: + event_store: Prooph\EventStore\Pd\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 + projection_managers: + event_store: Prooph\EventStore\Pd\MysqlEventStore + connection: 'doctrine.pdo.connection' + projections: + user_projection: + read_model: Prooph\ProophessorDo\Projection\User\UserReadModel + projection: Prooph\ProophessorDo\Projection\User\UserProjection +``` diff --git a/doc/event_store.md b/doc/event_store.md new file mode 100644 index 0000000..528759a --- /dev/null +++ b/doc/event_store.md @@ -0,0 +1 @@ +# Event Store diff --git a/doc/getting_started.md b/doc/getting_started.md new file mode 100644 index 0000000..71e54da --- /dev/null +++ b/doc/getting_started.md @@ -0,0 +1,47 @@ +# Getting started + +This documentation covers just the configuration of the Prooph Event Store in Symfony. +To inform yourself about the Event Store please have a look at the +[official documentation](http://docs.getprooph.org/event-store/). + +## Download the Bundle + +Download the bundle using composer by running +```bash +composer require prooph/event-store-symfony-bundle +``` +at the root of your Symfony project. + +## Enable the Bundle + +To start using this bundle, register the bundle in your application's kernel class: +```php + ['all' => true], +]; +``` diff --git a/doc/projection_manager.md b/doc/projection_manager.md new file mode 100644 index 0000000..901d21d --- /dev/null +++ b/doc/projection_manager.md @@ -0,0 +1 @@ +# Projection Manager From 0e54945044ea586bdc89e6f2141c2f754b5dcb17 Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 30 Oct 2017 12:48:50 +0100 Subject: [PATCH 02/10] Document the Event Store Bus Bridge --- doc/bookdown.json | 1 + doc/event_store_bus_bridge.md | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 doc/event_store_bus_bridge.md diff --git a/doc/bookdown.json b/doc/bookdown.json index f4adf6e..e134175 100644 --- a/doc/bookdown.json +++ b/doc/bookdown.json @@ -5,6 +5,7 @@ {"getting_started": "getting_started.md"}, {"event_store": "event_store.md"}, {"projection_manager": "projection_manager.md"}, + {"event_store_bus_bridge": "event_store_bus_bridge.md"}, {"configuration_reference": "configuration_reference.md"} ], "target": "./html", diff --git a/doc/event_store_bus_bridge.md b/doc/event_store_bus_bridge.md new file mode 100644 index 0000000..bd9ee57 --- /dev/null +++ b/doc/event_store_bus_bridge.md @@ -0,0 +1,64 @@ +# Event Store Bus Bridge + +While both the Prooph Event Store Symfony Bundle and the [Prooph Service Bus Symfony Bundle](https://github.com/prooph/service-bus-symfony-bundle/) +are useful on its own, usually you want to use both together. + +To combine them, you will need the [Prooph Event Store Bus Bridge](https://github.com/prooph/event-store-bus-bridge) +that can be required with composer: + +```bash +composer require prooph/event-store-bus-bridge +``` + +There are three locations where we can combine both bundles. + +## Transaction Manager + +The transaction manager starts a new event store transaction on every command dispatch and commits its afterwards. +To enable it for an Event Store, you need to add a service and tag it as a plugin for a service bus. + +Assuming that we have an Event Store named `acme_store` and a Service Bus named `acme_command_bus` +the configuration might look like this: + +```yaml +# app/config/services.yml +services: + prooph_event_store_bus_bridge.acme_transaction_manager: + class: Prooph\EventStoreBusBridge\TransactionManager + arguments: ['@prooph_event_store.acme_store'] + tags: + - { name: 'prooph_service_bus.acme_command_bus.plugin' } +``` + +## Event Publisher + +The Event Publisher is an Event Store Plugin which listens on the Event Store and publishes recorded message on the Event Bus. + +Assuming that we have an Event Store named `acme_store` and an Event Bus named `acme_event_bus` +the configuration might look like this: + +```yaml +# app/config/services.yml +services: + prooph_event_store_bus_bridge.acme_event_publisher: + class: Prooph\EventStoreBusBridge\EventPublisher + arguments: ['@prooph_service_bus.acme_event_bus'] + tags: + - { name: 'prooph_event_store.acme_store.plugin' } +``` + +## Causation Metadata Enricher + +The Causation Metadata Enricher will add causation metadata to each recorded event. + +To enable it for all command buses and all event stores you can use a configuration like this: + +```yaml +# app/config/services.yml +services: + prooph_event_store_bus_bridge.causation_metadata_enricher: + class: Prooph\EventStoreBusBridge\CausationMetadataEnricher + tags: + - { name: 'prooph_service_bus.command_bus.plugin' } + - { name: 'prooph_event_store.plugin' } +``` From fac6f40ba3554cceecbc6d812dc94662aab91ffb Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 30 Oct 2017 13:48:04 +0100 Subject: [PATCH 03/10] Document event stores --- doc/event_store.md | 237 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) diff --git a/doc/event_store.md b/doc/event_store.md index 528759a..6aeb9b1 100644 --- a/doc/event_store.md +++ b/doc/event_store.md @@ -1 +1,238 @@ # Event Store + +This documentation covers just the configuration of Prooph Event Stores in Symfony. +To inform yourself about the Prooph Event Store, please have a look at its +[official documentation](http://docs.getprooph.org/event-store/). + +## Setting up a MySQL PDO Event Store + +To setup a MySQL PDO Event Store we need the `prooph/pdo-event-store` package. + +```bash +composer require prooph/pdo-event-store +``` + +> **Hint**: You can also follow this instruction if you want to setup a PDO Event Store for MariaDB or PostgreSQL. +> You just need to use other classes which are also part of the `prooph/pdo-event-store` package. +> For further details please have a look at the [prooph/pdo-event-store package](https://github.com/prooph/pdo-event-store). + +Before we setup our event store, we need to setup some services: + +```yaml +# app/config/services.yml or (flex) config/packages/prooph_event_store.yaml +services: + prooph_event_store.pdo_mysql_event_store: + class: Prooph\EventStore\Pdo\MySqlEventStore + arguments: + - '@prooph_event_store.message_factory' + - '@pdo.connection' + - '@prooph_event_store.mysql.single_stream_strategy' + + prooph_event_store.mysql.single_stream_strategy: + class: Prooph\EventStore\Pdo\PersistenceStrategy\MySqlSingleStreamStrategy + + pdo.connection: + class: PDO + arguments: ['%dsn%'] +``` + +> **Hint**: For reusing a PDO connection from Doctrine please see below. + +> **Hint**: You can also use other stream strategies. +> Have a look at the documentation of the [prooph/pdo-event-store package](https://github.com/prooph/pdo-event-store/blob/master/docs/variants.md) +> to learn about the different strategies. + +Do not be confused about the fact that the we defined a service with a class called event store – we are not done yet. +But we are ready to configure the event store: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +prooph_event_store: + stores: + acme_store: + event_store: 'prooph_event_store.pdo_mysql_event_store' +``` + +> **Hint**: To get autocompletion in some IDEs you can prepend the service id +> with an `@` (`'@prooph_event_store.pdo_mysql_event_store'`). +> +> The bundle will recognize this and find your event store anyway. + +We configured our first event store. +To put data into the event store (and read them from it) we might want to add repositories. + +## Adding repositories to the event store + +If you are adding repositories to your event_store, you want to go for event sourcing. +Therefore we will explain how to add an event sourced repository. + +First you need to install another package, prooph/event-sourcing](http://docs.getprooph.org/event-sourcing/): + +```bash +composer require prooph/event-sourcing +``` + +Before we can start adding our repositories, we need to define another service: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +services: + prooph_event_sourcing.aggregate_translator: + class: Prooph\EventSourcing\EventStoreIntegration\AggregateTranslator +``` + +It will help our repository to translate the event stream into an aggregate and vice versa. + +We assume that there is + - a class `Acme\Prooph\Repository\EventStoreUserRepository` which extends `Prooph\EventSourcing\Aggregate\AggregateRepository` + - and a class `Acme\Model\User` which extends `Prooph\EventSourcing\AggregateRoot`. + +More information about Aggregate Roots and Aggregate Repositories can be found in the [official documentation](http://docs.getprooph.org/event-sourcing/). + +Now we can configure our repository: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +prooph_event_store: + stores: + acme_store: + event_store: 'prooph_event_store.pdo_mysql_event_store' + repositories: + Acme\Prooph\Repository\EventStoreUserRepository: + aggregate_type: Acme\Model\User + aggregate_translator: 'prooph_event_sourcing.aggregate_translator' +``` + +> **Hint**: To get autocompletion in some IDEs you can prepend the service id +> with an `@` (`'@prooph_event_sourcing.aggregate_translator'`). +> +> The bundle will recognize this and find your event store anyway. + +Now you can access the repository from the service container with the id `Acme\Prooph\Repository\EventStoreUserRepository`. + +> **Hint**: If you do not want your repositories to have their classes as service ids, +> you can configure them like this: +> ```yaml +> # app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +> prooph_event_store: +> stores: +> acme_store: +> event_store: 'prooph_event_store.pdo_mysql_event_store' +> repositories: +> acme.repository.prooph.event_store_user_repository: +> repository_class: Acme\Prooph\Repository\EventStoreUserRepository +> aggregate_type: Acme\Model\User +> aggregate_translator: 'prooph_event_sourcing.aggregate_translator' +> ``` +> This way your repository will be accessible with the service id `acme.repository.prooph.event_store_user_repository`. + +## Reusing a PDO connection from Doctrine + +If you already have a PDO connection configured through doctrine +and you want to use the same connection for your event store, +there is a simple way to reuse it: + +```yaml +# app/config/services.yaml +services: + prooph_event_store.connection.doctrine_pdo_connection: + class: PDO + factory: ['@doctrine.dbal.default_connection', getWrappedConnection] +``` + +## Plugins + +A prooph Event Store can be expanded using plugins. +If you want to know more about Event Store Plugins, please have a look at the [official documentation](http://bgfa854:8080/event_store.html#3-1). + +Adding plugins to an Event Store is really simple. +Let's assume that we already have a class implementing `Prooph\EventStore\Plugin\Plugin` +and that we have configured it as service: + +```yaml +# app/config/services.yml +services: + acme.prooph.plugins.example_plugin: + class: Acme\Prooph\Plugins\ExamplePlugin +``` + +To attaching the plugin to an Event Store, we just need to tag it with `prooph_event_store..plugin`. +So if our Event Store is named `acme_store`, it would look like this: + +```yaml +# app/config/services.yml +services: + acme.prooph.plugins.example_plugin: + class: Acme\Prooph\Plugins\ExamplePlugin + tags: + - { name: 'prooph_event_store.acme_store.plugin' } +``` + +If you cant to attach to plugin to multiple Event Stores, just tag it multiple times. +In the special case that you want to attach the plugin to **every** Event Store, +you can use the tag `prooph_event_store.plugin` instead. + +## Metadata enricher + +If you do not know what a metadata enricher is, please have a look at the official documentation of [Metadata enricher](http://docs.getprooph.org/event-store/event_store_plugins.html#3-3-4). + +Let's assume that we want to add the issuer of an event to the metadata. +Our Metadata enricher might look like this: + +```php +tokens = $tokens; + } + + public function enrich(Message $message): Message + { + if ($this->tokens->getToken()) { + $message = $message + ->withAddedMetadata('issuer_type', 'user') + ->withAddedMetadata('issuer_name', $this->tokens->getToken()->getUsername()); + } + return $message; + } +} +``` + +And our service definition like this: + +```yaml +# app/config/services.yml +services: + acme.prooph.metadata_enricher.issuer: + class: Acme\Prooph\MetadataEnricher\IssuerMetadataEnricher + arguments: ['@security.token_storage'] +``` + +To enable the enricher for every Event Store, we just need to tag the service: + +```yaml +# app/config/services.yml +services: + acme.prooph.metadata_enricher.issuer: + class: Acme\Prooph\MetadataEnricher\IssuerMetadataEnricher + arguments: ['@security.token_storage'] + tags: + - { name: 'prooph_event_store.metadata_enricher' } +``` + +But be careful, this tag would add the metadata enricher to **every** Event Store. +If you want to add it only to one store, you need to use the tag `prooph_event_store..metadata_enricher`. From cfe42b580152325d665498b26798a57eb56dcd5c Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 30 Oct 2017 13:48:21 +0100 Subject: [PATCH 04/10] Document the installation of the bundle --- doc/getting_started.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/getting_started.md b/doc/getting_started.md index 71e54da..a2777c3 100644 --- a/doc/getting_started.md +++ b/doc/getting_started.md @@ -45,3 +45,5 @@ return [ Prooph\Bundle\EventStore\ProophEventStoreBundle::class => ['all' => true], ]; ``` + +Now that you have installed the bundle you might want start with configuring an [Event Store](./event_store.html). From dd68956cbe4e709e381a882e1129628b251d272b Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 30 Oct 2017 15:34:37 +0100 Subject: [PATCH 05/10] Document how to configure a projection manager --- doc/projection_manager.md | 254 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) diff --git a/doc/projection_manager.md b/doc/projection_manager.md index 901d21d..a20cf45 100644 --- a/doc/projection_manager.md +++ b/doc/projection_manager.md @@ -1 +1,255 @@ # Projection Manager + +Projection Managers will help you to create persistent projections from your event stream. +For further information please have a look at the [official documentation](http://docs.getprooph.org/event-store/projections.html). + +Before you can setup an Projection Manager, you need to setup at least one [Event Store](./event_store.html). + +Then you can add a Projection Manager: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +prooph_event_store: + projection_managers: + acme_projection_manager: + event_store: 'prooph_event_store.pdo_mysql_event_store' + connection: 'pdo.connection' +``` + +Currently the bundle is limited to support Projection Managers for Event Stores +that are either part of the [prooph/pdo-event-store package](https://github.com/prooph/pdo-event-store) +or an `Prooph\EventStore\InMemoryEventStore`. +In the latter case you can omit the `connection`. + +Because a projection manager is worthless without connections he can manage, let's configure some projections. + +## Configure a projection + +To configure a projection we need a Projection before. + +Projections might either implement `Prooph\Bundle\EventStore\Projection` +or implement `Prooph\Bundle\EventStore\Projection\ReadModelProjection`. + +Both interfaces have just one method to configure the projection as explained in the [Event Store documentation](http://docs.getprooph.org/event-store/projections.html). + +To give one example from [proophessor-do-symfony](https://github.com/prooph/proophessor-do-symfony) +here is a Read Model: + +```php +connection = $connection; + } + + public function init(): void + { + $sql = <<connection->executeQuery($sql); + } + + public function isInitialized(): bool + { + $statement = $this->connection->executeQuery('SHOW TABLES LIKE read_todo;'); + return $statement->fetch() !== false; + } + + public function reset(): void + { + $this->connection->executeQuery('TRUNCATE TABLE read_todo;'); + } + + public function delete(): void + { + $this->connection->executeQuery('DROP TABLE read_todo;'); + } + + protected function insert(array $data): void + { + $this->connection->insert('read_todo', $data); + } + + protected function update(array $data, array $identifier): void + { + $this->connection->update('read_todo', $data, $identifier); + } +} +``` + +and the projection that uses the ReadModel: + +```php +fromStream('event_stream') + ->when([ + TodoWasPosted::class => function ($state, TodoWasPosted $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack('insert', [ + 'id' => $event->todoId()->toString(), + 'assignee_id' => $event->assigneeId()->toString(), + 'text' => $event->text()->toString(), + 'status' => $event->todoStatus()->toString(), + ]); + }, + TodoWasMarkedAsDone::class => function ($state, TodoWasMarkedAsDone $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['status' => $event->newStatus()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + TodoWasReopened::class => function ($state, TodoWasReopened $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['status' => $event->status()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + DeadlineWasAddedToTodo::class => function ($state, DeadlineWasAddedToTodo $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['deadline' => $event->deadline()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + ReminderWasAddedToTodo::class => function ($state, ReminderWasAddedToTodo $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['reminder' => $event->reminder()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + TodoWasMarkedAsExpired::class => function ($state, TodoWasMarkedAsExpired $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['status' => $event->newStatus()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + TodoWasUnmarkedAsExpired::class => function ($state, TodoWasUnmarkedAsExpired $event) { + /** @var TodoReadModel $readModel */ + $readModel = $this->readModel(); + $readModel->stack( + 'update', + ['status' => $event->newStatus()->toString()], + ['id' => $event->todoId()->toString()] + ); + }, + ]); + + return $projector; + } +} +``` + +A lot of code, but really simple one. Its configuration is shorter. +First we need to define a service definition for both: + +```yaml +# app/config/services.yml +services: + proophessor.projection.todo: + class: Prooph\ProophessorDo\Projection\Todo\TodoProjection + + proophessor.projection.read_model.todo: + class: Prooph\ProophessorDo\Projection\Todo\TodoReadModel +``` + +Now we have two possibilities to configure the projections. + +## Tags + +We can add a Tag to the projection: + +```yaml +# app/config/services.yml +services: + proophessor.projection.todo: + class: Prooph\ProophessorDo\Projection\Todo\TodoProjection + tags: + - { name: prooph_event_store.projection, projection_name: todo_projection, projection_manager: acme_projection_manager, read_model: 'proophessor.projection.read_model.todo' } + + proophessor.projection.read_model.todo: + class: Prooph\ProophessorDo\Projection\Todo\TodoReadModel +``` + +While the `projection_name` is freely selectable, the `projection_manager` must reference an existing Projection Manager +(like the one we configured above). +The `read_model` attribute is necessary only if the projection implements `Prooph\Bundle\EventStore\Projection\ReadModelProjection`. + +## Central + +If you do not like tags or want to configure your projections at a central place, +you can do this directly at the `projection_manager`: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +prooph_event_store: + projection_managers: + acme_projection_manager: + event_store: 'prooph_event_store.pdo_mysql_event_store' + connection: 'pdo.connection' + projections: + todo_projection: + read_model: 'proophessor.projection.read_model.todo' + projection: 'proophessor.projection.todo' +``` + +As with the tag the `read_model` is necessary only if the projection implements `Prooph\Bundle\EventStore\Projection\ReadModelProjection`. + +Since both ways will produce the same result, it is up to you which of them you choose. + +## Running projections From a2f987dff9de9b278dac6168616af4bffa881401 Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Mon, 25 Dec 2017 08:57:22 +0100 Subject: [PATCH 06/10] Fix typos and wrong urls --- doc/configuration_reference.md | 4 ++-- doc/event_store.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/configuration_reference.md b/doc/configuration_reference.md index 5628322..2ab25a0 100644 --- a/doc/configuration_reference.md +++ b/doc/configuration_reference.md @@ -4,14 +4,14 @@ prooph_event_store: stores: acme_store: - event_store: Prooph\EventStore\Pd\MysqlEventStore + 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 projection_managers: - event_store: Prooph\EventStore\Pd\MysqlEventStore + event_store: Prooph\EventStore\Pdo\MysqlEventStore connection: 'doctrine.pdo.connection' projections: user_projection: diff --git a/doc/event_store.md b/doc/event_store.md index 6aeb9b1..0ec7c9a 100644 --- a/doc/event_store.md +++ b/doc/event_store.md @@ -143,7 +143,7 @@ services: ## Plugins A prooph Event Store can be expanded using plugins. -If you want to know more about Event Store Plugins, please have a look at the [official documentation](http://bgfa854:8080/event_store.html#3-1). +If you want to know more about Event Store Plugins, please have a look at the [official documentation](http://docs.getprooph.org/event-store/event_store_plugins.html). Adding plugins to an Event Store is really simple. Let's assume that we already have a class implementing `Prooph\EventStore\Plugin\Plugin` From d5b260943552877a8d2926699499fe4868d67a4e Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Thu, 28 Dec 2017 22:18:20 +0100 Subject: [PATCH 07/10] Fix configuration reference --- doc/configuration_reference.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/configuration_reference.md b/doc/configuration_reference.md index 2ab25a0..269e396 100644 --- a/doc/configuration_reference.md +++ b/doc/configuration_reference.md @@ -11,10 +11,11 @@ prooph_event_store: aggregate_type: Prooph\ProophessorDo\Model\User\User aggregate_translator: prooph_event_sourcing.aggregate_translator projection_managers: - event_store: Prooph\EventStore\Pdo\MysqlEventStore - connection: 'doctrine.pdo.connection' - projections: - user_projection: - read_model: Prooph\ProophessorDo\Projection\User\UserReadModel - projection: Prooph\ProophessorDo\Projection\User\UserProjection + main_manager: + event_store: Prooph\EventStore\Pdo\MysqlEventStore + connection: 'doctrine.pdo.connection' + projections: + user_projection: + read_model: Prooph\ProophessorDo\Projection\User\UserReadModel + projection: Prooph\ProophessorDo\Projection\User\UserProjection ``` From 0bb5f8088fd10cdfb9126258cc025c2232b0f971 Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Fri, 16 Mar 2018 16:10:12 +0100 Subject: [PATCH 08/10] Enhance configuration reference --- doc/configuration_reference.md | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/doc/configuration_reference.md b/doc/configuration_reference.md index 269e396..22df3a9 100644 --- a/doc/configuration_reference.md +++ b/doc/configuration_reference.md @@ -4,18 +4,96 @@ prooph_event_store: stores: acme_store: + event_emitter: Prooph\Common\Event\ProophActionEventEmitter + wrap_action_event_emitter: true 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 + snapshot_store: ~ + stream_name: ~ + one_stream_per_aggregate: false projection_managers: main_manager: event_store: Prooph\EventStore\Pdo\MysqlEventStore connection: 'doctrine.pdo.connection' + event_streams_table: 'event_streams' + projection_table: 'projections' projections: user_projection: read_model: Prooph\ProophessorDo\Projection\User\UserReadModel projection: Prooph\ProophessorDo\Projection\User\UserProjection ``` + +## stores + +*Optional* + +This section contains the configuration of your event stores. +Please have a look at [the event store section](./event_store.md) of this documentation for further details. +The name of the event store will be part of its service id: `prooph_event_store.`. +So for the `acme_store` in our example above it will be `prooph_event_store.acme_store`. + +### event_emitter + +*Optional* + + +### wrap_action_event_emitter + +*Optional* + + +### event_store + +*Required* + + + +### repositories + +*Optional* + + +#### repository_class + +*Optional* + + +#### aggregate_type + +*Optional* + + +#### snapshot_store + +*Optional* + + +#### stream_name + +*Optional* + + +#### one_stream_per_aggregate + +*Optional* + + +## projection_managers + +### event_store + +### connection + +### event_streams_table + +### projection_table + +### projections + +#### read_model + +#### projection From 5c5b98b0bc332d1614e05683ae06a6e5518496ac Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Tue, 17 Apr 2018 11:24:37 +0200 Subject: [PATCH 09/10] Configure repositories for one_stream_pre_aggregate --- doc/event_store.md | 48 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/doc/event_store.md b/doc/event_store.md index 0ec7c9a..292293b 100644 --- a/doc/event_store.md +++ b/doc/event_store.md @@ -40,7 +40,8 @@ services: > **Hint**: You can also use other stream strategies. > Have a look at the documentation of the [prooph/pdo-event-store package](https://github.com/prooph/pdo-event-store/blob/master/docs/variants.md) -> to learn about the different strategies. +> to learn about the different strategies. +> See below for further information within this bundle. Do not be confused about the fact that the we defined a service with a class called event store – we are not done yet. But we are ready to configure the event store: @@ -140,6 +141,51 @@ services: factory: ['@doctrine.dbal.default_connection', getWrappedConnection] ``` +## Using different Stream Strategies + +To make yourself familiar with different stream strategies, +please have a look at the documentation of the [prooph/pdo-event-store package](https://github.com/prooph/pdo-event-store/blob/master/docs/variants.md). + +If you want to use one of the Single Stream Strategies, you just need to set up the Strategy as a service and pass it to the event store: + + +```yaml +# app/config/services.yml or (flex) config/packages/prooph_event_store.yaml +services: + prooph_event_store.pdo_mysql_event_store: + class: Prooph\EventStore\Pdo\MySqlEventStore + arguments: + - '@prooph_event_store.message_factory' + - '@pdo.connection' + - '@prooph_event_store.mysql.single_stream_strategy' + + prooph_event_store.mysql.single_stream_strategy: + class: Prooph\EventStore\Pdo\PersistenceStrategy\MySqlSingleStreamStrategy + + pdo.connection: + class: PDO + arguments: ['%dsn%'] +``` + +If you want to use one of the Aggregate Stream Strategies, +you also need to configure your Stream Strategie as a service like above. +But you also need to your repositories to follow this strategy using the `one_stream_per_aggregate` option: + +```yaml +# app/config/config.yml or (flex) config/packages/prooph_event_store.yaml +prooph_event_store: + stores: + acme_store: + event_store: 'prooph_event_store.pdo_mysql_event_store' + repositories: + Acme\Prooph\Repository\EventStoreUserRepository: + aggregate_type: Acme\Model\User + aggregate_translator: 'prooph_event_sourcing.aggregate_translator' + one_stream_per_aggregate: true +``` + +Because this option defaults to `false`, this is only necessary for Aggregate Stream Strategies. + ## Plugins A prooph Event Store can be expanded using plugins. From 3043aea57fddea2da999eb2de2ccb7ef15f18d0a Mon Sep 17 00:00:00 2001 From: Oskar Pfeifer-Bley Date: Tue, 17 Apr 2018 12:04:24 +0200 Subject: [PATCH 10/10] Add configuration reference for event stores --- doc/configuration_reference.md | 38 +++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/doc/configuration_reference.md b/doc/configuration_reference.md index 22df3a9..2579d21 100644 --- a/doc/configuration_reference.md +++ b/doc/configuration_reference.md @@ -34,53 +34,85 @@ prooph_event_store: This section contains the configuration of your event stores. Please have a look at [the event store section](./event_store.md) of this documentation for further details. The name of the event store will be part of its service id: `prooph_event_store.`. -So for the `acme_store` in our example above it will be `prooph_event_store.acme_store`. +For the `acme_store` in our example above it will be `prooph_event_store.acme_store`. ### event_emitter *Optional* +The event emitter that is used by the ActionEventEmitterEventStore. +It must be a class that implements `Prooph\Common\Event\ActionEventEmitter`. +The default value should be fine for most use cases. + ### wrap_action_event_emitter *Optional* +Should the given event store be decorated by an ActionEventEmitterEventStore? +In most cases you should keep this with the default value `true`. + ### event_store *Required* +The id of a service whose class implements `Prooph\EventStore\EventStore`. +Please have a look at [the event store section](./event_store.md) of this documentation for further details. ### repositories *Optional* +Defines the repository that you can use to load and store your aggregates. +For further details please have a look at [the event store section](./event_store.md) of this documentation. + #### repository_class -*Optional* +*Required* + +The FQCN of the repository. +In most cases it will be a subclass of `Prooph\EventSourcing\Aggregate\AggregateRepository` but it most not be, +it must just accept the same arguments in the constructor. #### aggregate_type -*Optional* +*Required* + +The FQCN of the aggregate that is loaded and stored by the repository. + + +## aggregate_translator +*Required* + +The service id of the aggregate translator that is used by the repository. +Its class must implement `Prooph\EventSourcing\Aggregate\AggregateTranslator`. #### snapshot_store *Optional* +The service id of a snap shot store. +Its class must implement `Prooph\SnapshotStore\SnapshotStore`. #### stream_name *Optional* +You can pass a string as custom stream name if you want. + #### one_stream_per_aggregate *Optional* +Should the repository create an own single stream for each aggregate? +See section *Using different Stream Strategies* for of [the event store section](./event_store.md) of this documentation for further details. + ## projection_managers