From 763530f6dc20eeb9b5fdbb91ba3e795558dc667b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kurf=C3=BCrst?= Date: Mon, 9 Nov 2020 08:45:16 +0100 Subject: [PATCH 01/10] TASK: Standalone usage composer.json --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index dbb72378..d755c727 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,6 @@ "license": "MIT", "require": { "php": ">=7.2", - "neos/flow": "^5.3 || ^6.0", - "flowpack/jobqueue-common": "^3.0 || dev-master", "symfony/serializer": "^5.1", "symfony/property-access": "^5.1", "ramsey/uuid": "^3.9" @@ -15,6 +13,9 @@ "roave/security-advisories": "dev-master", "dg/bypass-finals": "^1.2" }, + "suggest": { + "flowpack/jobqueue-common": "Needed for Neos/Flow only" + }, "autoload": { "psr-4": { "Neos\\EventSourcing\\": "Classes" From ad4ff0ca3d9553d88de0d4d98ef86ad0e3371979 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Mon, 9 Nov 2020 09:09:43 +0100 Subject: [PATCH 02/10] Task: IME. --- .../NeosEventSourcingExtension.php | 27 +++++++++++++++++++ Symfony/NeosEventSourcingBundle.php | 17 ++++++++++++ Symfony/Resources/config/services.yaml | 0 composer.json | 3 ++- 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 Symfony/DependencyInjection/NeosEventSourcingExtension.php create mode 100644 Symfony/NeosEventSourcingBundle.php create mode 100644 Symfony/Resources/config/services.yaml diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php new file mode 100644 index 00000000..acefe113 --- /dev/null +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -0,0 +1,27 @@ +load('services.yaml'); + } + + public function getAlias() + { + return 'neos_eventsourcing'; + } +} \ No newline at end of file diff --git a/Symfony/NeosEventSourcingBundle.php b/Symfony/NeosEventSourcingBundle.php new file mode 100644 index 00000000..e4954746 --- /dev/null +++ b/Symfony/NeosEventSourcingBundle.php @@ -0,0 +1,17 @@ + Date: Mon, 9 Nov 2020 10:57:54 +0100 Subject: [PATCH 03/10] Task: First event was created. --- .../FullyQualifiedClassNameResolver.php | 22 +++++ Symfony/Command/SetupCommand.php | 92 +++++++++++++++++++ .../NeosEventSourcingExtension.php | 2 +- Symfony/Resources/config/services.yaml | 43 +++++++++ composer.json | 1 + symfony.md | 15 +++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 Classes/Event/Resolver/FullyQualifiedClassNameResolver.php create mode 100644 Symfony/Command/SetupCommand.php create mode 100644 symfony.md diff --git a/Classes/Event/Resolver/FullyQualifiedClassNameResolver.php b/Classes/Event/Resolver/FullyQualifiedClassNameResolver.php new file mode 100644 index 00000000..28deefe8 --- /dev/null +++ b/Classes/Event/Resolver/FullyQualifiedClassNameResolver.php @@ -0,0 +1,22 @@ +eventStore = $eventStore; + parent::__construct(); + } + + + protected function configure() + { + // ... + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $result = $this->eventStore->setup(); + self::renderResult($result, $output); + + if ($result->hasErrors()) { + return Command::FAILURE; + } + return Command::SUCCESS; + } + + + /** + * Outputs the given Result object in a human-readable way + * + * @param Result $result + */ + private static function renderResult(Result $result, OutputInterface $output): void + { + if ($result->hasNotices()) { + /** @var Notice $notice */ + foreach ($result->getNotices() as $notice) { + if ($notice->getTitle() !== null) { + $output->writeln(vsprintf('%s: %s', [$notice->getTitle(), $notice->render()])); + } else { + $output->writeln($notice->render()); + } + } + } + + if ($result->hasErrors()) { + /** @var Error $error */ + foreach ($result->getErrors() as $error) { + $output->writeln(vsprintf('ERROR: %s', [$error->render()])); + } + } elseif ($result->hasWarnings()) { + /** @var Warning $warning */ + foreach ($result->getWarnings() as $warning) { + if ($warning->getTitle() !== null) { + $output->writeln(vsprintf('%s: %s !!!', [$warning->getTitle(), $warning->render()])); + } else { + $output->writeln(vsprintf('%s !!!', [$warning->render()])); + } + } + } else { + $output->writeln('SUCCESS'); + } + } + +} \ No newline at end of file diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php index acefe113..0989f933 100644 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -15,7 +15,7 @@ public function load(array $configs, ContainerBuilder $container) { $loader = new YamlFileLoader( $container, - new FileLocator(__DIR__, '/../Resources/config') + new FileLocator(__DIR__ . '/../Resources/config') ); $loader->load('services.yaml'); } diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index e69de29b..0a54ca2a 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -0,0 +1,43 @@ +services: + + # TODO: this should be configured "PER BOUNDED CONTEXT" (analogous to how Doctrine DBAL connections are handled) + Neos\EventSourcing\EventStore\EventStore: + alias: neos_eventsourcing_eventstore + + neos_eventsourcing_eventstore: + class: Neos\EventSourcing\EventStore\EventStore + arguments: + $storage: "@neos_eventsourcing_storage_eventStorageInterface" + $eventPublisher: "@neos_eventsourcing_eventPublisher" + $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" + public: true + + neos_eventsourcing_storage_eventStorageInterface: + alias: neos_eventsourcing_storage_doctrine_doctrineEventStorage + + neos_eventsourcing_storage_doctrine_doctrineEventStorage: + class: Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage + arguments: + $options: [] + # eventTableName: + $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" + $connection: "@Doctrine\\DBAL\\Driver\\Connection" + + neos_eventsourcing_event_eventTypeResolver: + class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver + + + + neos_eventsourcing_eventStore_eventNormalizer: + class: Neos\EventSourcing\EventStore\EventNormalizer + arguments: + $eventTypeResolver: "@neos_eventsourcing_event_eventTypeResolver" + + neos_eventsourcing_eventPublisher: + class: Neos\EventSourcing\EventPublisher\NoopEventPublisher + + neos_eventsourcing_symfony_command_setupCommand: + class: Neos\EventSourcing\Symfony\Command\SetupCommand + tags: ["console.command"] + arguments: + $eventStore: "@neos_eventsourcing_eventstore" \ No newline at end of file diff --git a/composer.json b/composer.json index a4c1ee15..8568fc3e 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "php": ">=7.2", "symfony/serializer": "^5.1", "symfony/property-access": "^5.1", + "neos/error-messages": "^6.3", "ramsey/uuid": "^3.9" }, "require-dev": { diff --git a/symfony.md b/symfony.md new file mode 100644 index 00000000..3d21bb38 --- /dev/null +++ b/symfony.md @@ -0,0 +1,15 @@ +# doctrine.yaml + +doctrine: + dbal: + connections: + default: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + server_version: '5.7' + + default_table_options: + charset: utf8mb4 + collate: utf8mb4_unicode_ci From b1c3c3e20608853598f14e89d8f7abc5aed7f8d4 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Mon, 9 Nov 2020 12:11:04 +0100 Subject: [PATCH 04/10] Task: We can load an event now. --- Symfony/Resources/config/services.yaml | 2 -- composer.json | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index 0a54ca2a..99d983f4 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -26,8 +26,6 @@ services: neos_eventsourcing_event_eventTypeResolver: class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver - - neos_eventsourcing_eventStore_eventNormalizer: class: Neos\EventSourcing\EventStore\EventNormalizer arguments: diff --git a/composer.json b/composer.json index 8568fc3e..20e17e30 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,8 @@ "php": ">=7.2", "symfony/serializer": "^5.1", "symfony/property-access": "^5.1", - "neos/error-messages": "^6.3", + "neos/error-messages": "*", + "neos/utility-objecthandling": "*", "ramsey/uuid": "^3.9" }, "require-dev": { From 113b56ab8ec55b5cbdc194c79abf21a4ea2dd0f9 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Mon, 9 Nov 2020 14:19:31 +0100 Subject: [PATCH 05/10] Task: Create AppliedEventsStorageSetup. --- .../Command/ProjectionCommandController.php | 4 +- .../DoctrineAppliedEventsStorage.php | 2 + Classes/Projection/ProjectionManager.php | 2 +- .../Projection/ProjectionManagerInterface.php | 85 ++++++++++++++ .../InternalCatchUpEventListenerCommand.php | 77 +++++++++++++ Symfony/Command/SetupCommand.php | 10 +- .../DoctrineAppliedEventsStorageSetup.php | 109 ++++++++++++++++++ .../EventPublisher/SymfonyEventPublisher.php | 94 +++++++++++++++ Symfony/Resources/config/services.yaml | 26 ++++- composer.json | 3 +- symfony.md | 4 + 11 files changed, 408 insertions(+), 8 deletions(-) create mode 100644 Classes/Projection/ProjectionManagerInterface.php create mode 100644 Symfony/Command/InternalCatchUpEventListenerCommand.php create mode 100644 Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php create mode 100644 Symfony/EventPublisher/SymfonyEventPublisher.php diff --git a/Classes/Command/ProjectionCommandController.php b/Classes/Command/ProjectionCommandController.php index 7c2e02ef..120b7a94 100644 --- a/Classes/Command/ProjectionCommandController.php +++ b/Classes/Command/ProjectionCommandController.php @@ -14,7 +14,7 @@ use Neos\EventSourcing\EventListener\Exception\EventCouldNotBeAppliedException; use Neos\EventSourcing\Projection\Projection; -use Neos\EventSourcing\Projection\ProjectionManager; +use Neos\EventSourcing\Projection\ProjectionManagerInterface; use Neos\Flow\Annotations as Flow; use Neos\Flow\Cli\CommandController; use Neos\Flow\Cli\Exception\StopCommandException; @@ -28,7 +28,7 @@ class ProjectionCommandController extends CommandController { /** * @Flow\Inject - * @var ProjectionManager + * @var ProjectionManagerInterface */ protected $projectionManager; diff --git a/Classes/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorage.php b/Classes/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorage.php index 9c025faf..3a718a40 100644 --- a/Classes/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorage.php +++ b/Classes/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorage.php @@ -21,6 +21,8 @@ /** * Doctrine DBAL adapter for the AppliedEventsStorageInterface + * + * TODO: we should have one doctrine applied events storage table PER BOUNDED CONTEXT, i.e. per storage. */ final class DoctrineAppliedEventsStorage implements AppliedEventsStorageInterface { diff --git a/Classes/Projection/ProjectionManager.php b/Classes/Projection/ProjectionManager.php index e750d399..2033832c 100644 --- a/Classes/Projection/ProjectionManager.php +++ b/Classes/Projection/ProjectionManager.php @@ -30,7 +30,7 @@ * @api * @Flow\Scope("singleton") */ -class ProjectionManager +class ProjectionManager implements ProjectionManagerInterface { /** * @var ObjectManagerInterface diff --git a/Classes/Projection/ProjectionManagerInterface.php b/Classes/Projection/ProjectionManagerInterface.php new file mode 100644 index 00000000..b03c59a1 --- /dev/null +++ b/Classes/Projection/ProjectionManagerInterface.php @@ -0,0 +1,85 @@ +eventStore = $eventStore; // TODO multiple event stores + $this->container = $container; + $this->connection = $connection; + parent::__construct(); + } + + + protected function configure() + { + $this->addArgument('eventListenerClassName', InputArgument::REQUIRED); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + dump("HALLO"); + $eventListenerClassName = $input->getArgument('eventListenerClassName'); + + dump($eventListenerClassName); + $listener = $this->container->get($eventListenerClassName); + + dump("HI"); + dump($listener); + $eventListenerInvoker = new EventListenerInvoker($this->eventStore, $listener, $this->connection); + $eventListenerInvoker->catchUp(); + + die(); + return Command::SUCCESS; + } + +} \ No newline at end of file diff --git a/Symfony/Command/SetupCommand.php b/Symfony/Command/SetupCommand.php index ac1d21c9..c68e1007 100644 --- a/Symfony/Command/SetupCommand.php +++ b/Symfony/Command/SetupCommand.php @@ -10,6 +10,7 @@ use Neos\Error\Messages\Result; use Neos\Error\Messages\Warning; use Neos\EventSourcing\EventStore\EventStore; +use Neos\EventSourcing\Symfony\EventListener\AppliedEventsStorage\DoctrineAppliedEventsStorageSetup; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -24,13 +25,19 @@ class SetupCommand extends Command */ private $eventStore; + /** + * @var DoctrineAppliedEventsStorageSetup + */ + private $doctrineAppliedEventsStorageSetup; + /** * SayHelloCommand constructor. * @param EventStore $eventStore */ - public function __construct(EventStore $eventStore) + public function __construct(EventStore $eventStore, DoctrineAppliedEventsStorageSetup $doctrineAppliedEventsStorageSetup) { $this->eventStore = $eventStore; + $this->doctrineAppliedEventsStorageSetup = $doctrineAppliedEventsStorageSetup; parent::__construct(); } @@ -43,6 +50,7 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $result = $this->eventStore->setup(); + $result->merge($this->doctrineAppliedEventsStorageSetup->setup()); self::renderResult($result, $output); if ($result->hasErrors()) { diff --git a/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php b/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php new file mode 100644 index 00000000..35c46942 --- /dev/null +++ b/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php @@ -0,0 +1,109 @@ +connection = $connection; + } + + + /** + * @inheritdoc + * @throws DBALException | \Throwable + */ + public function setup(): Result + { + $result = new Result(); + $schemaManager = $this->connection->getSchemaManager(); + if ($schemaManager === null) { + $result->addError(new Error('Failed to retrieve Schema Manager', 1592381759, [], 'Connection failed')); + return $result; + } + try { + $tableExists = $schemaManager->tablesExist([AppliedEventsLog::TABLE_NAME]); + } catch (ConnectionException $exception) { + $result->addError(new Error($exception->getMessage(), $exception->getCode(), [], 'Connection failed')); + return $result; + } + if ($tableExists) { + $result->addNotice(new Notice('Table "%s" (already exists)', null, [AppliedEventsLog::TABLE_NAME])); + } else { + $result->addNotice(new Notice('Creating database table "%s" in database "%s" on host %s....', null, [AppliedEventsLog::TABLE_NAME, $this->connection->getDatabase(), $this->connection->getHost()])); + } + + $fromSchema = $schemaManager->createSchema(); + $schemaDiff = (new Comparator())->compare($fromSchema, $this->createEventStoreSchema()); + + $statements = $schemaDiff->toSaveSql($this->connection->getDatabasePlatform()); + if ($statements === []) { + $result->addNotice(new Notice('Table schema is up to date, no migration required')); + return $result; + } + $this->connection->beginTransaction(); + try { + foreach ($statements as $statement) { + $result->addNotice(new Notice('++ %s', null, [$statement])); + $this->connection->exec($statement); + } + $this->connection->commit(); + } catch (\Throwable $exception) { + $this->connection->rollBack(); + throw $exception; + } + return $result; + } + + /** + * Creates the Doctrine schema to be compared with the current db schema for migration + * + * @return Schema + */ + private function createEventStoreSchema(): Schema + { + $schemaConfiguration = new SchemaConfig(); + $connectionParameters = $this->connection->getParams(); + if (isset($connectionParameters['defaultTableOptions'])) { + $schemaConfiguration->setDefaultTableOptions($connectionParameters['defaultTableOptions']); + } + $schema = new Schema([], [], $schemaConfiguration); + $table = $schema->createTable(AppliedEventsLog::TABLE_NAME); + + $table->addColumn('eventlisteneridentifier', Types::STRING, ['length' => 255]); + $table->addColumn('highestappliedsequencenumber', Types::INTEGER); + + $table->setPrimaryKey(['eventlisteneridentifier']); + + return $schema; + } +} \ No newline at end of file diff --git a/Symfony/EventPublisher/SymfonyEventPublisher.php b/Symfony/EventPublisher/SymfonyEventPublisher.php new file mode 100644 index 00000000..785b39db --- /dev/null +++ b/Symfony/EventPublisher/SymfonyEventPublisher.php @@ -0,0 +1,94 @@ +eventDispatcher = $eventDispatcher; + } + + + public function publish(DomainEvents $events): void + { + $queuedEventListenerClassNames = []; + $processedEventClassNames = []; + foreach ($events as $event) { + /** @var string $eventClassName */ + $eventClassName = \get_class($event instanceof DecoratedEvent ? $event->getWrappedEvent() : $event); + + // only process every Event type once + if (isset($processedEventClassNames[$eventClassName])) { + continue; + } + + + // NOTE: eventDispatcher is ONLY used for resolving the class name of the listener. + // you are NEVER allowed to call $this->eventDispatcher->dispatch($event, $eventClassName); + // because otherwise, the appliedEventsLog is not updated properly. + $listeners = $this->eventDispatcher->getListeners($eventClassName); + dump($listeners); + + foreach ($listeners as $listenerClassNameAndMethodName) { + $listenerClassName = get_class($listenerClassNameAndMethodName[0]); + + // only process every Event Listener once + if (isset($queuedEventListenerClassNames[$listenerClassName])) { + continue; + } + + + $this->triggerAsyncBackgroundJob($listenerClassName); + + $queuedEventListenerClassNames[$listenerClassName] = true; + } + + + // we have to know: "what event listers do we need to trigger"? + /*foreach ($this->mappings as $mapping) { + if ($mapping->getEventClassName() !== $eventClassName) { + continue; + } + // only process every Event Listener once + if (isset($queuedEventListenerClassNames[$mapping->getListenerClassName()])) { + continue; + } + $queueName = $mapping->getOption('queueName', self::DEFAULT_QUEUE_NAME); + $options = $mapping->getOption('queueOptions', []); + $this->jobManager->queue($queueName, new CatchUpEventListenerJob($mapping->getListenerClassName(), $this->eventStoreIdentifier), $options); + $queuedEventListenerClassNames[$mapping->getListenerClassName()] = true; + }*/ + } + + } + + private function triggerAsyncBackgroundJob($listenerClassName) + { + $process = new Process(['php', 'bin/console', InternalCatchUpEventListenerCommand::getDefaultName(), $listenerClassName]); + $process->run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust + $errOut = $process->getOutput() . $process->getErrorOutput(); + dump($errOut); + } +} \ No newline at end of file diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index 99d983f4..411e5f56 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -1,3 +1,6 @@ +parameters: + neos_foo: + services: # TODO: this should be configured "PER BOUNDED CONTEXT" (analogous to how Doctrine DBAL connections are handled) @@ -21,7 +24,7 @@ services: $options: [] # eventTableName: $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" - $connection: "@Doctrine\\DBAL\\Driver\\Connection" + $connection: "@Doctrine\\DBAL\\Connection" neos_eventsourcing_event_eventTypeResolver: class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver @@ -32,10 +35,27 @@ services: $eventTypeResolver: "@neos_eventsourcing_event_eventTypeResolver" neos_eventsourcing_eventPublisher: - class: Neos\EventSourcing\EventPublisher\NoopEventPublisher + class: Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher + arguments: + $eventDispatcher: "@Symfony\\Component\\EventDispatcher\\EventDispatcherInterface" neos_eventsourcing_symfony_command_setupCommand: class: Neos\EventSourcing\Symfony\Command\SetupCommand tags: ["console.command"] arguments: - $eventStore: "@neos_eventsourcing_eventstore" \ No newline at end of file + $eventStore: "@neos_eventsourcing_eventstore" + $doctrineAppliedEventsStorageSetup: "@neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup" + + neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup: + class: Neos\EventSourcing\Symfony\EventListener\AppliedEventsStorage\DoctrineAppliedEventsStorageSetup + arguments: + $connection: "@Doctrine\\DBAL\\Connection" + + + neos_eventsourcing_symfony_command_internalFooCommand: + class: Neos\EventSourcing\Symfony\Command\InternalCatchUpEventListenerCommand + tags: [ "console.command" ] + arguments: + $eventStore: "@neos_eventsourcing_eventstore" + $container: "@Psr\\Container\\ContainerInterface" + $connection: "@Doctrine\\DBAL\\Connection" diff --git a/composer.json b/composer.json index 20e17e30..59e02ac6 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "dg/bypass-finals": "^1.2" }, "suggest": { - "flowpack/jobqueue-common": "Needed for Neos/Flow only" + "flowpack/jobqueue-common": "Needed for Neos/Flow usage only", + "symfony/process": "Needed for standalone usage" }, "autoload": { "psr-4": { diff --git a/symfony.md b/symfony.md index 3d21bb38..f32b0f75 100644 --- a/symfony.md +++ b/symfony.md @@ -13,3 +13,7 @@ doctrine: default_table_options: charset: utf8mb4 collate: utf8mb4_unicode_ci + + + +... make projectors public (could be later done with compiler pass) \ No newline at end of file From 63a8c1ce0cbf5218d6831beb92414bc144e38520 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Mon, 9 Nov 2020 17:00:56 +0100 Subject: [PATCH 06/10] Task: Finished Dresden. --- .../InternalCatchUpEventListenerCommand.php | 15 ++--- Symfony/DependencyInjection/Configuration.php | 55 +++++++++++++++++++ .../NeosEventSourcingExtension.php | 33 +++++++++++ .../EventPublisher/SymfonyEventPublisher.php | 10 +++- Symfony/Resources/config/services.yaml | 50 ++++++++--------- 5 files changed, 125 insertions(+), 38 deletions(-) create mode 100644 Symfony/DependencyInjection/Configuration.php diff --git a/Symfony/Command/InternalCatchUpEventListenerCommand.php b/Symfony/Command/InternalCatchUpEventListenerCommand.php index d78436d2..83eeb5b3 100644 --- a/Symfony/Command/InternalCatchUpEventListenerCommand.php +++ b/Symfony/Command/InternalCatchUpEventListenerCommand.php @@ -23,12 +23,6 @@ class InternalCatchUpEventListenerCommand extends Command // the name of the command (the part after "bin/console") protected static $defaultName = 'eventsourcing:internal:catchup-event-listener'; - - /** - * @var EventStore - */ - protected $eventStore; - /** * @var ContainerInterface */ @@ -43,9 +37,8 @@ class InternalCatchUpEventListenerCommand extends Command * SayHelloCommand constructor. * @param EventStore $eventStore */ - public function __construct(EventStore $eventStore, ContainerInterface $container, Connection $connection) + public function __construct(ContainerInterface $container, Connection $connection) { - $this->eventStore = $eventStore; // TODO multiple event stores $this->container = $container; $this->connection = $connection; parent::__construct(); @@ -55,19 +48,23 @@ public function __construct(EventStore $eventStore, ContainerInterface $containe protected function configure() { $this->addArgument('eventListenerClassName', InputArgument::REQUIRED); + $this->addArgument('eventStoreContainerId', InputArgument::REQUIRED); } protected function execute(InputInterface $input, OutputInterface $output) { dump("HALLO"); $eventListenerClassName = $input->getArgument('eventListenerClassName'); + $eventStoreContainerId = $input->getArgument('eventStoreContainerId'); dump($eventListenerClassName); $listener = $this->container->get($eventListenerClassName); dump("HI"); dump($listener); - $eventListenerInvoker = new EventListenerInvoker($this->eventStore, $listener, $this->connection); + $eventStore = $this->container->get($eventStoreContainerId); + dump($eventStore, "ES"); + $eventListenerInvoker = new EventListenerInvoker($eventStore, $listener, $this->connection); $eventListenerInvoker->catchUp(); die(); diff --git a/Symfony/DependencyInjection/Configuration.php b/Symfony/DependencyInjection/Configuration.php new file mode 100644 index 00000000..5b9d292d --- /dev/null +++ b/Symfony/DependencyInjection/Configuration.php @@ -0,0 +1,55 @@ +getRootNode(); + + $this->addDbalSection($rootNode); + + return $treeBuilder; + } + + /** + * Add DBAL section to configuration tree + */ + private function addDbalSection(ArrayNodeDefinition $node): void + { + $node + ->children() + ->arrayNode('stores') + ->arrayPrototype() + ->children() + ->scalarNode('eventTableName')->end() + ->arrayNode('listenerClassNames') + ->scalarPrototype()->end() + ->end() + ->end() + ->end() + ->end() + ->end(); + } +} diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php index 0989f933..bf9e76a6 100644 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -4,20 +4,53 @@ namespace Neos\EventSourcing\Symfony\DependencyInjection; +use Doctrine\DBAL\Connection; +use Neos\EventSourcing\EventStore\EventStore; +use Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage; +use Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher; +use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Reference; class NeosEventSourcingExtension extends Extension { public function load(array $configs, ContainerBuilder $container) { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + dump($config); + + $loader = new YamlFileLoader( $container, new FileLocator(__DIR__ . '/../Resources/config') ); $loader->load('services.yaml'); + + foreach ($config['stores'] as $name => $store) { + $container->register('neos_eventsourcing.eventstore.' . $name) + ->setClass(EventStore::class) + ->setPublic(true) + ->setArgument('$storage', new Reference('neos_eventsourcing.eventstore.' . $name . '.storage')) + ->setArgument('$eventPublisher', new Reference('neos_eventsourcing.eventstore.' . $name . '.publisher')) + ->setArgument('$eventNormalizer', new Reference('neos_eventsourcing_eventStore_eventNormalizer')); + + $container->register('neos_eventsourcing.eventstore.' . $name . '.storage') + ->setClass(DoctrineEventStorage::class) // TODO make configurable + ->setArgument('$options', ['eventTableName' => $store['eventTableName']]) + ->setArgument('$eventNormalizer', new Reference('neos_eventsourcing_eventStore_eventNormalizer')) + ->setArgument('$connection', new Reference(Connection::class)); + + $container->register('neos_eventsourcing.eventstore.' . $name . '.publisher') + ->setClass(SymfonyEventPublisher::class) + ->setArgument('$eventDispatcher', new Reference(EventDispatcherInterface::class)) + ->setArgument('$eventStoreContainerId', 'neos_eventsourcing.eventstore.' . $name); + + } } public function getAlias() diff --git a/Symfony/EventPublisher/SymfonyEventPublisher.php b/Symfony/EventPublisher/SymfonyEventPublisher.php index 785b39db..a6e66442 100644 --- a/Symfony/EventPublisher/SymfonyEventPublisher.php +++ b/Symfony/EventPublisher/SymfonyEventPublisher.php @@ -24,15 +24,19 @@ class SymfonyEventPublisher implements EventPublisherInterface */ private $eventDispatcher; - public function __construct(EventDispatcherInterface $eventDispatcher) + private $eventStoreContainerId; + + public function __construct(EventDispatcherInterface $eventDispatcher, string $eventStoreContainerId) { - // TODO - later: "event store name" $this->eventDispatcher = $eventDispatcher; + $this->eventStoreContainerId = $eventStoreContainerId; } public function publish(DomainEvents $events): void { + // TODO: listener filter + $queuedEventListenerClassNames = []; $processedEventClassNames = []; foreach ($events as $event) { @@ -86,7 +90,7 @@ public function publish(DomainEvents $events): void private function triggerAsyncBackgroundJob($listenerClassName) { - $process = new Process(['php', 'bin/console', InternalCatchUpEventListenerCommand::getDefaultName(), $listenerClassName]); + $process = new Process(['php', 'bin/console', InternalCatchUpEventListenerCommand::getDefaultName(), $listenerClassName, $this->eventStoreContainerId]); $process->run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust $errOut = $process->getOutput() . $process->getErrorOutput(); dump($errOut); diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index 411e5f56..2bd01b37 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -4,27 +4,25 @@ parameters: services: # TODO: this should be configured "PER BOUNDED CONTEXT" (analogous to how Doctrine DBAL connections are handled) - Neos\EventSourcing\EventStore\EventStore: - alias: neos_eventsourcing_eventstore - neos_eventsourcing_eventstore: - class: Neos\EventSourcing\EventStore\EventStore - arguments: - $storage: "@neos_eventsourcing_storage_eventStorageInterface" - $eventPublisher: "@neos_eventsourcing_eventPublisher" - $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" - public: true - - neos_eventsourcing_storage_eventStorageInterface: - alias: neos_eventsourcing_storage_doctrine_doctrineEventStorage - - neos_eventsourcing_storage_doctrine_doctrineEventStorage: - class: Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage - arguments: - $options: [] - # eventTableName: - $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" - $connection: "@Doctrine\\DBAL\\Connection" +# neos_eventsourcing_eventstore: +# class: Neos\EventSourcing\EventStore\EventStore +# arguments: +# $storage: "@neos_eventsourcing_storage_eventStorageInterface" +# $eventPublisher: "@neos_eventsourcing_eventPublisher" +# $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" +# public: true + +# neos_eventsourcing_storage_eventStorageInterface: +# alias: neos_eventsourcing_storage_doctrine_doctrineEventStorage + +# neos_eventsourcing_storage_doctrine_doctrineEventStorage: +# class: Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage +# arguments: +# $options: [] +# # eventTableName: +# $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" +# $connection: "@Doctrine\\DBAL\\Connection" neos_eventsourcing_event_eventTypeResolver: class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver @@ -34,16 +32,17 @@ services: arguments: $eventTypeResolver: "@neos_eventsourcing_event_eventTypeResolver" - neos_eventsourcing_eventPublisher: - class: Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher - arguments: - $eventDispatcher: "@Symfony\\Component\\EventDispatcher\\EventDispatcherInterface" +# neos_eventsourcing_eventPublisher: +# class: Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher +# arguments: +# $eventDispatcher: "@Symfony\\Component\\EventDispatcher\\EventDispatcherInterface" neos_eventsourcing_symfony_command_setupCommand: class: Neos\EventSourcing\Symfony\Command\SetupCommand tags: ["console.command"] arguments: - $eventStore: "@neos_eventsourcing_eventstore" + # TODO + $eventStore: "@neos_eventsourcing.eventstore.example" # TODO needs adjustment $doctrineAppliedEventsStorageSetup: "@neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup" neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup: @@ -56,6 +55,5 @@ services: class: Neos\EventSourcing\Symfony\Command\InternalCatchUpEventListenerCommand tags: [ "console.command" ] arguments: - $eventStore: "@neos_eventsourcing_eventstore" $container: "@Psr\\Container\\ContainerInterface" $connection: "@Doctrine\\DBAL\\Connection" From 9700fc29bf2b0c022995cc11044a4e009399e358 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Sun, 22 Nov 2020 17:58:32 +0100 Subject: [PATCH 07/10] Task: Remove some debug messages. --- .../InternalCatchUpEventListenerCommand.php | 16 ++------------ Symfony/Command/SetupCommand.php | 4 +--- .../NeosEventSourcingExtension.php | 5 +---- .../EventPublisher/SymfonyEventPublisher.php | 22 +++++++++++-------- Symfony/Resources/config/services.yaml | 2 +- 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/Symfony/Command/InternalCatchUpEventListenerCommand.php b/Symfony/Command/InternalCatchUpEventListenerCommand.php index 83eeb5b3..25882dcb 100644 --- a/Symfony/Command/InternalCatchUpEventListenerCommand.php +++ b/Symfony/Command/InternalCatchUpEventListenerCommand.php @@ -4,12 +4,7 @@ namespace Neos\EventSourcing\Symfony\Command; -use App\Domain\Command\SayHello; use Doctrine\DBAL\Connection; -use Neos\Error\Messages\Error; -use Neos\Error\Messages\Notice; -use Neos\Error\Messages\Result; -use Neos\Error\Messages\Warning; use Neos\EventSourcing\EventListener\EventListenerInvoker; use Neos\EventSourcing\EventStore\EventStore; use Psr\Container\ContainerInterface; @@ -53,22 +48,15 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { - dump("HALLO"); $eventListenerClassName = $input->getArgument('eventListenerClassName'); $eventStoreContainerId = $input->getArgument('eventStoreContainerId'); - dump($eventListenerClassName); $listener = $this->container->get($eventListenerClassName); - - dump("HI"); - dump($listener); $eventStore = $this->container->get($eventStoreContainerId); - dump($eventStore, "ES"); + $eventListenerInvoker = new EventListenerInvoker($eventStore, $listener, $this->connection); $eventListenerInvoker->catchUp(); - die(); return Command::SUCCESS; } - -} \ No newline at end of file +} diff --git a/Symfony/Command/SetupCommand.php b/Symfony/Command/SetupCommand.php index c68e1007..1ab805d0 100644 --- a/Symfony/Command/SetupCommand.php +++ b/Symfony/Command/SetupCommand.php @@ -4,7 +4,6 @@ namespace Neos\EventSourcing\Symfony\Command; -use App\Domain\Command\SayHello; use Neos\Error\Messages\Error; use Neos\Error\Messages\Notice; use Neos\Error\Messages\Result; @@ -96,5 +95,4 @@ private static function renderResult(Result $result, OutputInterface $output): v $output->writeln('SUCCESS'); } } - -} \ No newline at end of file +} diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php index bf9e76a6..a17c0e3e 100644 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -1,9 +1,7 @@ setClass(SymfonyEventPublisher::class) ->setArgument('$eventDispatcher', new Reference(EventDispatcherInterface::class)) ->setArgument('$eventStoreContainerId', 'neos_eventsourcing.eventstore.' . $name); - } } @@ -57,4 +54,4 @@ public function getAlias() { return 'neos_eventsourcing'; } -} \ No newline at end of file +} diff --git a/Symfony/EventPublisher/SymfonyEventPublisher.php b/Symfony/EventPublisher/SymfonyEventPublisher.php index a6e66442..92ee6194 100644 --- a/Symfony/EventPublisher/SymfonyEventPublisher.php +++ b/Symfony/EventPublisher/SymfonyEventPublisher.php @@ -1,18 +1,13 @@ eventDispatcher->dispatch($event, $eventClassName); // because otherwise, the appliedEventsLog is not updated properly. $listeners = $this->eventDispatcher->getListeners($eventClassName); - dump($listeners); + //dump($listeners); foreach ($listeners as $listenerClassNameAndMethodName) { $listenerClassName = get_class($listenerClassNameAndMethodName[0]); @@ -90,9 +85,18 @@ public function publish(DomainEvents $events): void private function triggerAsyncBackgroundJob($listenerClassName) { - $process = new Process(['php', 'bin/console', InternalCatchUpEventListenerCommand::getDefaultName(), $listenerClassName, $this->eventStoreContainerId]); + + $process = new Process( + [ + 'php', + '/var/www/eventsourcing.app/bin/console', + InternalCatchUpEventListenerCommand::getDefaultName(), + $listenerClassName, + $this->eventStoreContainerId + ] + ); $process->run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust $errOut = $process->getOutput() . $process->getErrorOutput(); dump($errOut); } -} \ No newline at end of file +} diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index 2bd01b37..414f1ee6 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -42,7 +42,7 @@ services: tags: ["console.command"] arguments: # TODO - $eventStore: "@neos_eventsourcing.eventstore.example" # TODO needs adjustment + $eventStore: "@neos_eventsourcing.eventstore.blog" # TODO needs adjustment $doctrineAppliedEventsStorageSetup: "@neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup" neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup: From 2c3c93fe3cbc578ee24cf11dd8f948bf377b354c Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Sun, 29 Nov 2020 18:44:18 +0100 Subject: [PATCH 08/10] Task: Create different asyn transports. --- .../NeosEventSourcingExtension.php | 5 +-- .../EventPublisher/SymfonyEventPublisher.php | 28 +++++++-------- Symfony/NeosEventSourcingBundle.php | 2 -- Symfony/Resources/EventSourcingMessage.php | 25 ++++++++++++++ Symfony/Resources/config/services.yaml | 28 ++------------- Symfony/Transport/AsyncTransportInterface.php | 11 ++++++ Symfony/Transport/ConsoleCommandTransport.php | 29 ++++++++++++++++ Symfony/Transport/MessengerTransport.php | 34 +++++++++++++++++++ 8 files changed, 117 insertions(+), 45 deletions(-) create mode 100644 Symfony/Resources/EventSourcingMessage.php create mode 100644 Symfony/Transport/AsyncTransportInterface.php create mode 100644 Symfony/Transport/ConsoleCommandTransport.php create mode 100644 Symfony/Transport/MessengerTransport.php diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php index a17c0e3e..6673624a 100644 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -6,6 +6,7 @@ use Neos\EventSourcing\EventStore\EventStore; use Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage; use Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher; +use Neos\EventSourcing\Symfony\Transport\AsyncTransportInterface; use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -20,8 +21,7 @@ public function load(array $configs, ContainerBuilder $container) $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - dump($config); - + //dump($config); $loader = new YamlFileLoader( $container, @@ -45,6 +45,7 @@ public function load(array $configs, ContainerBuilder $container) $container->register('neos_eventsourcing.eventstore.' . $name . '.publisher') ->setClass(SymfonyEventPublisher::class) + ->setArgument('$asyncTransport', new Reference(AsyncTransportInterface::class)) ->setArgument('$eventDispatcher', new Reference(EventDispatcherInterface::class)) ->setArgument('$eventStoreContainerId', 'neos_eventsourcing.eventstore.' . $name); } diff --git a/Symfony/EventPublisher/SymfonyEventPublisher.php b/Symfony/EventPublisher/SymfonyEventPublisher.php index 92ee6194..c9e78fc9 100644 --- a/Symfony/EventPublisher/SymfonyEventPublisher.php +++ b/Symfony/EventPublisher/SymfonyEventPublisher.php @@ -7,9 +7,8 @@ use Neos\EventSourcing\Event\DecoratedEvent; use Neos\EventSourcing\Event\DomainEvents; use Neos\EventSourcing\EventPublisher\EventPublisherInterface; -use Neos\EventSourcing\Symfony\Command\InternalCatchUpEventListenerCommand; +use Neos\EventSourcing\Symfony\Transport\AsyncTransportInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Process\Process; class SymfonyEventPublisher implements EventPublisherInterface { @@ -19,10 +18,17 @@ class SymfonyEventPublisher implements EventPublisherInterface */ private $eventDispatcher; + private $asyncTransport; + private $eventStoreContainerId; - public function __construct(EventDispatcherInterface $eventDispatcher, string $eventStoreContainerId) + public function __construct( + AsyncTransportInterface $asyncTransport, + EventDispatcherInterface $eventDispatcher, + string $eventStoreContainerId + ) { + $this->asyncTransport = $asyncTransport; $this->eventDispatcher = $eventDispatcher; $this->eventStoreContainerId = $eventStoreContainerId; } @@ -58,7 +64,6 @@ public function publish(DomainEvents $events): void continue; } - $this->triggerAsyncBackgroundJob($listenerClassName); $queuedEventListenerClassNames[$listenerClassName] = true; @@ -85,18 +90,9 @@ public function publish(DomainEvents $events): void private function triggerAsyncBackgroundJob($listenerClassName) { - - $process = new Process( - [ - 'php', - '/var/www/eventsourcing.app/bin/console', - InternalCatchUpEventListenerCommand::getDefaultName(), - $listenerClassName, - $this->eventStoreContainerId - ] + $this->asyncTransport->send( + $listenerClassName, + $this->eventStoreContainerId ); - $process->run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust - $errOut = $process->getOutput() . $process->getErrorOutput(); - dump($errOut); } } diff --git a/Symfony/NeosEventSourcingBundle.php b/Symfony/NeosEventSourcingBundle.php index e4954746..719c2170 100644 --- a/Symfony/NeosEventSourcingBundle.php +++ b/Symfony/NeosEventSourcingBundle.php @@ -1,9 +1,7 @@ listenerClassName = $listenerClassName; + $newMessage->eventStoreContainerId = $eventStoreContainerId; + + return $newMessage; + } +} diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index 414f1ee6..a439a3be 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -4,26 +4,6 @@ parameters: services: # TODO: this should be configured "PER BOUNDED CONTEXT" (analogous to how Doctrine DBAL connections are handled) - -# neos_eventsourcing_eventstore: -# class: Neos\EventSourcing\EventStore\EventStore -# arguments: -# $storage: "@neos_eventsourcing_storage_eventStorageInterface" -# $eventPublisher: "@neos_eventsourcing_eventPublisher" -# $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" -# public: true - -# neos_eventsourcing_storage_eventStorageInterface: -# alias: neos_eventsourcing_storage_doctrine_doctrineEventStorage - -# neos_eventsourcing_storage_doctrine_doctrineEventStorage: -# class: Neos\EventSourcing\EventStore\Storage\Doctrine\DoctrineEventStorage -# arguments: -# $options: [] -# # eventTableName: -# $eventNormalizer: "@neos_eventsourcing_eventStore_eventNormalizer" -# $connection: "@Doctrine\\DBAL\\Connection" - neos_eventsourcing_event_eventTypeResolver: class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver @@ -32,11 +12,6 @@ services: arguments: $eventTypeResolver: "@neos_eventsourcing_event_eventTypeResolver" -# neos_eventsourcing_eventPublisher: -# class: Neos\EventSourcing\Symfony\EventPublisher\SymfonyEventPublisher -# arguments: -# $eventDispatcher: "@Symfony\\Component\\EventDispatcher\\EventDispatcherInterface" - neos_eventsourcing_symfony_command_setupCommand: class: Neos\EventSourcing\Symfony\Command\SetupCommand tags: ["console.command"] @@ -57,3 +32,6 @@ services: arguments: $container: "@Psr\\Container\\ContainerInterface" $connection: "@Doctrine\\DBAL\\Connection" + + Neos\EventSourcing\Symfony\Transport\ConsoleCommandTransport: ~ + Neos\EventSourcing\Symfony\Transport\AsyncTransportInterface: '@Neos\EventSourcing\Symfony\Transport\ConsoleCommandTransport' diff --git a/Symfony/Transport/AsyncTransportInterface.php b/Symfony/Transport/AsyncTransportInterface.php new file mode 100644 index 00000000..cfd242b1 --- /dev/null +++ b/Symfony/Transport/AsyncTransportInterface.php @@ -0,0 +1,11 @@ +run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust + $errOut = $process->getOutput() . $process->getErrorOutput(); + } +} \ No newline at end of file diff --git a/Symfony/Transport/MessengerTransport.php b/Symfony/Transport/MessengerTransport.php new file mode 100644 index 00000000..7cfe0c23 --- /dev/null +++ b/Symfony/Transport/MessengerTransport.php @@ -0,0 +1,34 @@ +messageBus = $messageBus; + } + + public function send( + string $listenerClassName, + string $eventStoreContainerId + ) + { + $message = EventSourcingMessage::create( + $listenerClassName, + $eventStoreContainerId + ); + $this->messageBus->dispatch( + $message + ); + } +} \ No newline at end of file From 21276e9fd4b127a07482fb03d4c4608ce763afa0 Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Sat, 5 Dec 2020 18:04:27 +0100 Subject: [PATCH 09/10] Task: Setup command can create more than one stores now. --- Symfony/Command/SetupCommand.php | 74 ++++++++++++++----- .../NeosEventSourcingExtension.php | 2 +- .../DoctrineAppliedEventsStorageSetup.php | 1 - Symfony/Resources/config/services.yaml | 2 +- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/Symfony/Command/SetupCommand.php b/Symfony/Command/SetupCommand.php index 1ab805d0..44a0b87b 100644 --- a/Symfony/Command/SetupCommand.php +++ b/Symfony/Command/SetupCommand.php @@ -10,45 +10,54 @@ use Neos\Error\Messages\Warning; use Neos\EventSourcing\EventStore\EventStore; use Neos\EventSourcing\Symfony\EventListener\AppliedEventsStorage\DoctrineAppliedEventsStorageSetup; +use Psr\Container\ContainerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class SetupCommand extends Command { - // the name of the command (the part after "bin/console") protected static $defaultName = 'eventsourcing:store-setup'; - /** - * @var EventStore - */ - private $eventStore; - /** * @var DoctrineAppliedEventsStorageSetup */ private $doctrineAppliedEventsStorageSetup; /** - * SayHelloCommand constructor. - * @param EventStore $eventStore + * @var ContainerInterface */ - public function __construct(EventStore $eventStore, DoctrineAppliedEventsStorageSetup $doctrineAppliedEventsStorageSetup) + protected $container; + + public function __construct( + DoctrineAppliedEventsStorageSetup $doctrineAppliedEventsStorageSetup, + ContainerInterface $container + ) { - $this->eventStore = $eventStore; $this->doctrineAppliedEventsStorageSetup = $doctrineAppliedEventsStorageSetup; + $this->container = $container; + parent::__construct(); } - protected function configure() { - // ... + $this + ->setDescription('Creates the needed stores.') + ->setHelp('This command allows you to create the needed stores which are defined in the config.'); } protected function execute(InputInterface $input, OutputInterface $output) { - $result = $this->eventStore->setup(); + $config = $this->container->getParameter('neos_eventsourcing'); + + $result = new Result(); + foreach ($config['stores'] as $name => $store) { + $store = $this->container->get('neos_eventsourcing.eventstore.' . $name); + /* @var $store EventStore */ + $result->merge($store->setup()); + } + $result->merge($this->doctrineAppliedEventsStorageSetup->setup()); self::renderResult($result, $output); @@ -58,7 +67,6 @@ protected function execute(InputInterface $input, OutputInterface $output) return Command::SUCCESS; } - /** * Outputs the given Result object in a human-readable way * @@ -70,7 +78,15 @@ private static function renderResult(Result $result, OutputInterface $output): v /** @var Notice $notice */ foreach ($result->getNotices() as $notice) { if ($notice->getTitle() !== null) { - $output->writeln(vsprintf('%s: %s', [$notice->getTitle(), $notice->render()])); + $output->writeln( + vsprintf( + '%s: %s', + [ + $notice->getTitle(), + $notice->render() + ] + ) + ); } else { $output->writeln($notice->render()); } @@ -80,15 +96,37 @@ private static function renderResult(Result $result, OutputInterface $output): v if ($result->hasErrors()) { /** @var Error $error */ foreach ($result->getErrors() as $error) { - $output->writeln(vsprintf('ERROR: %s', [$error->render()])); + $output->writeln( + vsprintf( + 'ERROR: %s', + [ + $error->render() + ] + ) + ); } } elseif ($result->hasWarnings()) { /** @var Warning $warning */ foreach ($result->getWarnings() as $warning) { if ($warning->getTitle() !== null) { - $output->writeln(vsprintf('%s: %s !!!', [$warning->getTitle(), $warning->render()])); + $output->writeln( + vsprintf( + '%s: %s !!!', + [ + $warning->getTitle(), + $warning->render() + ] + ) + ); } else { - $output->writeln(vsprintf('%s !!!', [$warning->render()])); + $output->writeln( + vsprintf( + '%s !!!', + [ + $warning->render() + ] + ) + ); } } } else { diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php index 6673624a..b85b6e36 100644 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ b/Symfony/DependencyInjection/NeosEventSourcingExtension.php @@ -21,7 +21,7 @@ public function load(array $configs, ContainerBuilder $container) $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - //dump($config); + $container->setParameter('neos_eventsourcing', $config); $loader = new YamlFileLoader( $container, diff --git a/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php b/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php index 35c46942..602aeb1c 100644 --- a/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php +++ b/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php @@ -37,7 +37,6 @@ public function __construct(Connection $connection) $this->connection = $connection; } - /** * @inheritdoc * @throws DBALException | \Throwable diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml index a439a3be..6ce1f2bf 100644 --- a/Symfony/Resources/config/services.yaml +++ b/Symfony/Resources/config/services.yaml @@ -17,8 +17,8 @@ services: tags: ["console.command"] arguments: # TODO - $eventStore: "@neos_eventsourcing.eventstore.blog" # TODO needs adjustment $doctrineAppliedEventsStorageSetup: "@neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup" + $container: "@Psr\\Container\\ContainerInterface" neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup: class: Neos\EventSourcing\Symfony\EventListener\AppliedEventsStorage\DoctrineAppliedEventsStorageSetup From 001f26568087e72dbd1f261d585ccd664f584a8f Mon Sep 17 00:00:00 2001 From: Timo Nussbaum Date: Tue, 29 Dec 2020 15:45:35 +0100 Subject: [PATCH 10/10] Task: Move symfony code to the new symfony bridge. --- .../InternalCatchUpEventListenerCommand.php | 62 -------- Symfony/Command/SetupCommand.php | 136 ------------------ Symfony/DependencyInjection/Configuration.php | 55 ------- .../NeosEventSourcingExtension.php | 58 -------- .../DoctrineAppliedEventsStorageSetup.php | 108 -------------- .../EventPublisher/SymfonyEventPublisher.php | 98 ------------- Symfony/NeosEventSourcingBundle.php | 15 -- Symfony/Resources/EventSourcingMessage.php | 25 ---- Symfony/Resources/config/services.yaml | 37 ----- Symfony/Transport/AsyncTransportInterface.php | 11 -- Symfony/Transport/ConsoleCommandTransport.php | 29 ---- Symfony/Transport/MessengerTransport.php | 34 ----- composer.json | 6 +- symfony.md | 19 --- 14 files changed, 2 insertions(+), 691 deletions(-) delete mode 100644 Symfony/Command/InternalCatchUpEventListenerCommand.php delete mode 100644 Symfony/Command/SetupCommand.php delete mode 100644 Symfony/DependencyInjection/Configuration.php delete mode 100644 Symfony/DependencyInjection/NeosEventSourcingExtension.php delete mode 100644 Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php delete mode 100644 Symfony/EventPublisher/SymfonyEventPublisher.php delete mode 100644 Symfony/NeosEventSourcingBundle.php delete mode 100644 Symfony/Resources/EventSourcingMessage.php delete mode 100644 Symfony/Resources/config/services.yaml delete mode 100644 Symfony/Transport/AsyncTransportInterface.php delete mode 100644 Symfony/Transport/ConsoleCommandTransport.php delete mode 100644 Symfony/Transport/MessengerTransport.php delete mode 100644 symfony.md diff --git a/Symfony/Command/InternalCatchUpEventListenerCommand.php b/Symfony/Command/InternalCatchUpEventListenerCommand.php deleted file mode 100644 index 25882dcb..00000000 --- a/Symfony/Command/InternalCatchUpEventListenerCommand.php +++ /dev/null @@ -1,62 +0,0 @@ -container = $container; - $this->connection = $connection; - parent::__construct(); - } - - - protected function configure() - { - $this->addArgument('eventListenerClassName', InputArgument::REQUIRED); - $this->addArgument('eventStoreContainerId', InputArgument::REQUIRED); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $eventListenerClassName = $input->getArgument('eventListenerClassName'); - $eventStoreContainerId = $input->getArgument('eventStoreContainerId'); - - $listener = $this->container->get($eventListenerClassName); - $eventStore = $this->container->get($eventStoreContainerId); - - $eventListenerInvoker = new EventListenerInvoker($eventStore, $listener, $this->connection); - $eventListenerInvoker->catchUp(); - - return Command::SUCCESS; - } -} diff --git a/Symfony/Command/SetupCommand.php b/Symfony/Command/SetupCommand.php deleted file mode 100644 index 44a0b87b..00000000 --- a/Symfony/Command/SetupCommand.php +++ /dev/null @@ -1,136 +0,0 @@ -doctrineAppliedEventsStorageSetup = $doctrineAppliedEventsStorageSetup; - $this->container = $container; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Creates the needed stores.') - ->setHelp('This command allows you to create the needed stores which are defined in the config.'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $config = $this->container->getParameter('neos_eventsourcing'); - - $result = new Result(); - foreach ($config['stores'] as $name => $store) { - $store = $this->container->get('neos_eventsourcing.eventstore.' . $name); - /* @var $store EventStore */ - $result->merge($store->setup()); - } - - $result->merge($this->doctrineAppliedEventsStorageSetup->setup()); - self::renderResult($result, $output); - - if ($result->hasErrors()) { - return Command::FAILURE; - } - return Command::SUCCESS; - } - - /** - * Outputs the given Result object in a human-readable way - * - * @param Result $result - */ - private static function renderResult(Result $result, OutputInterface $output): void - { - if ($result->hasNotices()) { - /** @var Notice $notice */ - foreach ($result->getNotices() as $notice) { - if ($notice->getTitle() !== null) { - $output->writeln( - vsprintf( - '%s: %s', - [ - $notice->getTitle(), - $notice->render() - ] - ) - ); - } else { - $output->writeln($notice->render()); - } - } - } - - if ($result->hasErrors()) { - /** @var Error $error */ - foreach ($result->getErrors() as $error) { - $output->writeln( - vsprintf( - 'ERROR: %s', - [ - $error->render() - ] - ) - ); - } - } elseif ($result->hasWarnings()) { - /** @var Warning $warning */ - foreach ($result->getWarnings() as $warning) { - if ($warning->getTitle() !== null) { - $output->writeln( - vsprintf( - '%s: %s !!!', - [ - $warning->getTitle(), - $warning->render() - ] - ) - ); - } else { - $output->writeln( - vsprintf( - '%s !!!', - [ - $warning->render() - ] - ) - ); - } - } - } else { - $output->writeln('SUCCESS'); - } - } -} diff --git a/Symfony/DependencyInjection/Configuration.php b/Symfony/DependencyInjection/Configuration.php deleted file mode 100644 index 5b9d292d..00000000 --- a/Symfony/DependencyInjection/Configuration.php +++ /dev/null @@ -1,55 +0,0 @@ -getRootNode(); - - $this->addDbalSection($rootNode); - - return $treeBuilder; - } - - /** - * Add DBAL section to configuration tree - */ - private function addDbalSection(ArrayNodeDefinition $node): void - { - $node - ->children() - ->arrayNode('stores') - ->arrayPrototype() - ->children() - ->scalarNode('eventTableName')->end() - ->arrayNode('listenerClassNames') - ->scalarPrototype()->end() - ->end() - ->end() - ->end() - ->end() - ->end(); - } -} diff --git a/Symfony/DependencyInjection/NeosEventSourcingExtension.php b/Symfony/DependencyInjection/NeosEventSourcingExtension.php deleted file mode 100644 index b85b6e36..00000000 --- a/Symfony/DependencyInjection/NeosEventSourcingExtension.php +++ /dev/null @@ -1,58 +0,0 @@ -processConfiguration($configuration, $configs); - - $container->setParameter('neos_eventsourcing', $config); - - $loader = new YamlFileLoader( - $container, - new FileLocator(__DIR__ . '/../Resources/config') - ); - $loader->load('services.yaml'); - - foreach ($config['stores'] as $name => $store) { - $container->register('neos_eventsourcing.eventstore.' . $name) - ->setClass(EventStore::class) - ->setPublic(true) - ->setArgument('$storage', new Reference('neos_eventsourcing.eventstore.' . $name . '.storage')) - ->setArgument('$eventPublisher', new Reference('neos_eventsourcing.eventstore.' . $name . '.publisher')) - ->setArgument('$eventNormalizer', new Reference('neos_eventsourcing_eventStore_eventNormalizer')); - - $container->register('neos_eventsourcing.eventstore.' . $name . '.storage') - ->setClass(DoctrineEventStorage::class) // TODO make configurable - ->setArgument('$options', ['eventTableName' => $store['eventTableName']]) - ->setArgument('$eventNormalizer', new Reference('neos_eventsourcing_eventStore_eventNormalizer')) - ->setArgument('$connection', new Reference(Connection::class)); - - $container->register('neos_eventsourcing.eventstore.' . $name . '.publisher') - ->setClass(SymfonyEventPublisher::class) - ->setArgument('$asyncTransport', new Reference(AsyncTransportInterface::class)) - ->setArgument('$eventDispatcher', new Reference(EventDispatcherInterface::class)) - ->setArgument('$eventStoreContainerId', 'neos_eventsourcing.eventstore.' . $name); - } - } - - public function getAlias() - { - return 'neos_eventsourcing'; - } -} diff --git a/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php b/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php deleted file mode 100644 index 602aeb1c..00000000 --- a/Symfony/EventListener/AppliedEventsStorage/DoctrineAppliedEventsStorageSetup.php +++ /dev/null @@ -1,108 +0,0 @@ -connection = $connection; - } - - /** - * @inheritdoc - * @throws DBALException | \Throwable - */ - public function setup(): Result - { - $result = new Result(); - $schemaManager = $this->connection->getSchemaManager(); - if ($schemaManager === null) { - $result->addError(new Error('Failed to retrieve Schema Manager', 1592381759, [], 'Connection failed')); - return $result; - } - try { - $tableExists = $schemaManager->tablesExist([AppliedEventsLog::TABLE_NAME]); - } catch (ConnectionException $exception) { - $result->addError(new Error($exception->getMessage(), $exception->getCode(), [], 'Connection failed')); - return $result; - } - if ($tableExists) { - $result->addNotice(new Notice('Table "%s" (already exists)', null, [AppliedEventsLog::TABLE_NAME])); - } else { - $result->addNotice(new Notice('Creating database table "%s" in database "%s" on host %s....', null, [AppliedEventsLog::TABLE_NAME, $this->connection->getDatabase(), $this->connection->getHost()])); - } - - $fromSchema = $schemaManager->createSchema(); - $schemaDiff = (new Comparator())->compare($fromSchema, $this->createEventStoreSchema()); - - $statements = $schemaDiff->toSaveSql($this->connection->getDatabasePlatform()); - if ($statements === []) { - $result->addNotice(new Notice('Table schema is up to date, no migration required')); - return $result; - } - $this->connection->beginTransaction(); - try { - foreach ($statements as $statement) { - $result->addNotice(new Notice('++ %s', null, [$statement])); - $this->connection->exec($statement); - } - $this->connection->commit(); - } catch (\Throwable $exception) { - $this->connection->rollBack(); - throw $exception; - } - return $result; - } - - /** - * Creates the Doctrine schema to be compared with the current db schema for migration - * - * @return Schema - */ - private function createEventStoreSchema(): Schema - { - $schemaConfiguration = new SchemaConfig(); - $connectionParameters = $this->connection->getParams(); - if (isset($connectionParameters['defaultTableOptions'])) { - $schemaConfiguration->setDefaultTableOptions($connectionParameters['defaultTableOptions']); - } - $schema = new Schema([], [], $schemaConfiguration); - $table = $schema->createTable(AppliedEventsLog::TABLE_NAME); - - $table->addColumn('eventlisteneridentifier', Types::STRING, ['length' => 255]); - $table->addColumn('highestappliedsequencenumber', Types::INTEGER); - - $table->setPrimaryKey(['eventlisteneridentifier']); - - return $schema; - } -} \ No newline at end of file diff --git a/Symfony/EventPublisher/SymfonyEventPublisher.php b/Symfony/EventPublisher/SymfonyEventPublisher.php deleted file mode 100644 index c9e78fc9..00000000 --- a/Symfony/EventPublisher/SymfonyEventPublisher.php +++ /dev/null @@ -1,98 +0,0 @@ -asyncTransport = $asyncTransport; - $this->eventDispatcher = $eventDispatcher; - $this->eventStoreContainerId = $eventStoreContainerId; - } - - - public function publish(DomainEvents $events): void - { - // TODO: listener filter - - $queuedEventListenerClassNames = []; - $processedEventClassNames = []; - foreach ($events as $event) { - /** @var string $eventClassName */ - $eventClassName = \get_class($event instanceof DecoratedEvent ? $event->getWrappedEvent() : $event); - - // only process every Event type once - if (isset($processedEventClassNames[$eventClassName])) { - continue; - } - - - // NOTE: eventDispatcher is ONLY used for resolving the class name of the listener. - // you are NEVER allowed to call $this->eventDispatcher->dispatch($event, $eventClassName); - // because otherwise, the appliedEventsLog is not updated properly. - $listeners = $this->eventDispatcher->getListeners($eventClassName); - //dump($listeners); - - foreach ($listeners as $listenerClassNameAndMethodName) { - $listenerClassName = get_class($listenerClassNameAndMethodName[0]); - - // only process every Event Listener once - if (isset($queuedEventListenerClassNames[$listenerClassName])) { - continue; - } - - $this->triggerAsyncBackgroundJob($listenerClassName); - - $queuedEventListenerClassNames[$listenerClassName] = true; - } - - - // we have to know: "what event listers do we need to trigger"? - /*foreach ($this->mappings as $mapping) { - if ($mapping->getEventClassName() !== $eventClassName) { - continue; - } - // only process every Event Listener once - if (isset($queuedEventListenerClassNames[$mapping->getListenerClassName()])) { - continue; - } - $queueName = $mapping->getOption('queueName', self::DEFAULT_QUEUE_NAME); - $options = $mapping->getOption('queueOptions', []); - $this->jobManager->queue($queueName, new CatchUpEventListenerJob($mapping->getListenerClassName(), $this->eventStoreIdentifier), $options); - $queuedEventListenerClassNames[$mapping->getListenerClassName()] = true; - }*/ - } - - } - - private function triggerAsyncBackgroundJob($listenerClassName) - { - $this->asyncTransport->send( - $listenerClassName, - $this->eventStoreContainerId - ); - } -} diff --git a/Symfony/NeosEventSourcingBundle.php b/Symfony/NeosEventSourcingBundle.php deleted file mode 100644 index 719c2170..00000000 --- a/Symfony/NeosEventSourcingBundle.php +++ /dev/null @@ -1,15 +0,0 @@ -listenerClassName = $listenerClassName; - $newMessage->eventStoreContainerId = $eventStoreContainerId; - - return $newMessage; - } -} diff --git a/Symfony/Resources/config/services.yaml b/Symfony/Resources/config/services.yaml deleted file mode 100644 index 6ce1f2bf..00000000 --- a/Symfony/Resources/config/services.yaml +++ /dev/null @@ -1,37 +0,0 @@ -parameters: - neos_foo: - -services: - - # TODO: this should be configured "PER BOUNDED CONTEXT" (analogous to how Doctrine DBAL connections are handled) - neos_eventsourcing_event_eventTypeResolver: - class: Neos\EventSourcing\Event\Resolver\FullyQualifiedClassNameResolver - - neos_eventsourcing_eventStore_eventNormalizer: - class: Neos\EventSourcing\EventStore\EventNormalizer - arguments: - $eventTypeResolver: "@neos_eventsourcing_event_eventTypeResolver" - - neos_eventsourcing_symfony_command_setupCommand: - class: Neos\EventSourcing\Symfony\Command\SetupCommand - tags: ["console.command"] - arguments: - # TODO - $doctrineAppliedEventsStorageSetup: "@neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup" - $container: "@Psr\\Container\\ContainerInterface" - - neos_eventsourcing_symfony_eventlistener_appliedeventsstorage_doctrineAppliedEventsStorageSetup: - class: Neos\EventSourcing\Symfony\EventListener\AppliedEventsStorage\DoctrineAppliedEventsStorageSetup - arguments: - $connection: "@Doctrine\\DBAL\\Connection" - - - neos_eventsourcing_symfony_command_internalFooCommand: - class: Neos\EventSourcing\Symfony\Command\InternalCatchUpEventListenerCommand - tags: [ "console.command" ] - arguments: - $container: "@Psr\\Container\\ContainerInterface" - $connection: "@Doctrine\\DBAL\\Connection" - - Neos\EventSourcing\Symfony\Transport\ConsoleCommandTransport: ~ - Neos\EventSourcing\Symfony\Transport\AsyncTransportInterface: '@Neos\EventSourcing\Symfony\Transport\ConsoleCommandTransport' diff --git a/Symfony/Transport/AsyncTransportInterface.php b/Symfony/Transport/AsyncTransportInterface.php deleted file mode 100644 index cfd242b1..00000000 --- a/Symfony/Transport/AsyncTransportInterface.php +++ /dev/null @@ -1,11 +0,0 @@ -run(); // !! WE DO NOT WAIT FOR THE RESULT - start !! - TODO: adjust - $errOut = $process->getOutput() . $process->getErrorOutput(); - } -} \ No newline at end of file diff --git a/Symfony/Transport/MessengerTransport.php b/Symfony/Transport/MessengerTransport.php deleted file mode 100644 index 7cfe0c23..00000000 --- a/Symfony/Transport/MessengerTransport.php +++ /dev/null @@ -1,34 +0,0 @@ -messageBus = $messageBus; - } - - public function send( - string $listenerClassName, - string $eventStoreContainerId - ) - { - $message = EventSourcingMessage::create( - $listenerClassName, - $eventStoreContainerId - ); - $this->messageBus->dispatch( - $message - ); - } -} \ No newline at end of file diff --git a/composer.json b/composer.json index 59e02ac6..10126045 100644 --- a/composer.json +++ b/composer.json @@ -16,13 +16,11 @@ "dg/bypass-finals": "^1.2" }, "suggest": { - "flowpack/jobqueue-common": "Needed for Neos/Flow usage only", - "symfony/process": "Needed for standalone usage" + "flowpack/jobqueue-common": "Needed for Neos/Flow usage only" }, "autoload": { "psr-4": { - "Neos\\EventSourcing\\": "Classes", - "Neos\\EventSourcing\\Symfony\\": "Symfony" + "Neos\\EventSourcing\\": "Classes" } }, "autoload-dev": { diff --git a/symfony.md b/symfony.md deleted file mode 100644 index f32b0f75..00000000 --- a/symfony.md +++ /dev/null @@ -1,19 +0,0 @@ -# doctrine.yaml - -doctrine: - dbal: - connections: - default: - url: '%env(resolve:DATABASE_URL)%' - - # IMPORTANT: You MUST configure your server version, - # either here or in the DATABASE_URL env var (see .env file) - server_version: '5.7' - - default_table_options: - charset: utf8mb4 - collate: utf8mb4_unicode_ci - - - -... make projectors public (could be later done with compiler pass) \ No newline at end of file