Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@
"Symfony\\App\\MultiTenant\\": "packages/Symfony/tests/phpunit/MultiTenant/src",
"Symfony\\App\\SingleTenant\\": "packages/Symfony/tests/phpunit/SingleTenant/src",
"Symfony\\App\\Licence\\": "packages/Symfony/tests/phpunit/Licence/src",
"Symfony\\App\\EnvPlaceholderEndpoint\\": "packages/Symfony/tests/phpunit/EnvPlaceholderEndpoint/src",
"Symfony\\App\\EnvPlaceholderKafka\\": "packages/Symfony/tests/phpunit/EnvPlaceholderKafka/src",
"Tests\\Ecotone\\": "tests"
}
},
Expand Down
1 change: 1 addition & 0 deletions packages/Amqp/src/Attribute/RabbitConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function getDefinition(): Definition
[
$this->getEndpointId(),
$this->queueName,
$this->finalFailureStrategy,
$this->connectionReference,
]
);
Expand Down
9 changes: 8 additions & 1 deletion packages/Ecotone/src/Messaging/Attribute/Asynchronous.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace Ecotone\Messaging\Attribute;

use Attribute;
use Ecotone\Messaging\Config\Container\DefinedObject;
use Ecotone\Messaging\Config\Container\Definition;
use Ecotone\Messaging\Support\Assert;

#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
/**
* licence Apache-2.0
*/
class Asynchronous
class Asynchronous implements DefinedObject
{
private string|array $channelName;
/** @var AsynchronousEndpointAttribute[] */
Expand Down Expand Up @@ -40,4 +42,9 @@ public function getAsynchronousExecution(): array
{
return $this->asynchronousExecution;
}

public function getDefinition(): Definition
{
return new Definition(self::class, [$this->channelName, $this->asynchronousExecution]);
}
}
15 changes: 14 additions & 1 deletion packages/Ecotone/src/Messaging/Attribute/DelayedRetry.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace Ecotone\Messaging\Attribute;

use Attribute;
use Ecotone\Messaging\Config\Container\DefinedObject;
use Ecotone\Messaging\Config\Container\Definition;
use Ecotone\Messaging\Support\Assert;

/**
* licence Enterprise
*/
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
final class DelayedRetry implements AsynchronousEndpointAttribute
final class DelayedRetry implements AsynchronousEndpointAttribute, DefinedObject
{
public function __construct(
public readonly int $initialDelayMs,
Expand All @@ -26,6 +28,17 @@ public function __construct(
Assert::isTrue($deadLetterChannel === null || $deadLetterChannel !== '', 'DelayedRetry deadLetterChannel must be null or a non-empty channel name');
}

public function getDefinition(): Definition
{
return new Definition(self::class, [
$this->initialDelayMs,
$this->multiplier,
$this->maxDelayMs,
$this->maxAttempts,
$this->deadLetterChannel,
]);
}

public static function generateChannelName(string $handlerEndpointId): string
{
return 'ecotone.retry.' . $handlerEndpointId;
Expand Down
9 changes: 8 additions & 1 deletion packages/Ecotone/src/Messaging/Attribute/ErrorChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
namespace Ecotone\Messaging\Attribute;

use Attribute;
use Ecotone\Messaging\Config\Container\DefinedObject;
use Ecotone\Messaging\Config\Container\Definition;
use Ecotone\Messaging\Support\Assert;

/**
* licence Enterprise
*/
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
class ErrorChannel implements AsynchronousEndpointAttribute
class ErrorChannel implements AsynchronousEndpointAttribute, DefinedObject
{
/**
* @param string $errorChannelName Name of the error channel to send Message too
Expand All @@ -21,4 +23,9 @@ public function __construct(
) {
Assert::notNullAndEmpty($errorChannelName, 'Channel name can not be empty string');
}

public function getDefinition(): Definition
{
return new Definition(self::class, [$this->errorChannelName]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
namespace Ecotone\Messaging\Attribute;

use Attribute;
use Ecotone\Messaging\Config\Container\DefinedObject;
use Ecotone\Messaging\Config\Container\Definition;

/**
* licence Apache-2.0
*/
#[Attribute]
class WithoutDatabaseTransaction implements AsynchronousEndpointAttribute
class WithoutDatabaseTransaction implements AsynchronousEndpointAttribute, DefinedObject
{
public function getDefinition(): Definition
{
return new Definition(self::class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
namespace Ecotone\Messaging\Attribute;

use Attribute;
use Ecotone\Messaging\Config\Container\DefinedObject;
use Ecotone\Messaging\Config\Container\Definition;

/**
* licence Enterprise
*/
#[Attribute]
class WithoutMessageCollector implements AsynchronousEndpointAttribute
class WithoutMessageCollector implements AsynchronousEndpointAttribute, DefinedObject
{
public function getDefinition(): Definition
{
return new Definition(self::class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ public static function buildDefinitionFromInstance(object $object): Definition

public static function buildAttributeDefinitionFromInstance(object $object): AttributeDefinition
{
if ($object instanceof DefinedObject) {
$definition = $object->getDefinition();

return new AttributeDefinition(
$definition->getClassName(),
$definition->getArguments(),
$definition->hasFactory() ? $definition->getFactory() : '',
);
}

return new AttributeDefinition(get_class($object), [serialize($object)], [self::class, 'unserializeSerializedObject']);
}

Expand All @@ -37,7 +47,12 @@ public static function resolvePotentialComplexAttribute(AttributeDefinition $att
{
$attributeArguments = $attributeDefinition->getArguments();
if (self::isComplexArgument($attributeArguments)) {
return DefinitionHelper::buildDefinitionFromInstance($attributeDefinition->instance());
$instance = $attributeDefinition->instance();
if ($instance instanceof DefinedObject) {
return $instance->getDefinition();
}

return DefinitionHelper::buildDefinitionFromInstance($instance);
} else {
return $attributeDefinition;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/Symfony/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
"doctrine/doctrine-bundle": "^2.7.2",
"doctrine/orm": "^2.11|^3.0",
"ecotone/dbal": "~1.313.2",
"ecotone/kafka": "~1.313.2",
"ext-rdkafka": "*",
"monolog/monolog": "^2.9|^3.3.1",
"phpstan/phpstan": "^1.8",
"phpunit/phpunit": "^10.5|^11.0",
Expand Down Expand Up @@ -81,7 +83,9 @@
"Ecotone\\SymfonyBundle\\App\\": "App",
"Symfony\\App\\MultiTenant\\": "tests/phpunit/MultiTenant/src",
"Symfony\\App\\SingleTenant\\": "tests/phpunit/SingleTenant/src",
"Symfony\\App\\Licence\\": "tests/phpunit/Licence/src"
"Symfony\\App\\Licence\\": "tests/phpunit/Licence/src",
"Symfony\\App\\EnvPlaceholderEndpoint\\": "tests/phpunit/EnvPlaceholderEndpoint/src",
"Symfony\\App\\EnvPlaceholderKafka\\": "tests/phpunit/EnvPlaceholderKafka/src"
}
},
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Test\EnvPlaceholderEndpoint;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Endpoint\ExecutionPollingMetadata;
use Ecotone\Modelling\CommandBus;
use Ecotone\SymfonyBundle\DependencyInjection\Compiler\CacheClearer;
use Ecotone\Test\LicenceTesting;
use PHPUnit\Framework\TestCase;
use Symfony\App\EnvPlaceholderEndpoint\Configuration\Kernel;

/**
* Reproduces https://github.com/ecotoneframework/ecotone-dev/issues/669
*
* licence Enterprise
* @internal
*/
final class EnvPlaceholderEndpointTest extends TestCase
{
protected function setUp(): void
{
putenv('SYMFONY_LICENCE_KEY=' . LicenceTesting::VALID_LICENCE);
putenv('ECOTONE_ERROR_CHANNEL=orders.error');
}

protected function tearDown(): void
{
putenv('SYMFONY_LICENCE_KEY');
putenv('ECOTONE_ERROR_CHANNEL');

restore_exception_handler();
}

public function test_consuming_async_handler_whose_endpoint_annotation_uses_env_placeholder(): void
{
$kernel = new Kernel('test', true);
$kernel->boot();
$container = $kernel->getContainer();
$container->get(CacheClearer::class)->clear('');

$container->get(CommandBus::class)->sendWithRouting('order.place', 'order-1');

$container->get(ConfiguredMessagingSystem::class)
->run('orders', ExecutionPollingMetadata::createWithTestingSetup());

$this->expectNotToPerformAssertions();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

use Ecotone\SymfonyBundle\EcotoneSymfonyBundle;

return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
EcotoneSymfonyBundle::class => ['all' => true],
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

use Ecotone\Messaging\Config\ModulePackageList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('ecotone', [
'skippedModulePackageNames' => ModulePackageList::allPackagesExcept([
ModulePackageList::SYMFONY_PACKAGE,
ModulePackageList::ASYNCHRONOUS_PACKAGE,
]),
'licenceKey' => '%env(SYMFONY_LICENCE_KEY)%',
]);

$services = $containerConfigurator->services();

$services->load('Symfony\\App\\EnvPlaceholderEndpoint\\', '%kernel.project_dir%/src/')
->autowire()
->autoconfigure();
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Symfony\App\EnvPlaceholderEndpoint\Configuration;

use Ecotone\Messaging\Attribute\ServiceContext;
use Ecotone\Messaging\Channel\SimpleMessageChannelBuilder;

/**
* licence Apache-2.0
*/
final class EcotoneConfiguration
{
#[ServiceContext]
public function ordersChannel(): array
{
return [
SimpleMessageChannelBuilder::createQueueChannel('orders'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Symfony\App\EnvPlaceholderEndpoint\Configuration;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;

/**
* licence Apache-2.0
*/
class Kernel extends \Symfony\Component\HttpKernel\Kernel
{
use MicroKernelTrait;

public function getProjectDir(): string
{
return __DIR__ . '/../../';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Symfony\App\EnvPlaceholderEndpoint;

use Ecotone\Messaging\Attribute\Asynchronous;
use Ecotone\Messaging\Attribute\ErrorChannel;
use Ecotone\Modelling\Attribute\CommandHandler;

/**
* licence Apache-2.0
*/
final class PlaceOrderHandler
{
#[Asynchronous('orders', asynchronousExecution: [new ErrorChannel('errorChannel.%env(ECOTONE_ERROR_CHANNEL)%')])]
#[CommandHandler('order.place', endpointId: 'placeOrderEndpoint')]
public function placeOrder(string $command): void
{
}
}
Loading
Loading