From 39ceb0352e366c9684e2a556cc4a4e49846b875c Mon Sep 17 00:00:00 2001 From: Jean Date: Fri, 9 Jun 2023 20:38:06 +0200 Subject: [PATCH] Fullapp benchmark (#144) * ci: fix phpbench baseline on main * add example app to run benchmarks on for Lite/Symfony/Laravel * ci: remove cached files between benchmarks * refactor benchmarks * add PlaceOrderWithoutEcotoneBenchmark * clean ExampleApp * ci: remove opcache benchmark * skip without ecotone benchmark --------- Co-authored-by: jlabedo --- .github/workflows/benchmark-pr.yml | 34 ++- Monorepo/Benchmark/EcotoneBenchmark.php | 72 ------- Monorepo/Benchmark/FullAppBenchmarkCase.php | 72 +++++++ Monorepo/Benchmark/KernelBootBenchmark.php | 17 ++ Monorepo/Benchmark/LaravelBenchmark.php | 50 ----- Monorepo/Benchmark/LiteContainerAccessor.php | 23 ++ Monorepo/Benchmark/MessagingBootBenchmark.php | 18 ++ Monorepo/Benchmark/PlaceOrderBenchmark.php | 33 +++ .../PlaceOrderWithoutEcotoneBenchmark.php | 34 +++ Monorepo/Benchmark/SymfonyBenchmark.php | 40 ---- .../Domain/Article/Command/ChangeContent.php | 10 + .../Domain/Article/Command/ChangeTitle.php | 10 + .../Article/Command/CreatePublication.php | 10 + .../Common/Domain/Article/Publication.php | 41 ++++ Monorepo/ExampleApp/Common/Domain/Clock.php | 10 + Monorepo/ExampleApp/Common/Domain/Money.php | 8 + .../Notification/NotificationSender.php | 10 + .../Notification/NotificationSubscriber.php | 30 +++ .../OrderConfirmationNotification.php | 19 ++ .../Domain/Order/Command/PlaceOrder.php | 18 ++ .../Domain/Order/Event/OrderWasPlaced.php | 14 ++ .../ExampleApp/Common/Domain/Order/Order.php | 62 ++++++ .../Common/Domain/Order/OrderRepository.php | 14 ++ .../Common/Domain/Order/ShippingAddress.php | 15 ++ .../Common/Domain/Product/Product.php | 27 +++ .../Common/Domain/Product/ProductDetails.php | 15 ++ .../Domain/Product/ProductRepository.php | 12 ++ .../Domain/Shipping/ShippingService.php | 14 ++ .../Domain/Shipping/ShippingSubscriber.php | 30 +++ .../ExampleApp/Common/Domain/User/User.php | 28 +++ .../Common/Domain/User/UserRepository.php | 12 ++ .../Authentication/AuthenticationService.php | 25 +++ .../Common/Infrastructure/Configuration.php | 62 ++++++ .../Common/Infrastructure/Converter/README.md | 4 + .../Converter/UuidConverter.php | 24 +++ .../InMemory/InMemoryOrderRepository.php | 49 +++++ .../InMemory/InMemoryProductRepository.php | 39 ++++ .../InMemory/InMemoryUserRepository.php | 39 ++++ .../Messaging/MessageChannelConfiguration.php | 30 +++ .../Common/Infrastructure/Output.php | 21 ++ .../Infrastructure/StubNotificationSender.php | 19 ++ .../Infrastructure/StubShippingService.php | 23 ++ .../Common/Infrastructure/SystemClock.php | 15 ++ .../ExampleApp/Common/UI/OrderController.php | 33 +++ .../UI/OrderControllerWithoutMessaging.php | 37 ++++ .../app/Providers/AppServiceProvider.php | 70 ++++++ Monorepo/ExampleApp/Laravel/artisan | 53 +++++ Monorepo/ExampleApp/Laravel/bootstrap/app.php | 55 +++++ .../Laravel/bootstrap/cache/.gitkeep | 0 Monorepo/ExampleApp/Laravel/config/app.php | 199 ++++++++++++++++++ Monorepo/ExampleApp/Laravel/config/cache.php | 111 ++++++++++ .../ExampleApp/Laravel/config/ecotone.php | 10 + .../ExampleApp/Laravel/config/filesystems.php | 82 ++++++++ .../ExampleApp/Laravel/config/logging.php | 131 ++++++++++++ .../ExampleApp/Laravel/config/services.php | 34 +++ .../ExampleApp/Laravel/public/favicon.ico | 0 Monorepo/ExampleApp/Laravel/public/index.php | 55 +++++ Monorepo/ExampleApp/Laravel/public/robots.txt | 2 + Monorepo/ExampleApp/Laravel/run.php | 31 +++ .../ExampleApp/Laravel/storage/app/.gitignore | 3 + .../Laravel/storage/app/public/.gitignore | 2 + .../Laravel/storage/framework/.gitignore | 9 + .../storage/framework/sessions/.gitignore | 2 + .../storage/framework/testing/.gitignore | 2 + .../storage/framework/views/.gitignore | 2 + .../Laravel/storage/logs/.gitignore | 2 + Monorepo/ExampleApp/Lite/app.php | 47 +++++ Monorepo/ExampleApp/Lite/run.php | 26 +++ Monorepo/ExampleApp/Symfony/Kernel.php | 15 ++ Monorepo/ExampleApp/Symfony/bin/console | 19 ++ Monorepo/ExampleApp/Symfony/bin/run.php | 31 +++ .../ExampleApp/Symfony/config/bundles.php | 8 + .../ExampleApp/Symfony/config/services.php | 38 ++++ 73 files changed, 2080 insertions(+), 181 deletions(-) delete mode 100644 Monorepo/Benchmark/EcotoneBenchmark.php create mode 100644 Monorepo/Benchmark/FullAppBenchmarkCase.php create mode 100644 Monorepo/Benchmark/KernelBootBenchmark.php delete mode 100644 Monorepo/Benchmark/LaravelBenchmark.php create mode 100644 Monorepo/Benchmark/LiteContainerAccessor.php create mode 100644 Monorepo/Benchmark/MessagingBootBenchmark.php create mode 100644 Monorepo/Benchmark/PlaceOrderBenchmark.php create mode 100644 Monorepo/Benchmark/PlaceOrderWithoutEcotoneBenchmark.php delete mode 100644 Monorepo/Benchmark/SymfonyBenchmark.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Article/Command/ChangeContent.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Article/Command/ChangeTitle.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Article/Command/CreatePublication.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Article/Publication.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Clock.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Money.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Notification/NotificationSender.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Notification/NotificationSubscriber.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Notification/OrderConfirmationNotification.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Order/Command/PlaceOrder.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Order/Event/OrderWasPlaced.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Order/Order.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Order/OrderRepository.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Order/ShippingAddress.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Product/Product.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Product/ProductDetails.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Product/ProductRepository.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Shipping/ShippingService.php create mode 100644 Monorepo/ExampleApp/Common/Domain/Shipping/ShippingSubscriber.php create mode 100644 Monorepo/ExampleApp/Common/Domain/User/User.php create mode 100644 Monorepo/ExampleApp/Common/Domain/User/UserRepository.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Authentication/AuthenticationService.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Configuration.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Converter/README.md create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Converter/UuidConverter.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryOrderRepository.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryProductRepository.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryUserRepository.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Messaging/MessageChannelConfiguration.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/Output.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/StubNotificationSender.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/StubShippingService.php create mode 100644 Monorepo/ExampleApp/Common/Infrastructure/SystemClock.php create mode 100644 Monorepo/ExampleApp/Common/UI/OrderController.php create mode 100644 Monorepo/ExampleApp/Common/UI/OrderControllerWithoutMessaging.php create mode 100644 Monorepo/ExampleApp/Laravel/app/Providers/AppServiceProvider.php create mode 100755 Monorepo/ExampleApp/Laravel/artisan create mode 100644 Monorepo/ExampleApp/Laravel/bootstrap/app.php create mode 100644 Monorepo/ExampleApp/Laravel/bootstrap/cache/.gitkeep create mode 100644 Monorepo/ExampleApp/Laravel/config/app.php create mode 100644 Monorepo/ExampleApp/Laravel/config/cache.php create mode 100644 Monorepo/ExampleApp/Laravel/config/ecotone.php create mode 100644 Monorepo/ExampleApp/Laravel/config/filesystems.php create mode 100644 Monorepo/ExampleApp/Laravel/config/logging.php create mode 100644 Monorepo/ExampleApp/Laravel/config/services.php create mode 100644 Monorepo/ExampleApp/Laravel/public/favicon.ico create mode 100644 Monorepo/ExampleApp/Laravel/public/index.php create mode 100644 Monorepo/ExampleApp/Laravel/public/robots.txt create mode 100644 Monorepo/ExampleApp/Laravel/run.php create mode 100644 Monorepo/ExampleApp/Laravel/storage/app/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/app/public/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/framework/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/framework/sessions/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/framework/testing/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/framework/views/.gitignore create mode 100644 Monorepo/ExampleApp/Laravel/storage/logs/.gitignore create mode 100644 Monorepo/ExampleApp/Lite/app.php create mode 100644 Monorepo/ExampleApp/Lite/run.php create mode 100644 Monorepo/ExampleApp/Symfony/Kernel.php create mode 100755 Monorepo/ExampleApp/Symfony/bin/console create mode 100644 Monorepo/ExampleApp/Symfony/bin/run.php create mode 100644 Monorepo/ExampleApp/Symfony/config/bundles.php create mode 100644 Monorepo/ExampleApp/Symfony/config/services.php diff --git a/.github/workflows/benchmark-pr.yml b/.github/workflows/benchmark-pr.yml index aec9a8532..4a9d52702 100644 --- a/.github/workflows/benchmark-pr.yml +++ b/.github/workflows/benchmark-pr.yml @@ -84,32 +84,28 @@ jobs: id: baseline continue-on-error: true run: | - vendor/bin/phpbench --profile=opcache_enabled --retry-threshold=5 --tag=main.opcache_enabled - vendor/bin/phpbench --profile=opcache_disabled --retry-threshold=5 --tag=main.opcache_disabled + vendor/bin/phpbench run --retry-threshold=5 --tag=main --report=github-report - uses: actions/checkout@v3 with: clean: false + - name: Remove cached files + working-directory: + run: | + rm -rf Monorepo/ExampleApp/Lite/var/cache + rm -rf Monorepo/ExampleApp/Symfony/var/cache + rm -rf Monorepo/ExampleApp/Laravel/framework/cache + - name: Install dependencies run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction - - name: Benchmark PR with opcache enabled - id: opcache_enabled - env: - PHPBENCH_REF_OPTION: "${{ steps.baseline.outcome == 'success' && '--ref=main.opcache_enabled' || '' }}" - run: | - vendor/bin/phpbench run --profile=opcache_enabled --retry-threshold=5 --report=github-report $PHPBENCH_REF_OPTION | bin/phpbench-to-md.sh > opcache_enabled.md - cat opcache_enabled.md - echo '## Opcache enabled' >> "$GITHUB_STEP_SUMMARY" - cat opcache_enabled.md >> "$GITHUB_STEP_SUMMARY" - - - name: Benchmark PR with opcache disabled - id: opcache_disabled + - name: Benchmark PR env: - PHPBENCH_REF_OPTION: "${{ steps.baseline.outcome == 'success' && '--ref=main.opcache_disabled' || '' }}" + PHPBENCH_REF_OPTION: "${{ steps.baseline.outcome == 'success' && '--ref=main' || '' }}" run: | - vendor/bin/phpbench run --profile=opcache_disabled --retry-threshold=5 --report=github-report $PHPBENCH_REF_OPTION | bin/phpbench-to-md.sh > opcache_disabled.md - cat opcache_disabled.md - echo '## Opcache disabled' >> "$GITHUB_STEP_SUMMARY" - cat opcache_disabled.md >> "$GITHUB_STEP_SUMMARY" + echo "Baseline: $PHPBENCH_REF_OPTION" + vendor/bin/phpbench run --retry-threshold=5 --report=github-report $PHPBENCH_REF_OPTION | bin/phpbench-to-md.sh > benchmark.md + cat benchmark.md + echo '## Benchmark' >> "$GITHUB_STEP_SUMMARY" + cat benchmark.md >> "$GITHUB_STEP_SUMMARY" diff --git a/Monorepo/Benchmark/EcotoneBenchmark.php b/Monorepo/Benchmark/EcotoneBenchmark.php deleted file mode 100644 index 25594f3ca..000000000 --- a/Monorepo/Benchmark/EcotoneBenchmark.php +++ /dev/null @@ -1,72 +0,0 @@ -execute( - ServiceConfiguration::createWithDefaults() - ->withFailFast(false) - ->withSkippedModulePackageNames(ModulePackageList::allPackages()), - false - ); - } - - public function bench_running_ecotone_lite_with_fail_fast() - { - $this->execute( - ServiceConfiguration::createWithDefaults() - ->withFailFast(true) - ->withSkippedModulePackageNames(ModulePackageList::allPackages()), - false - ); - } - - public function bench_running_ecotone_lite_with_cache() - { - $this->execute( - ServiceConfiguration::createWithDefaults() - ->withFailFast(false) - ->withCacheDirectoryPath(sys_get_temp_dir()) - ->withSkippedModulePackageNames(ModulePackageList::allPackages()), - true - ); - } - - private function execute(ServiceConfiguration $serviceConfiguration, bool $useCachedVersion): void - { - $ecotoneApplication = EcotoneLite::bootstrap( - [Merchant::class, User::class, MerchantSubscriber::class, InMemoryStandardRepository::class], - [ - new MerchantSubscriber(), InMemoryStandardRepository::createEmpty(), - ], - $serviceConfiguration, - useCachedVersion: $useCachedVersion, - allowGatewaysToBeRegisteredInContainer: true - ); - - $merchantId = '123'; - $ecotoneApplication->getCommandBus()->send(new CreateMerchant($merchantId)); - - Assertion::true( - $ecotoneApplication->getQueryBus()->sendWithRouting('user.get', metadata: ['aggregate.id' => $merchantId]) - ); - } -} diff --git a/Monorepo/Benchmark/FullAppBenchmarkCase.php b/Monorepo/Benchmark/FullAppBenchmarkCase.php new file mode 100644 index 000000000..f67071621 --- /dev/null +++ b/Monorepo/Benchmark/FullAppBenchmarkCase.php @@ -0,0 +1,72 @@ +boot(); + $container = $kernel->getContainer(); + + $this->execute($container); + + $kernel->shutdown(); + } + + public function bench_symfony_dev() + { + \putenv('APP_ENV=dev'); + $kernel = new Kernel('dev', true); + $kernel->boot(); + $container = $kernel->getContainer(); + + $this->execute($container); + + $kernel->shutdown(); + } + + public function bench_laravel_prod(): void + { + \putenv('APP_ENV=production'); + $app = $this->createLaravelApplication(); + $this->execute($app); + } + + public function bench_laravel_dev(): void + { + \putenv('APP_ENV=development'); + $app = $this->createLaravelApplication(); + $this->execute($app); + } + + public function bench_lite_prod() + { + $bootstrap = require __DIR__ . "/../ExampleApp/Lite/app.php"; + $messagingSystem = $bootstrap(true); + $this->execute(new LiteContainerAccessor($messagingSystem)); + } + + public function bench_lite_dev() + { + $bootstrap = require __DIR__ . "/../ExampleApp/Lite/app.php"; + $messagingSystem = $bootstrap(false); + $this->execute(new LiteContainerAccessor($messagingSystem)); + } + + private function createLaravelApplication() + { + $app = require __DIR__ . '/../ExampleApp/Laravel/bootstrap/app.php'; + + $app->make(\Illuminate\Foundation\Http\Kernel::class)->bootstrap(); + + return $app; + } + + protected abstract function execute(ContainerInterface $container): void; +} \ No newline at end of file diff --git a/Monorepo/Benchmark/KernelBootBenchmark.php b/Monorepo/Benchmark/KernelBootBenchmark.php new file mode 100644 index 000000000..b5da3ffb6 --- /dev/null +++ b/Monorepo/Benchmark/KernelBootBenchmark.php @@ -0,0 +1,17 @@ +createApplication(); - } - - public function bench_kernel_boot_on_dev() - { - putenv('APP_ENV=development'); - $this->createApplication(); - } - - public function bench_messaging_boot_on_prod() - { - putenv('APP_ENV=production'); - $app = $this->createApplication(); - $app->make(ConfiguredMessagingSystem::class); - } - - public function bench_messaging_boot_on_dev() - { - putenv('APP_ENV=development'); - $app = $this->createApplication(); - $app->make(ConfiguredMessagingSystem::class); - } - - public function createApplication(): Application - { - $app = require \dirname(__DIR__, 2) . '/packages/Laravel/tests/Application/bootstrap/app.php'; - - $app->make(Kernel::class)->bootstrap(); - - return $app; - } -} diff --git a/Monorepo/Benchmark/LiteContainerAccessor.php b/Monorepo/Benchmark/LiteContainerAccessor.php new file mode 100644 index 000000000..a2d9b7f6d --- /dev/null +++ b/Monorepo/Benchmark/LiteContainerAccessor.php @@ -0,0 +1,23 @@ +messagingSystem->getServiceFromContainer($id); + } + + public function has(string $id): bool + { + throw new \Exception("Not implemented"); + } +} \ No newline at end of file diff --git a/Monorepo/Benchmark/MessagingBootBenchmark.php b/Monorepo/Benchmark/MessagingBootBenchmark.php new file mode 100644 index 000000000..3143fe574 --- /dev/null +++ b/Monorepo/Benchmark/MessagingBootBenchmark.php @@ -0,0 +1,18 @@ +get(ConfiguredMessagingSystem::class); + } +} \ No newline at end of file diff --git a/Monorepo/Benchmark/PlaceOrderBenchmark.php b/Monorepo/Benchmark/PlaceOrderBenchmark.php new file mode 100644 index 000000000..a4461382d --- /dev/null +++ b/Monorepo/Benchmark/PlaceOrderBenchmark.php @@ -0,0 +1,33 @@ +get(OrderController::class); + $configuration = $container->get(Configuration::class); + + $orderController->placeOrder(new Request(content: json_encode([ + 'orderId' => Uuid::uuid4()->toString(), + 'address' => [ + 'street' => 'Washington', + 'houseNumber' => '15', + 'postCode' => '81-221', + 'country' => 'Netherlands' + ], + 'productId' => $configuration->productId(), + ]))); + } +} \ No newline at end of file diff --git a/Monorepo/Benchmark/PlaceOrderWithoutEcotoneBenchmark.php b/Monorepo/Benchmark/PlaceOrderWithoutEcotoneBenchmark.php new file mode 100644 index 000000000..2eb3d792e --- /dev/null +++ b/Monorepo/Benchmark/PlaceOrderWithoutEcotoneBenchmark.php @@ -0,0 +1,34 @@ +get(OrderControllerWithoutMessaging::class); + $configuration = $container->get(Configuration::class); + + $orderController->placeOrder(new Request(content: json_encode([ + 'orderId' => Uuid::uuid4()->toString(), + 'address' => [ + 'street' => 'Washington', + 'houseNumber' => '15', + 'postCode' => '81-221', + 'country' => 'Netherlands' + ], + 'productId' => $configuration->productId(), + ]))); + } +} \ No newline at end of file diff --git a/Monorepo/Benchmark/SymfonyBenchmark.php b/Monorepo/Benchmark/SymfonyBenchmark.php deleted file mode 100644 index 468215664..000000000 --- a/Monorepo/Benchmark/SymfonyBenchmark.php +++ /dev/null @@ -1,40 +0,0 @@ -boot(); - } - - public function bench_kernel_boot_on_dev() - { - $kernel = new Kernel('dev', false); - $kernel->boot(); - } - - public function bench_messaging_boot_on_prod() - { - $kernel = new Kernel('prod', false); - $kernel->boot(); - $kernel->getContainer()->get(ConfiguredMessagingSystem::class); - } - - public function bench_messaging_boot_on_dev() - { - $kernel = new Kernel('dev', false); - $kernel->boot(); - $kernel->getContainer()->get(ConfiguredMessagingSystem::class); - } -} diff --git a/Monorepo/ExampleApp/Common/Domain/Article/Command/ChangeContent.php b/Monorepo/ExampleApp/Common/Domain/Article/Command/ChangeContent.php new file mode 100644 index 000000000..3a6bcce28 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/Article/Command/ChangeContent.php @@ -0,0 +1,10 @@ +id, $command->title, $command->content); + } + + #[CommandHandler] + public function changeTitle(ChangeTitle $command): void + { + $this->title = $command->title; + } + + #[CommandHandler] + public function changeContent(ChangeContent $command): void + { + $this->content = $command->content; + } + + #[CommandHandler('article.publish')] + public function publish(): void + { + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/Clock.php b/Monorepo/ExampleApp/Common/Domain/Clock.php new file mode 100644 index 000000000..e5f1a8cbc --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/Clock.php @@ -0,0 +1,10 @@ +orderRepository->getBy($event->orderId); + $user = $this->userRepository->getBy($order->getUserId()); + + $this->notificationSender->send(new OrderConfirmationNotification( + $user->getFullName(), $order->getOrderId(), $order->getProductDetails(), $order->getTotalPrice()) + ); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/Notification/OrderConfirmationNotification.php b/Monorepo/ExampleApp/Common/Domain/Notification/OrderConfirmationNotification.php new file mode 100644 index 000000000..3d6497abd --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/Notification/OrderConfirmationNotification.php @@ -0,0 +1,19 @@ +recordThat(new OrderWasPlaced($this->orderId)); + } + + #[CommandHandler] + public static function create(PlaceOrder $command, ProductRepository $productRepository, Clock $clock): self + { + $productDetails = $productRepository->getBy($command->productId)->getProductDetails(); + + return new self($command->orderId, $command->userId, $command->shippingAddress, $productDetails, $clock->getCurrentTime()); + } + + public function getOrderId(): UuidInterface + { + return $this->orderId; + } + + public function getUserId(): UuidInterface + { + return $this->userId; + } + + public function getShippingAddress(): ShippingAddress + { + return $this->shippingAddress; + } + + public function getProductDetails(): ProductDetails + { + return $this->productDetails; + } + + public function getTotalPrice(): Money + { + return $this->productDetails->productPrice; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/Order/OrderRepository.php b/Monorepo/ExampleApp/Common/Domain/Order/OrderRepository.php new file mode 100644 index 000000000..2bb057ca7 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/Order/OrderRepository.php @@ -0,0 +1,14 @@ +productId; + } + + public function getProductDetails(): ProductDetails + { + return $this->productDetails; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/Product/ProductDetails.php b/Monorepo/ExampleApp/Common/Domain/Product/ProductDetails.php new file mode 100644 index 000000000..76026fc54 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/Product/ProductDetails.php @@ -0,0 +1,15 @@ +orderRepository->getBy($event->orderId); + + $this->shippingService->shipOrderFor( + $order->getUserId(), $order->getOrderId(), + $order->getProductDetails(), $order->getShippingAddress() + ); + } + +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/User/User.php b/Monorepo/ExampleApp/Common/Domain/User/User.php new file mode 100644 index 000000000..2c605a662 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/User/User.php @@ -0,0 +1,28 @@ +userId; + } + + public function getFullName(): string + { + return $this->fullName; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Domain/User/UserRepository.php b/Monorepo/ExampleApp/Common/Domain/User/UserRepository.php new file mode 100644 index 000000000..d75ed21b2 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Domain/User/UserRepository.php @@ -0,0 +1,12 @@ +userId; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/Configuration.php b/Monorepo/ExampleApp/Common/Infrastructure/Configuration.php new file mode 100644 index 000000000..458d25d87 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/Configuration.php @@ -0,0 +1,62 @@ +userId = Uuid::uuid4(); + $this->productId = Uuid::uuid4(); + $this->registeredUser = [new User($this->userId, 'John Travolta')]; + } + + public function users(): array + { + return $this->registeredUser; + } + + public function userRepository(): UserRepository + { + return new InMemoryUserRepository($this->users()); + } + + public function productRepository(): ProductRepository + { + return new InMemoryProductRepository([new Product($this->productId, new ProductDetails("Table", new Money()))]); + } + + public function authentication(): AuthenticationService + { + return new AuthenticationService($this->userId); + } + + public function userId(): UuidInterface + { + return $this->userId; + } + + public function productId(): UuidInterface + { + return $this->productId; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/Converter/README.md b/Monorepo/ExampleApp/Common/Infrastructure/Converter/README.md new file mode 100644 index 000000000..d3fb00c61 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/Converter/README.md @@ -0,0 +1,4 @@ +# Converter + +This converters are used by ecotone/jms-converter to store and retrieve Messages from database. +You may use of your [own Conversion](https://docs.ecotone.tech/messaging/conversion/conversion) if you want to. \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/Converter/UuidConverter.php b/Monorepo/ExampleApp/Common/Infrastructure/Converter/UuidConverter.php new file mode 100644 index 000000000..a7b3a0ab0 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/Converter/UuidConverter.php @@ -0,0 +1,24 @@ +toString(); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryOrderRepository.php b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryOrderRepository.php new file mode 100644 index 000000000..16a3bd336 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryOrderRepository.php @@ -0,0 +1,49 @@ +orders[$identifier])) { + return $this->orders[$identifier]; + } + + return null; + } + + public function save(array $identifiers, object $aggregate, array $metadata, ?int $versionBeforeHandling): void + { + $identifier = array_pop($identifiers); + + $this->orders[$identifier] = $aggregate; + } + + public function getBy(UuidInterface $orderId): Order + { + if (!isset($this->orders[$orderId->toString()])) { + throw new \RuntimeException(sprintf("User with id %s not found", $orderId->toString())); + } + + return $this->orders[$orderId->toString()]; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryProductRepository.php b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryProductRepository.php new file mode 100644 index 000000000..6525eae4a --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryProductRepository.php @@ -0,0 +1,39 @@ +save( $product); + } + } + + public function getBy(UuidInterface $productId): Product + { + if (!isset($this->products[$productId->toString()])) { + throw new \RuntimeException(sprintf("Product with id %s not found", $productId->toString())); + } + + return $this->products[$productId->toString()]; + } + + public function save(Product $product): void + { + $this->products[$product->getProductId()->toString()] = $product; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryUserRepository.php b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryUserRepository.php new file mode 100644 index 000000000..646190c70 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/InMemory/InMemoryUserRepository.php @@ -0,0 +1,39 @@ +save($user); + } + } + + public function getBy(UuidInterface $userId): User + { + if (!isset($this->users[$userId->toString()])) { + throw new \RuntimeException(sprintf("User with id %s not found", $userId->toString())); + } + + return $this->users[$userId->toString()]; + } + + public function save(User $user): void + { + $this->users[$user->getUserId()->toString()] = $user; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/Messaging/MessageChannelConfiguration.php b/Monorepo/ExampleApp/Common/Infrastructure/Messaging/MessageChannelConfiguration.php new file mode 100644 index 000000000..278dba5da --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/Messaging/MessageChannelConfiguration.php @@ -0,0 +1,30 @@ +messages[] = $message; + } + + /** + * @return array + */ + public function read(): array + { + return $this->messages; + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/StubNotificationSender.php b/Monorepo/ExampleApp/Common/Infrastructure/StubNotificationSender.php new file mode 100644 index 000000000..8a2aa35c2 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/StubNotificationSender.php @@ -0,0 +1,19 @@ +output->write("Sending Order Confirmation Notification!"); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/StubShippingService.php b/Monorepo/ExampleApp/Common/Infrastructure/StubShippingService.php new file mode 100644 index 000000000..013212c81 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/StubShippingService.php @@ -0,0 +1,23 @@ +output->write(sprintf("Shipping products to %s %s!", $shippingAddress->street, $shippingAddress->houseNumber)); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/Infrastructure/SystemClock.php b/Monorepo/ExampleApp/Common/Infrastructure/SystemClock.php new file mode 100644 index 000000000..3a9757d75 --- /dev/null +++ b/Monorepo/ExampleApp/Common/Infrastructure/SystemClock.php @@ -0,0 +1,15 @@ +getContent(), true, flags: JSON_THROW_ON_ERROR); + $currentUserId = $this->authenticationService->getCurrentUserId(); + $orderId = Uuid::fromString($data['orderId']); + $shippingAddress = new ShippingAddress($data['address']['street'], $data['address']['houseNumber'], $data['address']['postCode'], $data['address']['country']); + $productId = Uuid::fromString($data['productId']); + + $this->commandBus->send(new PlaceOrder($orderId, $currentUserId, $shippingAddress, $productId), metadata: [ + 'orderId' => $orderId->toString() + ]); + + return new Response(); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Common/UI/OrderControllerWithoutMessaging.php b/Monorepo/ExampleApp/Common/UI/OrderControllerWithoutMessaging.php new file mode 100644 index 000000000..6c5683830 --- /dev/null +++ b/Monorepo/ExampleApp/Common/UI/OrderControllerWithoutMessaging.php @@ -0,0 +1,37 @@ +getContent(), true, flags: JSON_THROW_ON_ERROR); + $currentUserId = $this->authenticationService->getCurrentUserId(); + $orderId = Uuid::fromString($data['orderId']); + $shippingAddress = new ShippingAddress($data['address']['street'], $data['address']['houseNumber'], $data['address']['postCode'], $data['address']['country']); + $productId = Uuid::fromString($data['productId']); + + $order = Order::create(new PlaceOrder($orderId, $currentUserId, $shippingAddress, $productId), $this->productRepository, $this->clock); + $this->orderRepository->save([$orderId->toString()], $order, [], null); + + return new Response(); + } +} \ No newline at end of file diff --git a/Monorepo/ExampleApp/Laravel/app/Providers/AppServiceProvider.php b/Monorepo/ExampleApp/Laravel/app/Providers/AppServiceProvider.php new file mode 100644 index 000000000..219d0c90d --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/app/Providers/AppServiceProvider.php @@ -0,0 +1,70 @@ +app->singleton(Configuration::class, fn () => new Configuration()); + $this->app->singleton(Output::class, fn () => new Output()); + + $this->app->singleton(AuthenticationService::class, function (Application $app) { + $configuration = $app->make(Configuration::class); + return $configuration->authentication(); + }); + + $this->app->alias(LoggerInterface::class, 'logger'); + $this->app->singleton('files', fn () => new Filesystem()); + + $this->app->singleton(OrderController::class); + $this->app->singleton(UuidConverter::class); + $this->app->singleton(Clock::class, SystemClock::class); + $this->app->singleton(InMemoryOrderRepository::class); + $this->app->singleton(NotificationSubscriber::class); + $this->app->singleton(NotificationSender::class, StubNotificationSender::class); + $this->app->singleton(ShippingSubscriber::class); + $this->app->singleton(ShippingService::class, StubShippingService::class); + + $this->app->singleton(UserRepository::class, function (Application $app) { + $configuration = $app->make(Configuration::class); + return $configuration->userRepository(); + }); + + $this->app->singleton(ProductRepository::class, function (Application $app) { + $configuration = $app->make(Configuration::class); + return $configuration->productRepository(); + }); + } + + /** + * Bootstrap any application services. + */ + public function boot(): void + { + } +} diff --git a/Monorepo/ExampleApp/Laravel/artisan b/Monorepo/ExampleApp/Laravel/artisan new file mode 100755 index 000000000..5b2842f57 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/artisan @@ -0,0 +1,53 @@ +#!/usr/bin/env php +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running, we will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/Monorepo/ExampleApp/Laravel/bootstrap/app.php b/Monorepo/ExampleApp/Laravel/bootstrap/app.php new file mode 100644 index 000000000..0bede82a9 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + \Illuminate\Foundation\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + \Illuminate\Foundation\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + \Illuminate\Foundation\Exceptions\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/Monorepo/ExampleApp/Laravel/bootstrap/cache/.gitkeep b/Monorepo/ExampleApp/Laravel/bootstrap/cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/Monorepo/ExampleApp/Laravel/config/app.php b/Monorepo/ExampleApp/Laravel/config/app.php new file mode 100644 index 000000000..66002f63c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/app.php @@ -0,0 +1,199 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + 'asset_url' => env('ASSET_URL'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => 'file', + // 'store' => 'redis', + ], + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => [ + /* + * Laravel Framework Service Providers... + */ +// Illuminate\Bus\BusServiceProvider::class, + Illuminate\Cache\CacheServiceProvider::class, +// Illuminate\Foundation\Providers\FoundationServiceProvider::class, +// Illuminate\Hashing\HashServiceProvider::class, +// Illuminate\Notifications\NotificationServiceProvider::class, +// Illuminate\Pagination\PaginationServiceProvider::class, +// Illuminate\Pipeline\PipelineServiceProvider::class, +// Illuminate\Queue\QueueServiceProvider::class, + + /* + * Package Service Providers... + */ + \Ecotone\Laravel\EcotoneProvider::class, + + /* + * Application Service Providers... + */ + \Monorepo\ExampleApp\Laravel\app\Providers\AppServiceProvider::class, + ], + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => Facade::defaultAliases()->merge([ + // 'Example' => App\Facades\Example::class, + ])->toArray(), + +]; diff --git a/Monorepo/ExampleApp/Laravel/config/cache.php b/Monorepo/ExampleApp/Laravel/config/cache.php new file mode 100644 index 000000000..d4171e221 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/cache.php @@ -0,0 +1,111 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'apc' => [ + 'driver' => 'apc', + ], + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'table' => 'cache', + 'connection' => null, + 'lock_connection' => null, + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => 'cache', + 'lock_connection' => 'default', + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, or DynamoDB cache + | stores there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + +]; diff --git a/Monorepo/ExampleApp/Laravel/config/ecotone.php b/Monorepo/ExampleApp/Laravel/config/ecotone.php new file mode 100644 index 000000000..84ee5582b --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/ecotone.php @@ -0,0 +1,10 @@ + [ + 'Monorepo\ExampleApp\Common', + ], + 'skippedModulePackageNames' => ModulePackageList::allPackagesExcept([ModulePackageList::ASYNCHRONOUS_PACKAGE]), +]; diff --git a/Monorepo/ExampleApp/Laravel/config/filesystems.php b/Monorepo/ExampleApp/Laravel/config/filesystems.php new file mode 100644 index 000000000..58f9fd058 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/filesystems.php @@ -0,0 +1,82 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been set up for each driver as an example of the required values. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'throw' => false, + ], + + 'common' => [ + 'driver' => 'local', + 'root' => storage_path('../../Common'), + 'throw' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/Monorepo/ExampleApp/Laravel/config/logging.php b/Monorepo/ExampleApp/Laravel/config/logging.php new file mode 100644 index 000000000..0b0ecf484 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/logging.php @@ -0,0 +1,131 @@ + env('LOG_CHANNEL', 'null'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Laravel uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + +// 'channels' => [ +// 'stack' => [ +// 'driver' => 'stack', +// 'channels' => ['single'], +// 'ignore_exceptions' => false, +// ], +// +// 'single' => [ +// 'driver' => 'single', +// 'path' => storage_path('logs/laravel.log'), +// 'level' => env('LOG_LEVEL', 'debug'), +// 'replace_placeholders' => true, +// ], +// +// 'daily' => [ +// 'driver' => 'daily', +// 'path' => storage_path('logs/laravel.log'), +// 'level' => env('LOG_LEVEL', 'debug'), +// 'days' => 14, +// 'replace_placeholders' => true, +// ], +// +// 'slack' => [ +// 'driver' => 'slack', +// 'url' => env('LOG_SLACK_WEBHOOK_URL'), +// 'username' => 'Laravel Log', +// 'emoji' => ':boom:', +// 'level' => env('LOG_LEVEL', 'critical'), +// 'replace_placeholders' => true, +// ], +// +// 'papertrail' => [ +// 'driver' => 'monolog', +// 'level' => env('LOG_LEVEL', 'debug'), +// 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), +// 'handler_with' => [ +// 'host' => env('PAPERTRAIL_URL'), +// 'port' => env('PAPERTRAIL_PORT'), +// 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), +// ], +// 'processors' => [PsrLogMessageProcessor::class], +// ], +// +//// 'stderr' => [ +//// 'driver' => 'monolog', +//// 'level' => env('LOG_LEVEL', 'debug'), +//// 'handler' => StreamHandler::class, +//// 'formatter' => env('LOG_STDERR_FORMATTER'), +//// 'with' => [ +//// 'stream' => 'php://stderr', +//// ], +//// 'processors' => [PsrLogMessageProcessor::class], +//// ], +// +// 'syslog' => [ +// 'driver' => 'syslog', +// 'level' => env('LOG_LEVEL', 'debug'), +// 'facility' => LOG_USER, +// 'replace_placeholders' => true, +// ], +// +// 'errorlog' => [ +// 'driver' => 'errorlog', +// 'level' => env('LOG_LEVEL', 'debug'), +// 'replace_placeholders' => true, +// ], +// +// 'null' => [ +// 'driver' => 'monolog', +// 'handler' => NullHandler::class, +// ], +// +// 'emergency' => [ +// 'path' => storage_path('logs/laravel.log'), +// ], +// ], + +]; diff --git a/Monorepo/ExampleApp/Laravel/config/services.php b/Monorepo/ExampleApp/Laravel/config/services.php new file mode 100644 index 000000000..0ace530e8 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/config/services.php @@ -0,0 +1,34 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'secret' => env('MAILGUN_SECRET'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'scheme' => 'https', + ], + + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + +]; diff --git a/Monorepo/ExampleApp/Laravel/public/favicon.ico b/Monorepo/ExampleApp/Laravel/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/Monorepo/ExampleApp/Laravel/public/index.php b/Monorepo/ExampleApp/Laravel/public/index.php new file mode 100644 index 000000000..1d69f3a28 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/public/index.php @@ -0,0 +1,55 @@ +make(Kernel::class); + +$response = $kernel->handle( + $request = Request::capture() +)->send(); + +$kernel->terminate($request, $response); diff --git a/Monorepo/ExampleApp/Laravel/public/robots.txt b/Monorepo/ExampleApp/Laravel/public/robots.txt new file mode 100644 index 000000000..eb0536286 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/Monorepo/ExampleApp/Laravel/run.php b/Monorepo/ExampleApp/Laravel/run.php new file mode 100644 index 000000000..4c7c5e2dc --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/run.php @@ -0,0 +1,31 @@ +make(\Illuminate\Foundation\Http\Kernel::class)->bootstrap(); + +$messagingSystem =$app->get(ConfiguredMessagingSystem::class); +$orderController =$app->get(OrderController::class); +$configuration = $app->get(Configuration::class); + +$orderController->placeOrder(new Request(content: json_encode([ + 'orderId' => Uuid::uuid4()->toString(), + 'address' => [ + 'street' => 'Washington', + 'houseNumber' => '15', + 'postCode' => '81-221', + 'country' => 'Netherlands' + ], + 'productId' => $configuration->productId(), +]))); + +$messagingSystem->run("asynchronous", ExecutionPollingMetadata::createWithDefaults()->withTestingSetup(2)); diff --git a/Monorepo/ExampleApp/Laravel/storage/app/.gitignore b/Monorepo/ExampleApp/Laravel/storage/app/.gitignore new file mode 100644 index 000000000..8f4803c05 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/app/.gitignore @@ -0,0 +1,3 @@ +* +!public/ +!.gitignore diff --git a/Monorepo/ExampleApp/Laravel/storage/app/public/.gitignore b/Monorepo/ExampleApp/Laravel/storage/app/public/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/app/public/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/Monorepo/ExampleApp/Laravel/storage/framework/.gitignore b/Monorepo/ExampleApp/Laravel/storage/framework/.gitignore new file mode 100644 index 000000000..05c4471f2 --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/framework/.gitignore @@ -0,0 +1,9 @@ +compiled.php +config.php +down +events.scanned.php +maintenance.php +routes.php +routes.scanned.php +schedule-* +services.json diff --git a/Monorepo/ExampleApp/Laravel/storage/framework/sessions/.gitignore b/Monorepo/ExampleApp/Laravel/storage/framework/sessions/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/Monorepo/ExampleApp/Laravel/storage/framework/testing/.gitignore b/Monorepo/ExampleApp/Laravel/storage/framework/testing/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/framework/testing/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/Monorepo/ExampleApp/Laravel/storage/framework/views/.gitignore b/Monorepo/ExampleApp/Laravel/storage/framework/views/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/Monorepo/ExampleApp/Laravel/storage/logs/.gitignore b/Monorepo/ExampleApp/Laravel/storage/logs/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/Monorepo/ExampleApp/Laravel/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/Monorepo/ExampleApp/Lite/app.php b/Monorepo/ExampleApp/Lite/app.php new file mode 100644 index 000000000..60cc710f7 --- /dev/null +++ b/Monorepo/ExampleApp/Lite/app.php @@ -0,0 +1,47 @@ + $configuration, + NotificationSender::class => new StubNotificationSender($output), + ShippingService::class => new StubShippingService($output), + Clock::class => new SystemClock(), + OrderRepository::class => new InMemoryOrderRepository(), + AuthenticationService::class => $configuration->authentication(), + UserRepository::class => $configuration->userRepository(), + ProductRepository::class => $configuration->productRepository(), + ]; + + return EcotoneLiteApplication::bootstrap( + serviceConfiguration: ServiceConfiguration::createWithDefaults() + ->doNotLoadCatalog() + ->withCacheDirectoryPath(__DIR__ . "/var/cache") + ->withSkippedModulePackageNames(ModulePackageList::allPackagesExcept([ModulePackageList::ASYNCHRONOUS_PACKAGE])) + ->withNamespaces(['Monorepo\\ExampleApp\\Common\\']), + cacheConfiguration: $useCachedVersion, + pathToRootCatalog: __DIR__.'/../Common', + classesToRegister: $classesToRegister, + ); +}; diff --git a/Monorepo/ExampleApp/Lite/run.php b/Monorepo/ExampleApp/Lite/run.php new file mode 100644 index 000000000..05b992045 --- /dev/null +++ b/Monorepo/ExampleApp/Lite/run.php @@ -0,0 +1,26 @@ +getServiceFromContainer(OrderController::class); +$configuration = $messagingSystem->getServiceFromContainer(Configuration::class); + +$orderController->placeOrder(new Request(content: json_encode([ + 'orderId' => Uuid::uuid4()->toString(), + 'address' => [ + 'street' => 'Washington', + 'houseNumber' => '15', + 'postCode' => '81-221', + 'country' => 'Netherlands' + ], + 'productId' => $configuration->productId(), +]))); diff --git a/Monorepo/ExampleApp/Symfony/Kernel.php b/Monorepo/ExampleApp/Symfony/Kernel.php new file mode 100644 index 000000000..c56f3bf80 --- /dev/null +++ b/Monorepo/ExampleApp/Symfony/Kernel.php @@ -0,0 +1,15 @@ +run($input); \ No newline at end of file diff --git a/Monorepo/ExampleApp/Symfony/bin/run.php b/Monorepo/ExampleApp/Symfony/bin/run.php new file mode 100644 index 000000000..eacf042cd --- /dev/null +++ b/Monorepo/ExampleApp/Symfony/bin/run.php @@ -0,0 +1,31 @@ +boot(); +$container = $kernel->getContainer(); + +$messagingSystem = $container->get(ConfiguredMessagingSystem::class); +$orderController = $container->get(OrderController::class); +$configuration = $container->get(Configuration::class); + +$orderController->placeOrder(new Request(content: json_encode([ + 'orderId' => Uuid::uuid4()->toString(), + 'address' => [ + 'street' => 'Washington', + 'houseNumber' => '15', + 'postCode' => '81-221', + 'country' => 'Netherlands' + ], + 'productId' => $configuration->productId(), +]))); + +$kernel->shutdown(); \ No newline at end of file diff --git a/Monorepo/ExampleApp/Symfony/config/bundles.php b/Monorepo/ExampleApp/Symfony/config/bundles.php new file mode 100644 index 000000000..50a4a672a --- /dev/null +++ b/Monorepo/ExampleApp/Symfony/config/bundles.php @@ -0,0 +1,8 @@ + ['all' => true], + EcotoneSymfonyBundle::class => ['all' => true], +]; diff --git a/Monorepo/ExampleApp/Symfony/config/services.php b/Monorepo/ExampleApp/Symfony/config/services.php new file mode 100644 index 000000000..163e0fa8e --- /dev/null +++ b/Monorepo/ExampleApp/Symfony/config/services.php @@ -0,0 +1,38 @@ +extension('ecotone', [ + 'defaultSerializationMediaType' => 'application/json', + 'loadSrcNamespaces' => false, + 'namespaces' => ['Monorepo\\ExampleApp\\Common'], + 'defaultErrorChannel' => 'errorChannel', + 'failFast' => false, + 'skippedModulePackageNames' => ModulePackageList::allPackagesExcept([ModulePackageList::ASYNCHRONOUS_PACKAGE]), + ]); + + $services = $containerConfigurator->services(); + + $services->defaults() + ->autowire() + ->autoconfigure(); + + $services->load('Monorepo\\ExampleApp\\Common\\', '%kernel.project_dir%/../Common/'); + + $services->set(Configuration::class)->public(); + $services->get(OrderController::class)->public(); + $services->get(OrderControllerWithoutMessaging::class)->public(); + + $services->set(UserRepository::class)->factory([service(Configuration::class), 'userRepository']); + $services->set(ProductRepository::class)->factory([service(Configuration::class), 'productRepository']); + $services->get(AuthenticationService::class)->factory([service(Configuration::class), 'authentication']); +}; \ No newline at end of file