### Docker Setup for Ecotone Tutorial Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/before-we-start-tutorial.md Instructions for setting up and running the Ecotone tutorial using Docker. This includes starting the Docker compose, entering the container, installing dependencies, and running the quickstart command. ```php /** Ecotone Quickstart ships with docker-compose with preinstalled PHP 8.0 */ 1. Run "docker-compose up -d" 2. Enter container "docker exec -it ecotone-quickstart /bin/bash" 3. Run starting command "composer install" 4. Run starting command "bin/console ecotone:quickstart" 5. You should see: "Running example... Hello World Good job, scenario ran with success!" ``` -------------------------------- ### Console Command for Quickstart Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-metadata-method-invocation.md Example of a console command to run the Ecotone quickstart example, demonstrating product registration and price retrieval. ```bash bin/console ecotone:quickstart ``` -------------------------------- ### Ecotone Quickstart Output Example Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-serialization-deserialization.md Example output from the Ecotone quickstart command, showing successful product registration and cost retrieval. ```text Running example... Product with id 1 was registered! 100 Good job, scenario ran with success! ``` -------------------------------- ### Local Environment Setup for Ecotone Tutorial Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/before-we-start-tutorial.md Instructions for setting up and running the Ecotone tutorial on a local environment. Requires PHP 8.0+ and Composer. Includes installing dependencies and running the quickstart command. ```php /** You need to have atleast PHP 8.0 and Composer installed */ 1. Run "composer install" 2. Run starting command "bin/console ecotone:quickstart" 3. You should see: "Running example... Hello World Good job, scenario ran with success!" ``` -------------------------------- ### Running Ecotone Quickstart Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md This command executes the Ecotone quickstart example with verbose output, demonstrating the successful processing of a scenario. ```bash bin/console ecotone:quickstart -vvv Running example... 400 Good job, scenario ran with success! ``` -------------------------------- ### Ecotone Quickstart Example Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md Demonstrates registering products, placing an order, and retrieving the total order price using Ecotone's CommandBus and QueryBus. ```php class EcotoneQuickstart { private CommandBus $commandBus; private QueryBus $queryBus; public function __construct(CommandBus $commandBus, QueryBus $queryBus) { $this->commandBus = $commandBus; $this->queryBus = $queryBus; } public function run() : void { $this->commandBus->sendWithRouting( "product.register", ["productId" => 1, "cost" => 100] ); $this->commandBus->sendWithRouting( "product.register", ["productId" => 2, "cost" => 300] ); $orderId = 100; $this->commandBus->sendWithRouting( "order.place", ["orderId" => $orderId, "productIds" => [1,2]] ); echo $this->queryBus->convertAndSend("order.getTotalPrice", MediaType::APPLICATION_X_PHP_ARRAY, ["orderId" => $orderId]); } } ``` -------------------------------- ### Run Testing Command Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-domain-driven-design.md Execute the Ecotone quickstart console command to run tests and verify the setup. This command is used to trigger the application's quick start scenario. ```bash bin/console ecotone:quickstart Running example... 100 Good job, scenario ran with success! ``` -------------------------------- ### Run Ecotone Quickstart Example Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-interceptors-middlewares.md Executes the Ecotone quickstart command to run the example. This command triggers the registered commands and queries, demonstrating the interceptor logic in action. ```bash bin/console ecotone:quickstart Running example... Product with id 1 was registered! 110 Good job, scenario ran with success! ``` -------------------------------- ### Example Output with Exception Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-metadata-method-invocation.md Shows the expected output when running the quickstart command, including the registration success message and the InvalidArgumentException due to unauthorized price change. ```text bin/console ecotone:quickstart Running example... Product with id 1 was registered! InvalidArgumentException You are not allowed to change the cost of this product ``` -------------------------------- ### Ecotone Quickstart Command Output Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-messaging-architecture.md Demonstrates the expected output from the ecotone:quickstart console command, indicating a successful initial setup. ```bash bin/console ecotone:quickstart "Running example... Hello World Good job, scenario ran with success!" ``` -------------------------------- ### Console Output Example Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md Shows the expected output when running the Ecotone quickstart example, including transaction logs and the final calculated price. ```text bin/console ecotone:quickstart Running example... Start transaction Product with id 1 was registered! Commit transaction Start transaction Product with id 2 was registered! Commit transaction Start transaction Commit transaction 400 Good job, scenario ran with success! ``` -------------------------------- ### Install Kafka Support Source: https://github.com/ecotoneframework/documentation/blob/main/modules/kafka-support/configuration.md Install the Kafka support library using Composer. ```bash composer require ecotone/kafka ``` -------------------------------- ### Autoregistered Ecotone Quickstart Class Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-messaging-architecture.md This class is automatically registered using PHP-DI's auto-wiring system. It's intended for quickstart examples and focuses on Ecotone's capabilities. ```php run('projections'); ``` -------------------------------- ### Install AMQP Support Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/configuration.md Install the Ecotone AMQP support package using Composer. ```bash composer require ecotone/amqp ``` -------------------------------- ### Start Position: First Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/message-channel.md Configure the consumer to start from the beginning of the stream, replaying all existing events. ```php // Start from the beginning (replay all events) AmqpStreamChannelBuilder::create( channelName: "events", startPosition: "first", queueName: "events_stream", messageGroupId: "replay-consumer" ) ``` -------------------------------- ### Clone Lite Tutorial Repository Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/before-we-start-tutorial.md Use this command to download the starting point for the Lite (no extra framework) version of the tutorial. ```bash git clone git@github.com:ecotoneframework/lite-tutorial.git # Go to lite-tutorial catalog ``` -------------------------------- ### Clone Symfony Tutorial Repository Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/before-we-start-tutorial.md Use this command to download the starting point for the Symfony version of the tutorial. ```bash git clone git@github.com:ecotoneframework/symfony-tutorial.git # Go to symfony-tutorial catalog ``` -------------------------------- ### Start Docker Environment Source: https://github.com/ecotoneframework/documentation/blob/main/messaging/contributing-to-ecotone/README.md Use this command to start the local development environment with Docker containers. Ensure you have copied `.env.dist` to `.env` first. ```bash docker-compose up -d ``` -------------------------------- ### Lite Connection Factory Setup Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/message-channel.md Bootstrap Ecotone Lite with the AmqpLib connection factory. ```php use Enqueue\AmqpLib\AmqpConnectionFactory; $application = EcotoneLite::bootstrap( [AmqpConnectionFactory::class => new AmqpConnectionFactory("amqp://guest:guest@localhost:5672//")] ); ``` -------------------------------- ### Install GRPC and Protobuf PHP Extensions and Packages Source: https://github.com/ecotoneframework/documentation/blob/main/modules/opentelemetry-tracing-and-metrics/configuration.md Install the GRPC and Protobuf PHP extensions and the corresponding OpenTelemetry transport and exporter packages for efficient trace sending. ```bash # Install PHP Extensions install-php-extensions grpc protobuf # Install PHP Packages in your application composer require open-telemetry/transport-grpc composer require open-telemetry/exporter-otlp ``` -------------------------------- ### Install OpenTelemetry Composer Package Source: https://github.com/ecotoneframework/documentation/blob/main/modules/opentelemetry-tracing-and-metrics/configuration.md Install the OpenTelemetry integration package for Ecotone using Composer. ```bash composer require ecotone/open-telemetry ``` -------------------------------- ### Usage Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/microservices-php/message-publisher.md Example of how to use the Message Publisher within an event handler. ```APIDOC ## How to use Message Publisher Publisher is a special type of [Gateway](../../messaging/messaging-concepts/messaging-gateway.md), which implements [Publisher interface](../../modules/amqp-support-rabbitmq/#available-actions). It will be available in your Dependency Container under passed `Reference name.` In case interface name `MessagePublisher:class` is used, it will be available using auto-wire. ```php #[EventHandler] public function whenOrderWasPlaced(OrderWasPlaced $event, MessagePublisher $publisher) : void { $publisher->convertAndSendWithMetadata( $event, [ "system.executor" => "Johny" ] ); } ``` ``` -------------------------------- ### V2 Projection Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/upgrading-from-v1.md Example of a new V2 projection using #[ProjectionV2] and #[FromAggregateStream]. Includes initialization, deletion, and reset methods. ```php connection->insert('ticket_list_v2', [ 'ticket_id' => $event->ticketId, 'ticket_type' => $event->type, 'status' => 'open', ]); } #[ProjectionInitialization] public function init(): void { /* CREATE TABLE ticket_list_v2 */ } #[ProjectionDelete] public function delete(): void { /* DROP TABLE ticket_list_v2 */ } #[ProjectionReset] public function reset(): void { /* DELETE FROM ticket_list_v2 */ } } ``` -------------------------------- ### Install Redis Support via Composer Source: https://github.com/ecotoneframework/documentation/blob/main/modules/redis-support.md Install the Redis support package using Composer. ```bash composer require ecotone/redis ``` -------------------------------- ### Configure RabbitMQ Connection Factory in Lite Setup Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/configuration.md Bootstrap Ecotone with the AmqpConnectionFactory for a lightweight setup. This registers the connection directly. ```php use Enqueue\AmqpExt\AmqpConnectionFactory; $application = EcotoneLiteApplication::boostrap( [ AmqpConnectionFactory::class => new AmqpConnectionFactory("amqp+lib://guest:guest@localhost:5672//") ] ); ``` -------------------------------- ### Install Context7 MCP Source: https://github.com/ecotoneframework/documentation/blob/main/other/ai-integration.md Install the Context7 MCP package to enable access to Ecotone and other library documentation through your AI assistant. ```bash npx -y @upstash/context7-mcp ``` -------------------------------- ### Install Data Protection Module Source: https://github.com/ecotoneframework/documentation/blob/main/modules/data-protection/README.md Install the Ecotone Data Protection module using Composer. ```bash composer require ecotone/data-protection ``` -------------------------------- ### Consumer Endpoint Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/recovering-tracing-and-monitoring/resiliency/retries.md An example of an asynchronous event handler that might benefit from retry strategies. ```php #[Asynchronous("asynchronous_messages")] #[EventHandler(endpointId: "notifyAboutNewOrder")] public function notifyAboutNewOrder(OrderWasPlaced $event, NotificationService $notificationService) : void { $notificationService->notifyAboutNewOrder($event->getOrderId()); } ``` -------------------------------- ### Lite - Local AmqpConnectionFactory Setup Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md Manually set AmqpConnectionFactory in the container within bin/console.php for a lightweight local setup. Requires RabbitMQ running on localhost. ```php # Add AmqpConnectionFactory in bin/console.php // add additional service in container public function __construct() { $this->container = new Container(); $this->container->set(Enqueue\AmqpExt\AmqpConnectionFactory::class, new Enqueue\AmqpExt\AmqpConnectionFactory("amqp+lib://guest:guest@localhost:5672//")); } ``` -------------------------------- ### Install Ecotone DBAL Package Source: https://github.com/ecotoneframework/documentation/blob/main/modules/dbal-support.md Install the Ecotone DBAL support package using Composer. ```php composer require ecotone/dbal ``` -------------------------------- ### Install Doctrine DBAL Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-interceptors-middlewares.md Install the Doctrine DBAL library using Composer to manage database interactions. ```bash composer require doctrine/dbal ``` -------------------------------- ### Install Ecotone Lite Application Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Install the Ecotone Lite Application package, which provides a pre-configured dependency injection container for Ecotone Lite. ```bash composer require ecotone/lite-application ``` -------------------------------- ### Automatic Header Propagation Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/extending-messaging-middlewares/message-headers.md Demonstrates how headers like 'executorId' are automatically propagated from a command to an event handler, even if not explicitly resent. ```php $this->commandBus->send( new BlockerUser($request->get("userId")), ["executorId" => $security->getUser()->getCurrentId()] ); ``` ```php #[CommandHandler] public function closeTicket(BlockerUser $command, EventBus $eventBus) { // handle blocking user $eventBus->publish(new UserWasBlocked($command->id)); } ``` ```php #[EventHandler] public function closeTicket( UserWasBlocked $command, #[Header('executorId')] $executorId ) { // handle storing audit data } ``` -------------------------------- ### Execute Console Command with Options Source: https://github.com/ecotoneframework/documentation/blob/main/messaging/console-commands.md Examples of executing a console command with options using Symfony, Laravel, and Ecotone's Lite mode. ```bash bin/console sendEmail "test@example.com" --type="welcome" ``` ```bash php artisan sendEmail "test@example.com" --type="welcome" ``` ```php $messagingSystem->runConsoleCommand( 'sendEmail', [ "email" => "test@example.com", "type" => "welcome" ] ) ``` -------------------------------- ### Lite - Docker AmqpConnectionFactory Setup Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md Manually set AmqpConnectionFactory in the container within bin/console.php for a lightweight Dockerized setup. Assumes RabbitMQ is accessible via the 'rabbitmq' hostname. ```php # Add AmqpConnectionFactory in bin/console.php // add additional service in container public function __construct() { $this->container = new Container(); $this->container->set(Enqueue\AmqpExt\AmqpConnectionFactory::class, new Enqueue\AmqpExt\AmqpConnectionFactory("amqp+lib://guest:guest@rabbitmq:5672//")); } ``` -------------------------------- ### Basic Kafka Consumer Setup Source: https://github.com/ecotoneframework/documentation/blob/main/modules/kafka-support/kafka-consumer.md Mark a method with the KafkaConsumer attribute to consume messages from specified topics. The consumer will run asynchronously. ```php #[KafkaConsumer( endpointId: 'orderConsumers', topics: ['orders'] )] public function handle(string $payload, array $metadata): void { // do something } ``` -------------------------------- ### Symfony Connection Factory Setup Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/message-channel.md Configure the AmqpLib connection factory in Symfony's services.yaml. ```yaml # config/services.yaml Enqueue\AmqpLib\AmqpConnectionFactory: class: Enqueue\AmqpLib\AmqpConnectionFactory arguments: - "amqp://guest:guest@localhost:5672//" ``` -------------------------------- ### Install Ecotone and Enqueue SQS Packages Source: https://github.com/ecotoneframework/documentation/blob/main/messaging/contributing-to-ecotone/demo-integration-with-sqs/preparation.md Add the necessary Ecotone and Enqueue SQS packages to your project using Composer. ```bash composer require enqueue/sqs && composer require ecotone/enqueue ``` -------------------------------- ### Run Message Consumer with Ecotone CLI Source: https://github.com/ecotoneframework/documentation/blob/main/modules/symfony/symfony-messenger-transport.md Start the Ecotone message consumer for the 'async' transport using the console command. ```bash bin/console ecotone:run async -vvv ``` -------------------------------- ### Execute Console Command with Arguments Source: https://github.com/ecotoneframework/documentation/blob/main/messaging/console-commands.md Examples of executing a console command with arguments using Symfony, Laravel, and Ecotone's Lite mode. ```bash bin/console sendEmail "test@example.com" "welcome" ``` ```bash php artisan sendEmail "test@example.com" "welcome" ``` ```php $messagingSystem->runConsoleCommand( 'sendEmail', [ "email" => "test@example.com", "type" => "welcome" ] ) ``` -------------------------------- ### Install Ecotone with Composer Source: https://github.com/ecotoneframework/documentation/blob/main/README.md Install Ecotone for Laravel or Symfony using Composer. This is the initial setup step for integrating Ecotone into your project. ```bash composer require ecotone/laravel # or ecotone/symfony-bundle ``` -------------------------------- ### Clone Laravel Tutorial Repository Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/before-we-start-tutorial.md Use this command to download the starting point for the Laravel version of the tutorial. Note that 'artisan' is aliased to 'bin/console' for consistency. ```bash git clone git@github.com:ecotoneframework/laravel-tutorial.git # Go to laravel-tutorial catalog # Normally you will use "php artisan" for running console commands # To reduce number of difference during the tutorial # "artisan" is changed to "bin/console" ``` -------------------------------- ### Run Message Consumer (Lite) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/asynchronous-handling/asynchronous-message-handlers.md In a Lite Ecotone setup, use the run() method on the messaging system with the endpoint name to start a message consumer. ```php $messagingSystem->run("orders"); ``` -------------------------------- ### Run Testing Command with Event Publishing Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-domain-driven-design.md Execute the Ecotone quickstart console command after implementing event publishing. This verifies that events recorded within the aggregate are now correctly processed. ```bash bin/console ecotone:quickstart Running example... Product with id 1 was registered! 100 Good job, scenario ran with success! ``` -------------------------------- ### Run Polling Projection in Lite Mode Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/scaling-and-advanced.md Start a polling projection in a lite Ecotone setup by calling the `run` method on the messaging system with the poller's endpoint ID. ```php $messagingSystem->run('analytics_poller'); ``` -------------------------------- ### Testing Handler Chains with EcotoneLite Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/connecting-handlers-with-channels.md Test complete business workflows from start to finish using EcotoneLite's flow testing capabilities. This example demonstrates testing a successful order processing workflow and a workflow that stops on validation errors. ```php class ProcessOrder { private array $placedOrders = []; private array $verifiedOrders = []; #[CommandHandler( 'verify.order', outputChannelName: 'place.order' )] public function verify(PlaceOrder $command): PlaceOrder { $this->verifiedOrders[] = $command->orderId; if ($command->orderId === 'invalid-order') { throw new InvalidOrderException('Order validation failed'); } return $command; } #[InternalHandler('place.order')] public function place(PlaceOrder $command): void { $this->placedOrders[] = $command->orderId; } // In production application you would most likely have some repository public function wasOrderVerified(string $orderId): bool { return in_array($orderId, $this->verifiedOrders); } public function wasOrderPlaced(string $orderId): bool { return in_array($orderId, $this->placedOrders); } } class WorkflowChainTest extends TestCase { public function test_successful_order_workflow(): void { $processor = new ProcessOrder(); $ecotoneLite = EcotoneLite::bootstrapFlowTesting( [ProcessOrder::class], [$processor] ); // Send to the first step of the workflow $command = new PlaceOrder('order-123', 'customer-456'); $ecotoneLite->sendDirectToChannel('verify.order', $command); // Verify both steps executed $this->assertTrue($processor->wasOrderVerified('order-123')); $this->assertTrue($processor->wasOrderPlaced('order-123')); } public function test_workflow_stops_on_validation_error(): void { $processor = new ProcessOrder(); $ecotoneLite = EcotoneLite::bootstrapFlowTesting( [ProcessOrder::class], [$processor] ); // This should fail validation and not reach the place step $this->expectException(InvalidOrderException::class); $command = new PlaceOrder('invalid-order', 'customer-456'); $ecotoneLite->sendDirectToChannel('verify.order', $command); // Verify verification was attempted but placement was not $this->assertTrue($processor->wasOrderVerified('invalid-order')); $this->assertFalse($processor->wasOrderPlaced('invalid-order')); } } ``` -------------------------------- ### Lite Ecotone Quickstart File Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-messaging-architecture.md Indicates the location of the EcotoneQuickstart class within a Lite Ecotone project. This file is typically located in the src directory. ```php Go to "src/EcotoneQuickstart.php" ``` -------------------------------- ### View Database Migration Status (Lite) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Execute the `ecotone:migration:database:setup` command via the `runConsoleCommand` method to view the status of database features. Arguments can be passed to filter results. ```php // Show all features and their status $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', []); // Show only used features (default) $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', ['onlyUsed' => true]); // Show all available features $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', ['onlyUsed' => false]); // Show status for specific features $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', [ 'feature' => ['dead_letter', 'deduplication'] ]); ``` -------------------------------- ### Initialize and Clean Up Ecotone Migrations with Ecotone Lite Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Demonstrates how to use Ecotone Lite to run migration console commands for database and channel setup, initialization, and deletion within a testing environment. Ensure Ecotone Lite and necessary configurations are bootstrapped. ```php use Ecotone horace use Ecotone horace use Ecotone horace $ecotone = EcotoneLite::bootstrapFlowTesting( containerOrAvailableServices: [ DbalConnectionFactory::class => $connectionFactory, ], configuration: ServiceConfiguration::createWithDefaults() ->withExtensionObjects([ DbalConfiguration::createWithDefaults() ->withAutomaticTableInitialization(false), ChannelInitializationConfiguration::createWithDefaults() ->withAutomaticChannelInitialization(false), ]), ); // Initialize storage in test setup $ecotone->runConsoleCommand('ecotone:migration:database:setup', ['initialize' => true]); $ecotone->runConsoleCommand('ecotone:migration:channel:setup', ['initialize' => true]); // Run your tests... // Clean up in teardown $ecotone->runConsoleCommand('ecotone:migration:database:delete', ['force' => true]); $ecotone->runConsoleCommand('ecotone:migration:channel:delete', ['force' => true]); ``` -------------------------------- ### V1 Projection Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/upgrading-from-v1.md Example of an existing V1 projection using the #[Projection] annotation. ```php connection->insert('ticket_list', [ 'ticket_id' => $event->ticketId, 'ticket_type' => $event->type, 'status' => 'open', ]); } #[ProjectionInitialization] public function init(): void { /* CREATE TABLE ticket_list */ } } ``` -------------------------------- ### Symfony Ecotone Quickstart File Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-messaging-architecture.md Indicates the location of the EcotoneQuickstart class within a Symfony project. This class is automatically registered via Symfony Autowire. ```php Go to "src/EcotoneQuickstart.php" # This class is autoregistered using Symfony Autowire ``` -------------------------------- ### Initialize Database Tables (Lite) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Use these commands to set up the necessary database tables for Ecotone features in a Lite configuration. You can initialize all used features, specific features by name, or all available features regardless of usage. ```php // Initialize all used features $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', ['initialize' => true]); ``` ```php // Initialize specific features only $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', [ 'feature' => ['dead_letter'], 'initialize' => true ]); ``` ```php // Initialize all available features (including unused) $messagingSystem->runConsoleCommand('ecotone:migration:database:setup', [ 'initialize' => true, 'onlyUsed' => false ]); ``` -------------------------------- ### Initialize Database Tables Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Use these commands to set up the necessary database tables for Ecotone features. You can initialize all used features, specific features by name, or all available features regardless of usage. ```bash # Initialize all used features bin/console ecotone:migration:database:setup --initialize=true ``` ```bash # Initialize specific features only bin/console ecotone:migration:database:setup --feature=dead_letter --initialize=true ``` ```bash # Initialize all available features (including unused) bin/console ecotone:migration:database:setup --initialize=true --onlyUsed=false ``` -------------------------------- ### Laravel Ecotone Quickstart File Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-messaging-architecture.md Indicates the location of the EcotoneQuickstart class within a Laravel project. This class is automatically registered via Laravel Autowire. ```php Go to "app/EcotoneQuickstart.php" # This class is autoregistered using Laravel Autowire ``` -------------------------------- ### Start Position: Last Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amqp-support-rabbitmq/message-channel.md Configure the consumer to start from the end of the stream, processing only new messages. ```php // Start from the end (only new events) AmqpStreamChannelBuilder::create( channelName: "events", startPosition: "last", queueName: "events_stream", messageGroupId: "new-events-consumer" ) ``` -------------------------------- ### Configure Partitioned Projection for Blue-Green Deployment Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/blue-green-deployments.md Configure a new v2 projection as partitioned, with manual kickoff and live mode disabled initially. This allows for backfilling historical data without emitting duplicate events. The same handlers are used, but events are tracked per-aggregate. ```php #[ProjectionV2('tickets_v2')] #[FromAggregateStream(Ticket::class)] #[Partitioned] #[ProjectionDeployment(manualKickOff: true, live: false)] class TicketsV2Projection extends TicketsProjection { // Same handlers, now partitioned } ``` -------------------------------- ### Initialize Database Tables (Laravel) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Use these commands to set up the necessary database tables for Ecotone features within a Laravel project. You can initialize all used features, specific features by name, or all available features regardless of usage. ```bash # Initialize all used features php artisan ecotone:migration:database:setup --initialize=true ``` ```bash # Initialize specific features only php artisan ecotone:migration:database:setup --feature=dead_letter --initialize=true ``` ```bash # Initialize all available features (including unused) php artisan ecotone:migration:database:setup --initialize=true --onlyUsed=false ``` -------------------------------- ### Start Asynchronous Worker (Laravel) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/execution-modes.md Command to start the background worker for asynchronous projections in a Laravel application. ```bash artisan ecotone:run projections -vvv ``` -------------------------------- ### Start Asynchronous Worker (Symfony) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/execution-modes.md Command to start the background worker for asynchronous projections in a Symfony application. ```bash bin/console ecotone:run projections -vvv ``` -------------------------------- ### Start Event Store Feeder in Symfony Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/scaling-and-advanced.md Run the Event Store adapter feeder using the Symfony console command `ecotone:run` with the adapter's endpoint ID. ```bash # Start the Event Store feeder (reads events, forwards to channel) bin/console ecotone:run product_stream_feeder -vvv ``` -------------------------------- ### Testing Command Bus Operations Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-metadata-method-invocation.md Example of sending commands and queries using the command bus and query bus. Includes registering a product, changing its price, and retrieving its cost. ```php public function run() : void { $this->commandBus->sendWithRouting( "product.register", \json_encode(["productId" => 1, "cost" => 100]), "application/json", [ "userId" => 1 ] ); $this->commandBus->sendWithRouting( "product.changePrice", \json_encode(["productId" => 1, "cost" => 110]), "application/json", [ "userId" => 1 ] ); echo $this->queryBus->sendWithRouting("product.getCost", \json_encode(["productId" => 1]), "application/json"); } ``` -------------------------------- ### Install Amazon SQS Support via Composer Source: https://github.com/ecotoneframework/documentation/blob/main/modules/amazon-sqs-support.md Install the Ecotone SQS support package using Composer. ```php composer require ecotone/sqs ``` -------------------------------- ### Verify Ecotone Laravel Installation Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Run this Artisan command to confirm that Ecotone is correctly installed and configured within your Laravel application. ```bash php artisan ecotone:list ``` -------------------------------- ### Install Ecotone Laravel Package Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Use Composer to install the Ecotone Laravel integration package. This enables auto-configuration for Laravel projects. ```bash composer require ecotone/laravel ``` -------------------------------- ### Testing Complete Workflow with Ecotone Lite Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/orchestrators.md Demonstrates how to set up Ecotone Lite for testing an entire orchestrator workflow. This includes bootstrapping the testing environment with necessary services and configurations. ```php use Ecotone\Lite\EcotoneLite; use PHPUnit\Framework\TestCase; class ImageProcessingOrchestratorTest extends TestCase { private EcotoneLite $ecotoneLite; protected function setUp(): void { $this->ecotoneLite = EcotoneLite::bootstrapFlowTesting( [ImageProcessingOrchestrator::class], [ 'storageService' => new InMemoryStorageService(), 'imageProcessor' => new TestImageProcessor() ], ServiceConfiguration::createWithDefaults() ->withLicenceKey(VALID_LICENCE) ); } public function test_complete_image_processing_workflow(): void { // Arrange $imageData = new ImageData('test-image.jpg', 1920, 1080); // Act $result = $this->ecotoneLite->sendDirectToChannel('process.image', $imageData); // Assert $this->assertInstanceOf(ImageData::class, $result); $this->assertEquals(800, $result->width); $this->assertEquals(600, $result->height); $this->assertTrue($result->hasWatermark()); $this->assertTrue($result->isOptimized()); } } ``` -------------------------------- ### Verify Ecotone Symfony Installation Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Run this console command to confirm that Ecotone is correctly installed and configured within your Symfony application. ```bash php bin/console ecotone:list ``` -------------------------------- ### Dynamically Build Customer Onboarding Workflow Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/orchestrators.md Construct a dynamic workflow for customer onboarding based on customer attributes and business rules. This orchestrator determines the sequence of steps at runtime. ```php class DynamicCustomerOnboardingOrchestrator { public function __construct( private CustomerService $customerService, private ComplianceService $complianceService ) {} #[Orchestrator(inputChannelName: "onboard.customer")] public function onboardCustomer(Customer $customer): array { $steps = ["validate.customer"]; // Add steps based on customer type if ($customer->isEnterprise()) { $steps[] = "enterprise.verification"; $steps[] = "compliance.check"; } // Add steps based on location if ($customer->isInternational()) { $steps[] = "international.verification"; } // Add steps based on business rules if ($this->complianceService->requiresKYC($customer)) { $steps[] = "kyc.verification"; } // Common final steps $steps[] = "create.account"; $steps[] = "send.welcome.email"; return $steps; } } ``` -------------------------------- ### Install Ecotone Symfony Bundle Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Use Composer to install the Ecotone Symfony integration package. This enables auto-configuration for Symfony projects. ```bash composer require ecotone/symfony-bundle ``` -------------------------------- ### Test Command for Placing an Order Source: https://github.com/ecotoneframework/documentation/blob/main/tutorial-php-ddd-cqrs-event-sourcing/php-asynchronous-processing.md Execute a series of commands to register products and then place an order. This setup is used to test asynchronous order placement. ```php public function run() : void { $this->commandBus->sendWithRouting( "product.register", ["productId" => 1, "cost" => 100] ); $this->commandBus->sendWithRouting( "product.register", ["productId" => 2, "cost" => 300] ); $orderId = 990; $this->commandBus->sendWithRouting( "order.place", ["orderId" => $orderId, "productIds" => [1,2]] ); echo $this->queryBus->sendWithRouting("order.getTotalPrice", ["orderId" => $orderId]); } ``` -------------------------------- ### Install Ecotone Skills Plugin Source: https://github.com/ecotoneframework/documentation/blob/main/other/ai-integration.md Install the Ecotone Skills plugin for Claude Code. This provides slash commands and subagents for Ecotone development. ```bash /plugin install ecotone-skills@ecotone ``` -------------------------------- ### Initialize a Specific Projection via Lite CLI Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/lifecycle-management.md In a Lite application setup, use `runConsoleCommand` with `ecotone:projection:init` and the projection name to manually initialize its schema. ```php $messagingSystem->runConsoleCommand('ecotone:projection:init', ['name' => 'ticket_list']); ``` -------------------------------- ### Install Ecotone Lite Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Install the core Ecotone package for use in non-Symfony/Laravel projects or standalone applications. Requires PSR-4 or PSR-0 autoloading. ```bash composer require ecotone/ecotone ``` -------------------------------- ### Start Event Store Feeder in Laravel Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/scaling-and-advanced.md Run the Event Store adapter feeder using the Laravel artisan command `ecotone:run` with the adapter's endpoint ID. ```bash artisan ecotone:run product_stream_feeder -vvv ``` -------------------------------- ### Nested Orchestrators Example Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/orchestrators.md Shows how orchestrators can call other orchestrators as steps within a workflow. This example defines a master orchestrator that calls two sub-workflows. ```php class MasterOrchestrator { #[Orchestrator(inputChannelName: "master.workflow")] public function masterWorkflow(): array { return [ "prepare.data", "sub.workflow.a", // This calls another orchestrator "sub.workflow.b", // This calls another orchestrator "combine.results" ]; } #[InternalHandler(inputChannelName: "prepare.data")] public function prepareData(RawData $data): ProcessedData { return new ProcessedData($data); } #[Orchestrator(inputChannelName: "sub.workflow.a")] public function subWorkflowA(): array { return ["step.a1", "step.a2"]; } #[Orchestrator(inputChannelName: "sub.workflow.b")] public function subWorkflowB(): array { return ["step.b1", "step.b2"]; } #[InternalHandler(inputChannelName: "combine.results")] public function combineResults(ProcessedData $data): FinalResult { return new FinalResult($data); } } ``` -------------------------------- ### Bootstrap Ecotone Lite with Real Event Store Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/testing-support/testing-event-sourcing-applications.md Initialize Ecotone Lite for flow testing using a real event store. This requires providing database connection details and enabling the production event store. ```php $ecotoneLite = EcotoneLite::bootstrapFlowTestingWithEventStore( [Ticket::class], // Provide connection to the database [DbalConnectionFactory::class => new DbalConnectionFactory('pgsql://ecotone:secret@localhost:5432/ecotone')], // Tell Ecotone to enable production Event Store runForProductionEventStore: true ); ``` -------------------------------- ### Doctrine ORM Example Implementation Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/command-handling/repository/configure-repository.md An example of a custom `StandardRepository` implementation using Doctrine ORM to manage `Ticket` aggregates. It demonstrates how to use the `EntityManagerInterface` for persistence. ```php final class EcotoneTicketRepository implements StandardRepository { public function __construct(private readonly EntityManagerInterface $entityManager) { } public function canHandle(string $aggregateClassName): bool { return $aggregateClassName === Ticket::class; } public function findBy(string $aggregateClassName, array $identifiers): ?object { return $this->entityManager->getRepository(Ticket::class) // Array of identifiers for given Aggregate ->find($identifiers['ticketId']); } public function save(array $identifiers, object $aggregate, array $metadata, ?int $versionBeforeHandling): void { $this->entityManager->persist($aggregate); } } ``` -------------------------------- ### Test Workflows with Ecotone Lite Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/connecting-handlers-with-channels.md Use Ecotone Lite to simplify testing of handler chains. This example demonstrates setting up handlers, sending a command, and asserting the workflow's execution. ```php use Ecotone\Lite\EcotoneLite; use PHPUnit\Framework\TestCase; class WorkflowTest extends TestCase { public function test_order_verification_workflow(): void { // Arrange - Set up your handlers $orderProcessor = new ProcessOrder(); $ecotoneLite = EcotoneLite::bootstrapFlowTesting( [ProcessOrder::class], // Classes to register [$orderProcessor], // Service instances ); // Act - Send a command to start the workflow $command = new PlaceOrder('order-123', 'customer-456'); $result = $ecotoneLite->sendCommand($command); // Assert - Verify the workflow executed correctly $this->assertNull($result); // Void return from final handler // Verify side effects (database changes, sent emails, etc.) $this->assertTrue($orderProcessor->wasOrderPlaced('order-123')); } } ``` -------------------------------- ### Get Help for Dead Letter Console Commands (Laravel) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/recovering-tracing-and-monitoring/resiliency/error-channel-and-dead-letter/dbal-dead-letter.md Use this Artisan console command to get help and understand the available dead letter commands. ```bash artisan ecotone:deadletter:help ``` -------------------------------- ### Get Help for Dead Letter Console Commands (Symfony) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/recovering-tracing-and-monitoring/resiliency/error-channel-and-dead-letter/dbal-dead-letter.md Use this Symfony console command to get help and understand the available dead letter commands. ```php bin/console ecotone:deadletter:help ``` -------------------------------- ### Bootstrap Ecotone Lite without Dependency Container Source: https://github.com/ecotoneframework/documentation/blob/main/install-php-service-bus.md Initialize Ecotone Lite by providing a list of classes to resolve and an array of pre-instantiated services. Useful for testing or small scripts. ```php $ecotoneLite = EcotoneLite::bootstrap( classesToResolve: [User::class, UserRepository::class, UserService::class], containerOrAvailableServices: [new UserRepository(), new UserService()] ); ``` -------------------------------- ### View Database Migration Status (Symfony) Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/migrations-storage/README.md Use the `ecotone:migration:database:setup` console command to view the status of database features. Options include filtering by used features or specific features. ```bash # Show all features and their status bin/console ecotone:migration:database:setup # Show only used features (default) bin/console ecotone:migration:database:setup --onlyUsed=true # Show all available features bin/console ecotone:migration:database:setup --onlyUsed=false # Show status for specific features bin/console ecotone:migration:database:setup --feature=dead_letter --feature=deduplication ``` -------------------------------- ### Install Ecotone PDO Event Sourcing Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/installation.md Install the Event Sourcing module using Composer. This package provides the core components for implementing Event Sourcing patterns. ```php composer require ecotone/pdo-event-sourcing ``` -------------------------------- ### Initialize All Projections via CLI Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/setting-up-projections/lifecycle-management.md Run `ecotone:projection:init --all` to manually initialize the schemas for all projections in your application. This command ensures all necessary storage structures are in place. ```bash bin/console ecotone:projection:init --all ``` -------------------------------- ### Bootstrap Publishing Service for Testing Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/microservices-php/distributed-bus/distributed-bus-with-service-map/testing.md Configure and bootstrap the publishing service for distributed bus testing. This sets up the service name, distributed service map, and shared in-memory message channels. ```php # test file $distributedTicketChannel = SimpleMessageChannelBuilder::createQueueChannel('distributed_ticket'); $userService = EcotoneLite::bootstrapFlowTesting( configuration: ServiceConfiguration::createWithDefaults() ->withServiceName('user_service') ->withExtensionObjects([ // distributed service map on the publisher side DistributedServiceMap::initialize() ->withServiceMapping(serviceName: 'ticket_service', channelName: 'distributed_ticket'), // shared in memory channel enableAsynchronousProcessing: [distributedTicketChannel] ]) ) ``` -------------------------------- ### Ecotone Lite Saga Test Setup Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/business-workflows/sagas.md Initialize Ecotone Lite for testing saga flows. This setup allows you to bootstrap the application with your saga classes and prepare for event publishing and query sending. ```php use Ecotone\Lite\EcotoneLite; use PHPUnit\Framework\TestCase; class OrderProcessSagaTest extends TestCase { private EcotoneLite $ecotoneLite; protected function setUp(): void { $this->ecotoneLite = EcotoneLite::bootstrapFlowTesting( [OrderProcess::class], [], ); } public function test_saga_initialization(): void { // Act - Trigger saga creation $event = new OrderWasPlaced('order-123'); $this->ecotoneLite->publishEvent($event); // Assert - Verify saga was created and can be queried $status = $this->ecotoneLite->sendQueryWithRouting( 'order.getStatus', metadata: ['aggregate.id' => 'order-123'] ); $this->assertEquals('order-123', $status['orderId']); $this->assertEquals('PLACED', $status['status']); $this->assertFalse($status['isPaid']); $this->assertFalse($status['isShipped']); } } ``` -------------------------------- ### Install Ecotone JMS Converter for Serialization Source: https://github.com/ecotoneframework/documentation/blob/main/modelling/event-sourcing/installation.md Install the JMS converter package to enable Ecotone's built-in event serialization and deserialization capabilities. This simplifies event handling by abstracting the conversion process. ```php composer require ecotone/jms-converter ```