2525use Patchlevel \EventSourcing \Clock \FrozenClock ;
2626use Patchlevel \EventSourcing \Clock \SystemClock ;
2727use Patchlevel \EventSourcing \CommandBus \CommandBus ;
28+ use Patchlevel \EventSourcing \CommandBus \InstantRetryCommandBus ;
2829use Patchlevel \EventSourcing \Console \Command \DatabaseCreateCommand ;
2930use Patchlevel \EventSourcing \Console \Command \DatabaseDropCommand ;
3031use Patchlevel \EventSourcing \Console \Command \DebugCommand ;
4445use Patchlevel \EventSourcing \Console \Command \WatchCommand ;
4546use Patchlevel \EventSourcing \Console \DoctrineHelper ;
4647use Patchlevel \EventSourcing \Cryptography \DoctrineCipherKeyStore ;
48+ use Patchlevel \EventSourcing \DCB \AttributeEventTagExtractor ;
49+ use Patchlevel \EventSourcing \DCB \DecisionModelBuilder ;
50+ use Patchlevel \EventSourcing \DCB \EventAppender ;
51+ use Patchlevel \EventSourcing \DCB \EventTagExtractor ;
52+ use Patchlevel \EventSourcing \DCB \StoreDecisionModelBuilder ;
53+ use Patchlevel \EventSourcing \DCB \StoreEventAppender ;
4754use Patchlevel \EventSourcing \EventBus \AttributeListenerProvider ;
4855use Patchlevel \EventSourcing \EventBus \Consumer ;
4956use Patchlevel \EventSourcing \EventBus \DefaultConsumer ;
6976use Patchlevel \EventSourcing \QueryBus \QueryBus ;
7077use Patchlevel \EventSourcing \Repository \DefaultRepositoryManager ;
7178use Patchlevel \EventSourcing \Repository \MessageDecorator \ChainMessageDecorator ;
79+ use Patchlevel \EventSourcing \Repository \MessageDecorator \EventTagDecorator ;
7280use Patchlevel \EventSourcing \Repository \MessageDecorator \MessageDecorator ;
7381use Patchlevel \EventSourcing \Repository \MessageDecorator \SplitStreamDecorator ;
7482use Patchlevel \EventSourcing \Repository \RepositoryManager ;
95103use Patchlevel \EventSourcing \Store \Store ;
96104use Patchlevel \EventSourcing \Store \StreamDoctrineDbalStore ;
97105use Patchlevel \EventSourcing \Store \StreamReadOnlyStore ;
106+ use Patchlevel \EventSourcing \Store \TaggableDoctrineDbalStore ;
98107use Patchlevel \EventSourcing \Subscription \Engine \CatchUpSubscriptionEngine ;
99108use Patchlevel \EventSourcing \Subscription \Engine \DefaultSubscriptionEngine ;
100109use Patchlevel \EventSourcing \Subscription \Engine \GapResolverStoreMessageLoader ;
@@ -189,6 +198,7 @@ public function load(array $configs, ContainerBuilder $container): void
189198 $ this ->configureMigration ($ config , $ container );
190199 $ this ->configureValueResolver ($ container );
191200 $ this ->configureStoreMigration ($ config , $ container );
201+ $ this ->configureDCB ($ config , $ container );
192202 }
193203
194204 /** @param Config $config */
@@ -231,6 +241,9 @@ private function configureSerializer(array $config, ContainerBuilder $container)
231241 ]);
232242
233243 $ container ->setAlias (HeadersSerializer::class, DefaultHeadersSerializer::class);
244+
245+ $ container ->register (AttributeEventTagExtractor::class);
246+ $ container ->setAlias (EventTagExtractor::class, AttributeEventTagExtractor::class);
234247 }
235248
236249 /** @param Config $config */
@@ -246,7 +259,14 @@ private function configureCommandBus(array $config, ContainerBuilder $container)
246259 new Reference ($ config ['command_bus ' ]['service ' ]),
247260 ]);
248261
249- $ container ->setAlias (CommandBus::class, SymfonyCommandBus::class);
262+ $ container ->register (InstantRetryCommandBus::class)
263+ ->setArguments ([
264+ new Reference (SymfonyCommandBus::class),
265+ $ config ['command_bus ' ]['instant_retry ' ]['default_max_retries ' ],
266+ $ config ['command_bus ' ]['instant_retry ' ]['default_exceptions ' ],
267+ ]);
268+
269+ $ container ->setAlias (CommandBus::class, InstantRetryCommandBus::class);
250270
251271 $ container ->setParameter (
252272 'patchlevel_event_sourcing.aggregate_handlers.bus ' ,
@@ -621,6 +641,10 @@ private function configureMessageDecorator(ContainerBuilder $container): void
621641 ->setArguments ([new Reference (EventMetadataFactory::class)])
622642 ->addTag ('event_sourcing.message_decorator ' );
623643
644+ $ container ->register (EventTagDecorator::class)
645+ ->setArguments ([new Reference (EventTagExtractor::class)])
646+ ->addTag ('event_sourcing.message_decorator ' );
647+
624648 $ container ->registerForAutoconfiguration (MessageDecorator::class)
625649 ->addTag ('event_sourcing.message_decorator ' );
626650
@@ -748,6 +772,26 @@ private function configureStore(array $config, ContainerBuilder $container): voi
748772 return ;
749773 }
750774
775+ if ($ config ['store ' ]['type ' ] === 'dbal_taggable ' ) {
776+ $ container ->register (TaggableDoctrineDbalStore::class)
777+ ->setArguments ([
778+ new Reference ('event_sourcing.dbal_connection ' ),
779+ new Reference (EventSerializer::class),
780+ new Reference (HeadersSerializer::class),
781+ new Reference ('event_sourcing.clock ' ),
782+ $ config ['store ' ]['options ' ],
783+ ])
784+ ->addTag ('event_sourcing.doctrine_schema_configurator ' );
785+
786+ $ container ->setAlias (Store::class, TaggableDoctrineDbalStore::class);
787+
788+ if ($ config ['store ' ]['read_only ' ]) {
789+ throw new InvalidArgumentException ('Taggable store does not support read only ' );
790+ }
791+
792+ return ;
793+ }
794+
751795 throw new InvalidArgumentException (sprintf ('Unknown store type "%s" ' , $ config ['store ' ]['type ' ]));
752796 }
753797
@@ -814,6 +858,20 @@ private function configureStoreMigration(array $config, ContainerBuilder $contai
814858 return ;
815859 }
816860
861+ if ($ config ['store ' ]['migrate_to_new_store ' ]['type ' ] === 'dbal_taggable ' ) {
862+ $ container ->register ($ id , TaggableDoctrineDbalStore::class)
863+ ->setArguments ([
864+ new Reference ('event_sourcing.dbal_connection ' ),
865+ new Reference (EventSerializer::class),
866+ new Reference (HeadersSerializer::class),
867+ new Reference ('event_sourcing.clock ' ),
868+ $ config ['store ' ]['migrate_to_new_store ' ]['options ' ],
869+ ])
870+ ->addTag ('event_sourcing.doctrine_schema_configurator ' );
871+
872+ return ;
873+ }
874+
817875 throw new InvalidArgumentException (sprintf ('Unknown store type "%s" ' , $ config ['store ' ]['type ' ]));
818876 }
819877
@@ -1165,6 +1223,31 @@ private function configureCryptography(array $config, ContainerBuilder $containe
11651223 $ container ->setAlias (PayloadCryptographer::class, PersonalDataPayloadCryptographer::class);
11661224 }
11671225
1226+ /** @param Config $config */
1227+ private function configureDCB (array $ config , ContainerBuilder $ container ): void
1228+ {
1229+ if (!$ config ['dcb ' ]['enabled ' ]) {
1230+ return ;
1231+ }
1232+
1233+ if ($ config ['store ' ]['type ' ] !== 'dbal_taggable ' ) {
1234+ throw new InvalidArgumentException (
1235+ 'DCB requires a taggable store, please use "dbal_taggable" as store type. ' ,
1236+ );
1237+ }
1238+
1239+ $ container ->register (StoreDecisionModelBuilder::class)
1240+ ->setArguments ([new Reference (TaggableDoctrineDbalStore::class)]);
1241+ $ container ->setAlias (DecisionModelBuilder::class, StoreDecisionModelBuilder::class);
1242+
1243+ $ container ->register (StoreEventAppender::class)
1244+ ->setArguments ([
1245+ new Reference (TaggableDoctrineDbalStore::class),
1246+ new Reference (EventTagExtractor::class),
1247+ ]);
1248+ $ container ->setAlias (EventAppender::class, StoreEventAppender::class);
1249+ }
1250+
11681251 private function configureValueResolver (ContainerBuilder $ container ): void
11691252 {
11701253 $ container ->register (AggregateRootIdValueResolver::class)
0 commit comments