From 6d4d24688dde838e57412110ed75393767931198 Mon Sep 17 00:00:00 2001 From: David Badura Date: Sat, 3 Oct 2026 13:40:40 +0200 Subject: [PATCH] Add 4.0 upgrade guide and remove hydrator enabled option The hydrator option could no longer be disabled since the legacy hydrator is gone, so the enabled flag is removed. Also fix the configuration docs that still described dbal_aggregate and the old cryptography options. --- docs/UPGRADE-4.0.md | 212 ++++++++++++++++++ docs/configuration.md | 37 ++- docs/installation.md | 4 +- docs/project.json | 4 + src/DependencyInjection/Configuration.php | 2 - .../PatchlevelEventSourcingBundleTest.php | 1 - 6 files changed, 235 insertions(+), 25 deletions(-) create mode 100644 docs/UPGRADE-4.0.md diff --git a/docs/UPGRADE-4.0.md b/docs/UPGRADE-4.0.md new file mode 100644 index 00000000..1db502ab --- /dev/null +++ b/docs/UPGRADE-4.0.md @@ -0,0 +1,212 @@ +--- +searchable: false +--- +# Upgrade 4.0 + +## Dependencies + +The bundle now requires `patchlevel/event-sourcing` 4.0 and `patchlevel/hydrator` 2.0. +Both libraries bring their own breaking changes, for example renamed identifier classes, +removed stores or a new upcaster interface. +Follow the [event-sourcing upgrade guide](https://github.com/patchlevel/event-sourcing/blob/4.0.x/docs/UPGRADE-4.0.md) +and the [hydrator upgrade guide](https://github.com/patchlevel/hydrator/blob/2.0.x/UPGRADE-2.0.md) for these. +This guide only covers the changes of the bundle itself. + +## Subscription + +### Retry Strategy + +The deprecated `retry_strategy` option has been removed. Use `retry_strategies` instead. +The `Patchlevel\EventSourcing\Subscription\RetryStrategy\RetryStrategy` service alias has been removed too, +inject the `RetryStrategyRepository` instead. + +before: + +```yaml +patchlevel_event_sourcing: + subscription: + retry_strategy: + base_delay: 5 + delay_factor: 2 + max_attempts: 5 +``` +after: + +```yaml +patchlevel_event_sourcing: + subscription: + retry_strategies: + default: + type: clock_based + options: + base_delay: 5 + delay_factor: 2 + max_attempts: 5 +``` +### SubscriberHelper + +The `SubscriberHelper` service is no longer registered, because the class has been removed from the library. +See the [event-sourcing upgrade guide](https://github.com/patchlevel/event-sourcing/blob/4.0.x/docs/UPGRADE-4.0.md#subscriberhelper-and-subscriberutil) +for the replacement. + +## Store + +### Store Type + +The store type `dbal_aggregate` has been removed together with the `DoctrineDbalStore`. +The default store type is now `dbal_stream`. +The new store type `dbal_taggable` is available for the DCB feature. + +before: + +```yaml +patchlevel_event_sourcing: + store: + type: dbal_aggregate +``` +after: + +```yaml +patchlevel_event_sourcing: + store: + type: dbal_stream +``` +:::danger +The `dbal_stream` store uses a different table structure than `dbal_aggregate`. +Migrate your events with the `migrate_to_new_store` option and the `event-sourcing:store:migrate` command +while you are still on 3.x, otherwise your events can no longer be read. +::: + +### Read Only Mode + +`read_only` is now only supported by the `dbal_stream` store. +For `dbal_taggable`, `in_memory` and `custom` an exception is thrown at container compile time. + +### StoreMigrateCommand + +The deprecated `Patchlevel\EventSourcingBundle\Command\StoreMigrateCommand` has been removed. +Use `Patchlevel\EventSourcing\Console\Command\StoreMigrateCommand` from the library instead. +The command name `event-sourcing:store:migrate` stays the same. + +## Hydrator + +### Legacy Hydrator + +The legacy `MetadataHydrator` has been removed, the bundle always uses the `StackHydrator` now. +For this reason the `hydrator.enabled` option has been removed too. +Remove `hydrator: true` or `enabled` from your configuration, the other `hydrator` options stay the same. + +before: + +```yaml +patchlevel_event_sourcing: + hydrator: + enabled: true + default_lazy: true +``` +after: + +```yaml +patchlevel_event_sourcing: + hydrator: + default_lazy: true +``` + +Together with the legacy hydrator, the guesser integration has been removed: +the `event_sourcing.hydrator.guesser` tag and the autoconfiguration for `Patchlevel\Hydrator\Guesser\Guesser` no longer exist. +Register your guesser in a hydrator extension with `$builder->addGuesser()` instead. +Services implementing `Patchlevel\Hydrator\Extension` are registered automatically. + +### Cryptography + +The root `cryptography` option has been removed. Use `hydrator.cryptography` instead. +The options `use_encrypted_field_name` and `fallback_to_field_name` have been removed without replacement. + +before: + +```yaml +patchlevel_event_sourcing: + cryptography: + algorithm: 'aes-256-gcm' + use_encrypted_field_name: true +``` +after: + +```yaml +patchlevel_event_sourcing: + hydrator: + cryptography: + algorithm: 'aes-256-gcm' +``` +:::danger +Data encrypted with the legacy cryptography can no longer be decrypted. +Migrate your store and snapshots to the new format while you are still on 3.x, +see the [event-sourcing upgrade guide](https://github.com/patchlevel/event-sourcing/blob/4.0.x/docs/UPGRADE-4.0.md#sensitive-data). +::: + +### Upcaster + +The `UpcasterChain` service and the `Patchlevel\EventSourcing\Serializer\Upcast\Upcaster` alias have been removed. +Upcasters now implement `Patchlevel\Hydrator\Extension\Upcast\Upcaster` and are registered automatically. +The bundle adds them to the `UpcastExtension` of the hydrator. +Services tagged with `event_sourcing.upcaster` still work and are sorted by the `priority` attribute. + +### SymfonyUuidNormalizer + +The deprecated `Patchlevel\EventSourcingBundle\Normalizer\SymfonyUuidNormalizer` has been removed. +Use `Patchlevel\EventSourcingBundle\Normalizer\UidNormalizer` instead. + +before: + +```php +use Patchlevel\EventSourcingBundle\Normalizer\SymfonyUuidNormalizer; +use Symfony\Component\Uid\Uuid; + +final class ProfileCreated +{ + public function __construct( + #[SymfonyUuidNormalizer] + public readonly Uuid $profileId, + ) { + } +} +``` +after: + +```php +use Patchlevel\EventSourcingBundle\Normalizer\UidNormalizer; +use Symfony\Component\Uid\Uuid; + +final class ProfileCreated +{ + public function __construct( + #[UidNormalizer] + public readonly Uuid $profileId, + ) { + } +} +``` +## Command Bus + +The deprecated `aggregate_handlers` option has been removed. Use `command_bus` instead. + +before: + +```yaml +patchlevel_event_sourcing: + aggregate_handlers: + bus: command.bus +``` +after: + +```yaml +patchlevel_event_sourcing: + command_bus: + service: command.bus +``` +## Value Resolver + +`Patchlevel\EventSourcingBundle\ValueResolver\AggregateRootIdValueResolver` has been renamed to +`Patchlevel\EventSourcingBundle\ValueResolver\IdentifierValueResolver`. +It now resolves every controller argument that implements `Patchlevel\EventSourcing\Identifier\Identifier`. +You only have to change something if you reference the class directly, e.g. in `#[ValueResolver]`. diff --git a/docs/configuration.md b/docs/configuration.md index 285fc9c1..8beb9871 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -216,8 +216,8 @@ patchlevel_event_sourcing: ``` Following store types are available: -- `dbal_aggregate` *default (deprecated)* -- `dbal_stream` *recommended* +- `dbal_stream` *default* +- `dbal_taggable` *required for DCB* - `in_memory` - `custom` @@ -237,7 +237,7 @@ patchlevel_event_sourcing: ``` ### Read Only Mode -For `dbal_aggregate` and `dbal_stream` store types you can activate the read only mode. +For the `dbal_stream` store type you can activate the read only mode. Readings are possible, but if you try to write, an exception `StoreIsReadOnly` is thrown. ```yaml @@ -286,17 +286,18 @@ patchlevel_event_sourcing: If you want to migrate from your current store to a new store, you can use the following configuration. This register a new store and a new cli command `event-sourcing:store:migrate`. You can define translators to translate the old events to the new store. -Here is an example for a migration from `dbal_aggregate` to `dbal_stream`. +Here is an example for a migration from `dbal_stream` to `dbal_taggable`, +which adds the event tags to the existing events. ```yaml patchlevel_event_sourcing: store: migrate_to_new_store: - type: 'dbal_stream' + type: 'dbal_taggable' options: - table_name: 'my_stream_store' + table_name: 'my_taggable_store' translators: - - Patchlevel\EventSourcing\Message\Translator\AggregateToStreamHeaderTranslator + - Patchlevel\EventSourcing\Message\Translator\ExtractEventTagTranslator ``` :::danger Make sure that you use different table names for the old and new store. @@ -669,29 +670,25 @@ You can find out more about snapshots [here](https://event-sourcing.patchlevel.i ## Cryptography -You can use the library to encrypt and decrypt personal data. -For this you need to enable the crypto shredding. +You can use the library to encrypt and decrypt sensitive data. +For this you need to enable the cryptography extension of the hydrator. ```yaml patchlevel_event_sourcing: - cryptography: - use_encrypted_field_name: true + hydrator: + cryptography: true ``` -:::tip -You should activate `use_encrypted_field_name` to mark the fields that are encrypted. -That allows you later to migrate not encrypted fields to encrypted fields. -If you have already encrypted fields, you can activate `fallback_to_field_name` to use the old field name as fallback. -::: - +The cipher keys are stored in the same database as the event store. If you want to use another algorithm, you can specify this here: ```yaml patchlevel_event_sourcing: - cryptography: - algorithm: 'aes-256-gcm' + hydrator: + cryptography: + algorithm: 'aes-256-gcm' ``` :::note -You can find out more about personal data [here](https://event-sourcing.patchlevel.io/latest/personal_data/). +You can find out more about sensitive data [here](https://event-sourcing.patchlevel.io/latest/sensitive-data/). ::: ## Clock diff --git a/docs/installation.md b/docs/installation.md index bef677db..f023176d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -49,8 +49,8 @@ patchlevel_event_sourcing: gap_detection: ~ # enable this if you want to use sensitive data encryption - #cryptography: ~ - # use_encrypted_field_name: true + #hydrator: + # cryptography: true when@dev: patchlevel_event_sourcing: diff --git a/docs/project.json b/docs/project.json index cfdca365..0dde3ec6 100644 --- a/docs/project.json +++ b/docs/project.json @@ -19,6 +19,10 @@ { "title": "Usage", "file": "usage.md" + }, + { + "title": "Upgrade from 3.x", + "file": "UPGRADE-4.0.md" } ] } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index e16f314e..85096bff 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -82,7 +82,6 @@ * clock: array{freeze: ?string, service: ?string}, * dcb: array{enabled: bool}, * hydrator: array{ - * enabled: bool, * default_lazy: bool, * cryptography: array{ * enabled: bool, @@ -335,7 +334,6 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->arrayNode('hydrator') - ->canBeDisabled() ->addDefaultsIfNotSet() ->children() ->booleanNode('default_lazy')->defaultFalse()->end() diff --git a/tests/Unit/PatchlevelEventSourcingBundleTest.php b/tests/Unit/PatchlevelEventSourcingBundleTest.php index cb4e2736..48944bf6 100644 --- a/tests/Unit/PatchlevelEventSourcingBundleTest.php +++ b/tests/Unit/PatchlevelEventSourcingBundleTest.php @@ -1360,7 +1360,6 @@ public function testHydrator(): void 'patchlevel_event_sourcing' => [ 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], 'hydrator' => [ - 'enabled' => true, 'lifecycle' => ['enabled' => true], 'cryptography' => ['enabled' => true], ],