Skip to content

[Messenger] Extract Dsn object #32566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
$serializerId = $transport['serializer'] ?? 'messenger.default_serializer';

$transportDefinition = (new Definition(TransportInterface::class))
->setFactory([new Reference('messenger.transport_factory'), 'createTransport'])
->setFactory([new Reference('messenger.transport_factory'), 'fromString'])
->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)])
->addTag('messenger.receiver', ['alias' => $name])
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ public function testMessengerTransports()
$transportFactory = $container->getDefinition('messenger.transport.customised')->getFactory();
$transportArguments = $container->getDefinition('messenger.transport.customised')->getArguments();

$this->assertEquals([new Reference('messenger.transport_factory'), 'createTransport'], $transportFactory);
$this->assertEquals([new Reference('messenger.transport_factory'), 'fromString'], $transportFactory);
$this->assertCount(3, $transportArguments);
$this->assertSame('amqp://localhost/%2f/messages?exchange_name=exchange_name', $transportArguments[0]);
$this->assertEquals(['queue' => ['name' => 'Queue'], 'transport_name' => 'customised'], $transportArguments[1]);
Expand All @@ -699,7 +699,7 @@ public function testMessengerTransports()
$transportFactory = $container->getDefinition('messenger.transport.redis')->getFactory();
$transportArguments = $container->getDefinition('messenger.transport.redis')->getArguments();

$this->assertEquals([new Reference('messenger.transport_factory'), 'createTransport'], $transportFactory);
$this->assertEquals([new Reference('messenger.transport_factory'), 'fromString'], $transportFactory);
$this->assertCount(3, $transportArguments);
$this->assertSame('redis://127.0.0.1:6379/messages', $transportArguments[0]);

Expand Down
5 changes: 4 additions & 1 deletion src/Symfony/Component/Messenger/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ CHANGELOG

4.4.0
-----

* Added `Dsn` class which represents connection dsn.
* [BC BREAK] The `TransportFactoryInterface` interface
changed: `supports(Dsn $dsn)`, `createTransport(Dsn $dsn, SerializerInterface $serializer, string $name)`.
* [BC BREAK] Options from dsn overwrite options from options array in Doctrine transport.
* Added support for auto trimming of Redis streams.
* `InMemoryTransport` handle acknowledged and rejected messages.
* Made all dispatched worker event classes final.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,36 @@
use Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransport;
use Symfony\Component\Messenger\Transport\AmqpExt\AmqpTransportFactory;
use Symfony\Component\Messenger\Transport\AmqpExt\Connection;
use Symfony\Component\Messenger\Transport\Dsn;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;

class AmqpTransportFactoryTest extends TestCase
{
public function testSupportsOnlyAmqpTransports()
/**
* @dataProvider supportsProvider
*/
public function testSupports(Dsn $dsn, bool $supports): void
{
$factory = new AmqpTransportFactory();

$this->assertTrue($factory->supports('amqp://localhost', []));
$this->assertFalse($factory->supports('sqs://localhost', []));
$this->assertFalse($factory->supports('invalid-dsn', []));
$this->assertSame($supports, $factory->supports($dsn));
}

public function testItCreatesTheTransport()
public function supportsProvider(): iterable
{
yield [Dsn::fromString('amqp://localhost'), true];

yield [Dsn::fromString('foo://localhost'), false];
}

public function testCreate(): void
{
$factory = new AmqpTransportFactory();
$serializer = $this->createMock(SerializerInterface::class);

$expectedTransport = new AmqpTransport(Connection::fromDsn('amqp://localhost', ['foo' => 'bar']), $serializer);
$dsn = Dsn::fromString('amqp://localhost', ['foo' => 'bar']);
$expectedTransport = new AmqpTransport(Connection::fromDsnObject($dsn), $serializer);

$this->assertEquals($expectedTransport, $factory->createTransport('amqp://localhost', ['foo' => 'bar'], $serializer));
$this->assertEquals($expectedTransport, $factory->createTransport($dsn, $serializer, 'amqp'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ConnectionTest extends TestCase
public function testItCannotBeConstructedWithAWrongDsn()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('The given AMQP DSN "amqp://:" is invalid.');
$this->expectExceptionMessage('The "amqp://:" messenger DSN is invalid.');
Connection::fromDsn('amqp://:');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public function buildConfigurationProvider(): iterable
'expectedAutoSetup' => false,
];

yield 'options from options array wins over options from dsn' => [
yield 'options from dsn wins over options from options array' => [
'dsn' => 'doctrine://default?table_name=name_from_dsn&redeliver_timeout=1200&queue_name=normal&auto_setup=true',
'options' => [
'table_name' => 'name_from_options',
Expand All @@ -216,10 +216,10 @@ public function buildConfigurationProvider(): iterable
'auto_setup' => false,
],
'expectedConnection' => 'default',
'expectedTableName' => 'name_from_options',
'expectedRedeliverTimeout' => 1800,
'expectedQueue' => 'important',
'expectedAutoSetup' => false,
'expectedTableName' => 'name_from_dsn',
'expectedRedeliverTimeout' => 1200,
'expectedQueue' => 'normal',
'expectedAutoSetup' => true,
];

yield 'options from dsn with falsey boolean' => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,35 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\SchemaConfig;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Exception\TransportException;
use Symfony\Component\Messenger\Transport\Doctrine\Connection;
use Symfony\Component\Messenger\Transport\Doctrine\DoctrineTransport;
use Symfony\Component\Messenger\Transport\Doctrine\DoctrineTransportFactory;
use Symfony\Component\Messenger\Transport\Dsn;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;

class DoctrineTransportFactoryTest extends TestCase
{
public function testSupports()
/**
* @dataProvider supportsProvider
*/
public function testSupports(Dsn $dsn, bool $supports): void
{
$factory = new DoctrineTransportFactory(
$this->createMock(ConnectionRegistry::class)
);

$this->assertTrue($factory->supports('doctrine://default', []));
$this->assertFalse($factory->supports('amqp://localhost', []));
$this->assertSame($supports, $factory->supports($dsn));
}

public function testCreateTransport()
public function supportsProvider(): iterable
{
yield [Dsn::fromString('doctrine://localhost'), true];

yield [Dsn::fromString('foo://localhost'), false];
}

public function testCreate(): void
{
$driverConnection = $this->createMock(\Doctrine\DBAL\Connection::class);
$schemaManager = $this->createMock(AbstractSchemaManager::class);
Expand All @@ -48,15 +59,16 @@ public function testCreateTransport()
$factory = new DoctrineTransportFactory($registry);
$serializer = $this->createMock(SerializerInterface::class);

$this->assertEquals(
new DoctrineTransport(new Connection(Connection::buildConfiguration('doctrine://default'), $driverConnection), $serializer),
$factory->createTransport('doctrine://default', [], $serializer)
);
$dsn = Dsn::fromString('doctrine://default');
$connection = new Connection(Connection::buildConfigurationFromDsnObject($dsn), $driverConnection);
$expectedTransport = new DoctrineTransport($connection, $serializer);

$this->assertEquals($expectedTransport, $factory->createTransport($dsn, $serializer, 'doctrine'));
}

public function testCreateTransportMustThrowAnExceptionIfManagerIsNotFound()
public function testCreateTransportMustThrowAnExceptionIfManagerIsNotFound(): void
{
$this->expectException('Symfony\Component\Messenger\Exception\TransportException');
$this->expectException(TransportException::class);
$this->expectExceptionMessage('Could not find Doctrine connection from Messenger DSN "doctrine://default".');
$registry = $this->createMock(ConnectionRegistry::class);
$registry->expects($this->once())
Expand All @@ -66,6 +78,7 @@ public function testCreateTransportMustThrowAnExceptionIfManagerIsNotFound()
});

$factory = new DoctrineTransportFactory($registry);
$factory->createTransport('doctrine://default', [], $this->createMock(SerializerInterface::class));
$dsn = Dsn::fromString('doctrine://default');
$factory->createTransport($dsn, $this->createMock(SerializerInterface::class), 'doctrine');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Transport\Dsn;
use Symfony\Component\Messenger\Transport\InMemoryTransport;
use Symfony\Component\Messenger\Transport\InMemoryTransportFactory;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
Expand All @@ -34,36 +35,38 @@ protected function setUp(): void
}

/**
* @dataProvider provideDSN
* @dataProvider supportsProvider
*/
public function testSupports(string $dsn, bool $expected = true)
public function testSupports(Dsn $dsn, bool $supports): void
{
$this->assertSame($expected, $this->factory->supports($dsn, []), 'InMemoryTransportFactory::supports returned unexpected result.');
$this->assertSame($supports, $this->factory->supports($dsn));
}

public function testCreateTransport()
public function supportsProvider(): iterable
{
yield [Dsn::fromString('in-memory://'), true];

yield [Dsn::fromString('foo://localhost'), false];
}

public function testCreate(): void
{
/** @var SerializerInterface $serializer */
$serializer = $this->createMock(SerializerInterface::class);

$this->assertInstanceOf(InMemoryTransport::class, $this->factory->createTransport('in-memory://', [], $serializer));
$dsn = Dsn::fromString('in-memory://');
$expectedTransport = new InMemoryTransport();

$this->assertEquals($expectedTransport, $this->factory->createTransport($dsn, $serializer, 'in-memory'));
}

public function testResetCreatedTransports()
public function testResetCreatedTransports(): void
{
$transport = $this->factory->createTransport('in-memory://', [], $this->createMock(SerializerInterface::class));
$dsn = Dsn::fromString('in-memory://');
$transport = $this->factory->createTransport($dsn, $this->createMock(SerializerInterface::class), 'in-memory');
$transport->send(Envelope::wrap(new DummyMessage('Hello.')));

$this->assertCount(1, $transport->get());
$this->factory->reset();
$this->assertCount(0, $transport->get());
}

public function provideDSN(): array
{
return [
'Supported' => ['in-memory://foo'],
'Unsupported' => ['amqp://bar', false],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ public static function setUpBeforeClass(): void
}
}

public function testFromInvalidDsn()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('The given Redis DSN "redis://" is invalid.');

Connection::fromDsn('redis://');
}

public function testFromDsn()
{
$this->assertEquals(
Expand Down Expand Up @@ -212,16 +204,16 @@ public function testLastErrorGetsCleared()

try {
$connection->add('message', []);
$this->fail(sprintf('Expected that "%s" was thrown.', TransportException::class));
} catch (TransportException $e) {
$this->assertSame('xadd error', $e->getMessage());
}

$this->assertSame('xadd error', $e->getMessage());

try {
$connection->ack('1');
$this->fail(sprintf('Expected that "%s" was thrown.', TransportException::class));
} catch (TransportException $e) {
$this->assertSame('xack error', $e->getMessage());
}

$this->assertSame('xack error', $e->getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Tests\Transport\RedisExt;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Transport\Dsn;
use Symfony\Component\Messenger\Transport\RedisExt\Connection;
use Symfony\Component\Messenger\Transport\RedisExt\RedisTransport;
use Symfony\Component\Messenger\Transport\RedisExt\RedisTransportFactory;
Expand All @@ -22,21 +23,31 @@
*/
class RedisTransportFactoryTest extends TestCase
{
public function testSupportsOnlyRedisTransports()
/**
* @dataProvider supportsProvider
*/
public function testSupports(Dsn $dsn, bool $supports): void
{
$factory = new RedisTransportFactory();

$this->assertTrue($factory->supports('redis://localhost', []));
$this->assertFalse($factory->supports('sqs://localhost', []));
$this->assertFalse($factory->supports('invalid-dsn', []));
$this->assertSame($supports, $factory->supports($dsn));
}

public function testCreateTransport()
public function supportsProvider(): iterable
{
yield [Dsn::fromString('redis://localhost'), true];

yield [Dsn::fromString('foo://localhost'), false];
}

public function testCreate(): void
{
$serializer = $this->createMock(SerializerInterface::class);

$dsn = Dsn::fromString('redis://localhost', ['foo' => 'bar']);
$expectedTransport = new RedisTransport(Connection::fromDsnObject($dsn), $serializer);
$factory = new RedisTransportFactory();
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();
$expectedTransport = new RedisTransport(Connection::fromDsn('redis://localhost', ['foo' => 'bar']), $serializer);

$this->assertEquals($expectedTransport, $factory->createTransport('redis://localhost', ['foo' => 'bar'], $serializer));
$this->assertEquals($expectedTransport, $factory->createTransport($dsn, $serializer, 'redis'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,44 @@
* file that was distributed with this source code.
*/

namespace Symfony\Component\Messenger\Tests\Transport\AmqpExt;
namespace Symfony\Component\Messenger\Tests\Transport\Sync;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Transport\Dsn;
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
use Symfony\Component\Messenger\Transport\Sync\SyncTransport;
use Symfony\Component\Messenger\Transport\Sync\SyncTransportFactory;

class SyncTransportFactoryTest extends TestCase
{
public function testCreateTransport()
/**
* @dataProvider supportsProvider
*/
public function testSupports(Dsn $dsn, bool $supports): void
{
$bus = $this->createMock(MessageBusInterface::class);
$factory = new SyncTransportFactory($bus);

$this->assertSame($supports, $factory->supports($dsn));
}

public function supportsProvider(): iterable
{
yield [Dsn::fromString('sync://'), true];

yield [Dsn::fromString('foo://localhost'), false];
}

public function testCreate(): void
{
$serializer = $this->createMock(SerializerInterface::class);
$bus = $this->createMock(MessageBusInterface::class);

$dsn = Dsn::fromString('sync://');
$expectedTransport = new SyncTransport($bus);
$factory = new SyncTransportFactory($bus);
$transport = $factory->createTransport('sync://', [], $serializer);
$this->assertInstanceOf(SyncTransport::class, $transport);

$this->assertEquals($expectedTransport, $factory->createTransport($dsn, $serializer, 'sync'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/

namespace Symfony\Component\Messenger\Tests\Transport\AmqpExt;
namespace Symfony\Component\Messenger\Tests\Transport\Sync;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
Expand Down
Loading