Skip to content

Commit

Permalink
Compiled event sourcing (#242)
Browse files Browse the repository at this point in the history
* Allow to load different modules

* load namespaces condtionally

* Event sourcing test scenario

* Failing test

* add a ValidityCheckPass.php

* fix symfony external references aliasing

* make it work

* fix another missing DefinedObject

* cleaning

* disabling dbal

* clean

* add laravel missing directory

---------

Co-authored-by: jlabedo <jean@needelp.com>
  • Loading branch information
dgafka and jlabedo authored Oct 24, 2023
1 parent d419ffe commit f427ed0
Show file tree
Hide file tree
Showing 67 changed files with 1,574 additions and 156 deletions.
11 changes: 5 additions & 6 deletions Monorepo/Benchmark/AsynchronousStackBenchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@
namespace Monorepo\Benchmark;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Endpoint\ExecutionPollingMetadata;
use Ecotone\Modelling\CommandBus;
use Ecotone\Modelling\QueryBus;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Illuminate\Support\Facades\Artisan;
use Monorepo\CrossModuleTests\Tests\FullAppTestCase;
use Monorepo\ExampleApp\Common\Domain\Order\Command\PlaceOrder;
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Psr\Container\ContainerInterface;
use Ramsey\Uuid\Uuid;

#[Warmup(1), Revs(10), Iterations(5)]
final class AsynchronousStackBenchmark extends FullAppTestCase
final class AsynchronousStackBenchmark extends FullAppBenchmarkCase
{
public function executeForSymfony(ContainerInterface $container, SymfonyKernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
Expand Down
5 changes: 4 additions & 1 deletion Monorepo/Benchmark/BootingEcotoneBenchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Ecotone\Lite\EcotoneLiteApplication;
use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel;
use PhpBench\Attributes\Iterations;
use PhpBench\Attributes\Revs;
Expand All @@ -14,7 +15,9 @@
#[Warmup(1), Revs(10), Iterations(5)]
class BootingEcotoneBenchmark extends FullAppBenchmarkCase
{
public function executeForSymfony(ContainerInterface $container, Kernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$container->get(ConfiguredMessagingSystem::class)->list();
}
Expand Down
34 changes: 23 additions & 11 deletions Monorepo/Benchmark/FullAppBenchmarkCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
namespace Monorepo\Benchmark;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Config\ModulePackageList;
use Ecotone\Messaging\Endpoint\ExecutionPollingMetadata;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Illuminate\Support\Facades\Artisan;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Console\Application as SymfonyConsoleApplication;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpKernel\Kernel as SymfonyKernel;

/**
* @BeforeClassMethods("clearAllCaches")
Expand Down Expand Up @@ -60,31 +61,31 @@ public function bench_laravel_dev(): void
public function bench_lite_application_prod()
{
self::productionEnvironments();
$bootstrap = require __DIR__ . "/../ExampleApp/LiteApplication/app.php";
$bootstrap = require static::getProjectDir() . '/LiteApplication/app.php';
$messagingSystem = $bootstrap(true);
$this->executeForLiteApplication(new LiteContainerAccessor($messagingSystem));
}

public function bench_lite_application_dev()
{
self::developmentEnvironments();
$bootstrap = require __DIR__ . "/../ExampleApp/LiteApplication/app.php";
$bootstrap = require static::getProjectDir() . '/LiteApplication/app.php';
$messagingSystem = $bootstrap(false);
$this->executeForLiteApplication(new LiteContainerAccessor($messagingSystem));
}

public function bench_lite_prod()
{
self::productionEnvironments();
$bootstrap = require __DIR__ . '/../ExampleApp/Lite/app.php';
$bootstrap = require static::getProjectDir() . '/Lite/app.php';
$messagingSystem = $bootstrap(true);
$this->executeForLite($messagingSystem);
}

public function bench_lite_dev()
{
self::developmentEnvironments();
$bootstrap = require __DIR__ . '/../ExampleApp/Lite/app.php';
$bootstrap = require static::getProjectDir() . '/Lite/app.php';
$messagingSystem = $bootstrap(false);
$this->executeForLite($messagingSystem);
}
Expand All @@ -100,15 +101,15 @@ public static function clearAllCaches(): void
public static function clearLiteCache(): void
{
self::deleteFiles(
__DIR__ . '/../ExampleApp/Lite/var/cache',
static::getProjectDir() . '/Lite/var/cache',
false
);
}

public static function clearLiteApplicationCache(): void
{
self::deleteFiles(
__DIR__ . '/../ExampleApp/LiteApplication/var/cache',
static::getProjectDir() . '/LiteApplication/var/cache',
false
);
}
Expand All @@ -128,15 +129,15 @@ public function dumpLaravelCache(): void
public static function clearLaravelCache(): void
{
self::deleteFiles(
__DIR__ . '/../ExampleApp/Laravel/storage/framework/cache/data',
static::getProjectDir() . '/Laravel/storage/framework/cache/data',
false
);
}

public static function clearSymfonyCache(): void
{
self::deleteFiles(
__DIR__ . '/../ExampleApp/Symfony/var/cache',
static::getProjectDir() . '/Symfony/var/cache',
false
);
}
Expand Down Expand Up @@ -184,21 +185,31 @@ public abstract function executeForLite(
ConfiguredMessagingSystem $messagingSystem
): void;

protected abstract static function getSymfonyKernelClass(): string;
protected abstract static function getProjectDir(): string;

private static function productionEnvironments(): void
{
\putenv('APP_ENV=prod');
\putenv('APP_DEBUG=false');
\putenv(sprintf('APP_SKIPPED_PACKAGES=%s', \json_encode(static::skippedPackages(), JSON_THROW_ON_ERROR)));
}

private static function developmentEnvironments(): void
{
\putenv('APP_ENV=dev');
\putenv('APP_DEBUG=true');
\putenv(sprintf("APP_SKIPPED_PACKAGES=%s", \json_encode(static::skippedPackages(), JSON_THROW_ON_ERROR)));
}

public static function skippedPackages(): array
{
return ModulePackageList::allPackagesExcept([ModulePackageList::ASYNCHRONOUS_PACKAGE]);
}

private static function createLaravelApplication(): Application
{
$app = require __DIR__ . '/../ExampleApp/Laravel/bootstrap/app.php';
$app = require static::getProjectDir() . '/Laravel/bootstrap/app.php';

$app->make(LaravelKernel::class)->bootstrap();

Expand All @@ -207,7 +218,8 @@ private static function createLaravelApplication(): Application

private static function bootSymfonyKernel(string $environment, bool $debug): SymfonyKernel
{
$kernel = new SymfonyKernel($environment, $debug);
$kernelClass = static::getSymfonyKernelClass();
$kernel = new $kernelClass($environment, $debug);
$kernel->boot();
return $kernel;
}
Expand Down
4 changes: 3 additions & 1 deletion Monorepo/Benchmark/HttpStackBenchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Common\UI\OrderController;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use PhpBench\Attributes\Iterations;
use PhpBench\Attributes\Revs;
Expand All @@ -21,7 +22,8 @@
#[Warmup(1), Revs(10), Iterations(5)]
class HttpStackBenchmark extends FullAppBenchmarkCase
{
public function executeForSymfony(ContainerInterface $container, SymfonyKernel $kernel): void
use ExampleAppCaseTrait;
public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
$response = $kernel->handle(
Expand Down
5 changes: 4 additions & 1 deletion Monorepo/Benchmark/KernelBootBenchmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel;
use PhpBench\Attributes\Iterations;
use PhpBench\Attributes\Revs;
Expand All @@ -13,7 +14,9 @@
#[Warmup(1), Revs(10), Iterations(5)]
class KernelBootBenchmark extends FullAppBenchmarkCase
{
public function executeForSymfony(ContainerInterface $container, Kernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
// do nothing
}
Expand Down
13 changes: 5 additions & 8 deletions Monorepo/CrossModuleTests/Tests/AsynchronousStackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,22 @@
namespace Monorepo\CrossModuleTests\Tests;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Endpoint\ExecutionPollingMetadata;
use Ecotone\Modelling\CommandBus;
use Ecotone\Modelling\QueryBus;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Illuminate\Support\Facades\Artisan;
use Monorepo\ExampleApp\Common\Domain\Order\Command\PlaceOrder;
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Common\UI\OrderController;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use PHPUnit\Framework\Assert;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel;
use Psr\Container\ContainerInterface;
use Ramsey\Uuid\Uuid;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
use Illuminate\Http\Request as LaravelRequest;

final class AsynchronousStackTest extends FullAppTestCase
{
public function executeForSymfony(ContainerInterface $container, SymfonyKernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
Expand Down
11 changes: 5 additions & 6 deletions Monorepo/CrossModuleTests/Tests/ErrorChannelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@
namespace Monorepo\CrossModuleTests\Tests;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Endpoint\ExecutionPollingMetadata;
use Ecotone\Modelling\CommandBus;
use Ecotone\Modelling\QueryBus;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Illuminate\Support\Facades\Artisan;
use Monorepo\ExampleApp\Common\Domain\Order\Command\PlaceOrder;
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel;
use Psr\Container\ContainerInterface;

final class ErrorChannelTest extends FullAppTestCase
{
public function executeForSymfony(ContainerInterface $container, SymfonyKernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
Expand Down Expand Up @@ -124,6 +125,4 @@ private function placeOrder(mixed $commandBus, Configuration $configuration): vo
)
);
}


}
85 changes: 85 additions & 0 deletions Monorepo/CrossModuleTests/Tests/EventSourcingStackTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace Monorepo\CrossModuleTests\Tests;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Config\ModulePackageList;
use Ecotone\Modelling\CommandBus;
use Ecotone\Modelling\QueryBus;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Monorepo\ExampleAppEventSourcing\Common\Command\ChangePrice;
use Monorepo\ExampleAppEventSourcing\Common\Command\RegisterProduct;
use Monorepo\ExampleAppEventSourcing\Common\PriceChange;
use Monorepo\ExampleAppEventSourcing\ExampleAppEventSourcingCaseTrait;
use Monorepo\ExampleAppEventSourcing\Symfony\Kernel;
use Monorepo\ExampleAppEventSourcing\Symfony\Kernel as SymfonyKernel;
use PHPUnit\Framework\Assert;
use Psr\Container\ContainerInterface;
use Ramsey\Uuid\Uuid;

final class EventSourcingStackTest extends FullAppTestCase
{
use ExampleAppEventSourcingCaseTrait;

public static function skippedPackages(): array
{
return ModulePackageList::allPackagesExcept([
ModulePackageList::EVENT_SOURCING_PACKAGE,
// @TODO uncomment to fail on dbal configuration
// @dgafka: it is required to register "Enqueue\Dbal\DbalConnectionFactory" when using dbal, or you will get a compile time error
// ModulePackageList::DBAL_PACKAGE,
ModulePackageList::JMS_CONVERTER_PACKAGE
]);
}

public static function namespacesToLoad(): array
{
return ['Monorepo\ExampleApp\CommonEventSourcing'];
}

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$this->executeTestScenario(
$container->get(CommandBus::class),
$container->get(QueryBus::class)
);
}

private function executeTestScenario(CommandBus $commandBus, QueryBus $queryBus): void
{
$productId = Uuid::uuid4()->toString();
$commandBus->send(new RegisterProduct($productId, 100));

Assert::assertEquals([new PriceChange(100, 0)], $queryBus->sendWithRouting('product.getPriceChange', $productId), 'Price change should equal to 0 after registration');

$commandBus->send(new ChangePrice($productId, 120));

Assert::assertEquals([new PriceChange(100, 0), new PriceChange(120, 20)], $queryBus->sendWithRouting('product.getPriceChange', $productId), 'Price change should equal to 0 after registration');
}

public function executeForLaravel(ContainerInterface $container, LaravelKernel $kernel): void
{
$this->executeTestScenario(
$container->get(CommandBus::class),
$container->get(QueryBus::class)
);
}

public function executeForLiteApplication(ContainerInterface $container): void
{
$this->executeTestScenario(
$container->get(CommandBus::class),
$container->get(QueryBus::class)
);
}

public function executeForLite(ConfiguredMessagingSystem $messagingSystem): void
{
$this->executeTestScenario(
$messagingSystem->getCommandBus(),
$messagingSystem->getQueryBus()
);
}
}
6 changes: 5 additions & 1 deletion Monorepo/CrossModuleTests/Tests/HttpStackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Common\UI\OrderController;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use Monorepo\ExampleApp\Symfony\Kernel;
use Monorepo\ExampleApp\Symfony\Kernel as SymfonyKernel;
use PHPUnit\Framework\Assert;
use Psr\Container\ContainerInterface;
Expand All @@ -19,7 +21,9 @@

final class HttpStackTest extends FullAppTestCase
{
public function executeForSymfony(ContainerInterface $container, SymfonyKernel $kernel): void
use ExampleAppCaseTrait;

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
$response = $kernel->handle(
Expand Down
Loading

0 comments on commit f427ed0

Please sign in to comment.