Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a8c32a

Browse files
committed
Replace receiver's generators by handler
1 parent 2355eb4 commit 8a8c32a

File tree

13 files changed

+161
-121
lines changed

13 files changed

+161
-121
lines changed

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ public function testMessengerValidationDisabled()
543543
$container = $this->createContainerFromFile('messenger_validation');
544544
$this->assertFalse($container->hasDefinition('messenger.middleware.validator'));
545545
}
546-
546+
547547
public function testMessengerAdapter()
548548
{
549549
$container = $this->createContainerFromFile('messenger_adapter');

src/Symfony/Component/Messenger/Adapter/PhpAmqp/AmqpReceiver.php

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,26 @@ public function __construct(DecoderInterface $messageDecoder, Connection $connec
3535
/**
3636
* {@inheritdoc}
3737
*/
38-
public function receive(): iterable
38+
public function receive(callable $handler): void
3939
{
40-
$this->shouldStop = false;
41-
4240
while (!$this->shouldStop) {
43-
if (null === $message = $this->connection->waitAndGet()) {
41+
$message = $this->connection->get();
42+
if (null === $message) {
43+
$handler(null);
44+
45+
usleep($this->connection->getConnectionCredentials()['loop_sleep'] ?? 200000);
46+
if (function_exists('pcntl_signal_dispatch')) {
47+
pcntl_signal_dispatch();
48+
}
49+
4450
continue;
4551
}
4652

4753
try {
48-
yield $this->messageDecoder->decode(array(
54+
$handler($this->messageDecoder->decode(array(
4955
'body' => $message->getBody(),
5056
'headers' => $message->getHeaders(),
51-
));
57+
)));
5258

5359
$this->connection->ack($message);
5460
} catch (RejectMessageExceptionInterface $e) {
@@ -60,6 +66,10 @@ public function receive(): iterable
6066

6167
throw $e;
6268
}
69+
70+
if (function_exists('pcntl_signal_dispatch')) {
71+
pcntl_signal_dispatch();
72+
}
6373
}
6474
}
6575

src/Symfony/Component/Messenger/Adapter/PhpAmqp/Connection.php

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,32 +107,28 @@ public function publish(string $body, array $headers = array())
107107
*
108108
* @throws \AMQPException
109109
*/
110-
public function waitAndGet(): ?\AMQPEnvelope
110+
public function get(): ?\AMQPEnvelope
111111
{
112112
if ($this->debug) {
113113
$this->setup();
114114
}
115115

116-
$message = null;
117-
118116
try {
119-
$this->queue()->consume(function (\AMQPEnvelope $envelope) use (&$message): bool {
120-
$message = $envelope;
121-
122-
return false;
123-
});
117+
if (false !== $message = $this->queue()->get()) {
118+
return $message;
119+
}
124120
} catch (\AMQPQueueException $e) {
125121
if (404 === $e->getCode()) {
126122
// If we get a 404 for the queue, it means we need to setup the exchange & queue.
127123
$this->setup();
128124

129-
return $this->waitAndGet();
125+
return $this->get();
126+
} else {
127+
throw $e;
130128
}
131-
132-
throw $e;
133129
}
134130

135-
return $message;
131+
return null;
136132
}
137133

138134
public function ack(\AMQPEnvelope $message)
@@ -162,7 +158,7 @@ public function setup()
162158
$this->queue()->bind($this->exchange()->getName(), $this->queueConfiguration['routing_key'] ?? null);
163159
}
164160

165-
private function channel(): \AMQPChannel
161+
public function channel(): \AMQPChannel
166162
{
167163
if (null === $this->amqpChannel) {
168164
$connection = $this->amqpFactory->createConnection($this->connectionCredentials);
@@ -178,7 +174,7 @@ private function channel(): \AMQPChannel
178174
return $this->amqpChannel;
179175
}
180176

181-
private function queue(): \AMQPQueue
177+
public function queue(): \AMQPQueue
182178
{
183179
if (null === $this->amqpQueue) {
184180
$this->amqpQueue = $this->amqpFactory->createQueue($this->channel());
@@ -193,7 +189,7 @@ private function queue(): \AMQPQueue
193189
return $this->amqpQueue;
194190
}
195191

196-
private function exchange(): \AMQPExchange
192+
public function exchange(): \AMQPExchange
197193
{
198194
if (null === $this->amqpExchange) {
199195
$this->amqpExchange = $this->amqpFactory->createExchange($this->channel());
@@ -209,6 +205,11 @@ private function exchange(): \AMQPExchange
209205
return $this->amqpExchange;
210206
}
211207

208+
public function getConnectionCredentials(): array
209+
{
210+
return $this->connectionCredentials;
211+
}
212+
212213
private function clear()
213214
{
214215
$this->amqpChannel = null;

src/Symfony/Component/Messenger/Asynchronous/Transport/WrapIntoReceivedMessage.php

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,15 @@ public function __construct(ReceiverInterface $decoratedConsumer)
2525
$this->decoratedReceiver = $decoratedConsumer;
2626
}
2727

28-
public function receive(): iterable
28+
public function receive(callable $handler): void
2929
{
30-
$iterator = $this->decoratedReceiver->receive();
31-
32-
foreach ($iterator as $message) {
33-
try {
34-
yield new ReceivedMessage($message);
35-
} catch (\Throwable $e) {
36-
if (!$iterator instanceof \Generator) {
37-
throw $e;
38-
}
39-
40-
$iterator->throw($e);
30+
$this->decoratedReceiver->receive(function ($message) use ($handler) {
31+
if (null !== $message) {
32+
$message = new ReceivedMessage($message);
4133
}
42-
}
34+
35+
$handler($message);
36+
});
4337
}
4438

4539
public function stop(): void

src/Symfony/Component/Messenger/Tests/Adapter/PhpAmqp/AmqpReceiverTest.php

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*/
2727
class AmqpReceiverTest extends TestCase
2828
{
29-
public function testItYieldsTheDecodedMessageAndAcknowledgeIt()
29+
public function testItSendTheDecodedMessageToTheHandlerAndAcknowledgeIt()
3030
{
3131
$serializer = new Serializer(
3232
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
@@ -39,19 +39,15 @@ public function testItYieldsTheDecodedMessageAndAcknowledgeIt()
3939
));
4040

4141
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
42-
$connection->method('waitAndGet')->willReturn($envelope);
42+
$connection->method('get')->willReturn($envelope);
43+
4344
$connection->expects($this->once())->method('ack')->with($envelope);
4445

4546
$receiver = new AmqpReceiver($serializer, $connection);
46-
/** @var \Generator $generator */
47-
$generator = $receiver->receive();
48-
49-
foreach ($generator as $message) {
47+
$receiver->receive(function ($message) use ($receiver) {
5048
$this->assertEquals(new DummyMessage('Hi'), $message);
51-
52-
// Stop the generator
5349
$receiver->stop();
54-
}
50+
});
5551
}
5652

5753
/**
@@ -70,17 +66,14 @@ public function testItNonAcknowledgeTheMessageIfAnExceptionHappened()
7066
));
7167

7268
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
73-
$connection->method('waitAndGet')->willReturn($envelope);
69+
$connection->method('get')->willReturn($envelope);
70+
7471
$connection->expects($this->once())->method('nack')->with($envelope);
7572

7673
$receiver = new AmqpReceiver($serializer, $connection);
77-
78-
/** @var \Generator $generator */
79-
$generator = $receiver->receive();
80-
81-
foreach ($generator as $message) {
82-
$generator->throw(new InterruptException('Well...'));
83-
}
74+
$receiver->receive(function () {
75+
throw new InterruptException('Well...');
76+
});
8477
}
8578

8679
/**
@@ -99,17 +92,13 @@ public function testItRejectsTheMessageIfTheExceptionIsARejectMessageExceptionIn
9992
));
10093

10194
$connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
102-
$connection->method('waitAndGet')->willReturn($envelope);
95+
$connection->method('get')->willReturn($envelope);
10396
$connection->expects($this->once())->method('reject')->with($envelope);
10497

10598
$receiver = new AmqpReceiver($serializer, $connection);
106-
107-
/** @var \Generator $generator */
108-
$generator = $receiver->receive();
109-
110-
foreach ($generator as $message) {
111-
$generator->throw(new WillNeverWorkException('Well...'));
112-
}
99+
$receiver->receive(function () {
100+
throw new WillNeverWorkException('Well...');
101+
});
113102
}
114103
}
115104

src/Symfony/Component/Messenger/Tests/Adapter/PhpAmqp/Fixtures/long_receiver.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@
77
}
88

99
if (!file_exists($autoload)) {
10-
bailout('You should run "composer install --dev" in the component before running this script.');
10+
exit('You should run "composer install --dev" in the component before running this script.');
1111
}
1212

1313
require_once $autoload;
1414

1515
use Symfony\Component\Messenger\Adapter\PhpAmqp\AmqpReceiver;
1616
use Symfony\Component\Messenger\Adapter\PhpAmqp\AmqpSender;
1717
use Symfony\Component\Messenger\Adapter\PhpAmqp\Connection;
18+
use Symfony\Component\Messenger\MessageBusInterface;
1819
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
20+
use Symfony\Component\Messenger\Worker;
1921
use Symfony\Component\Serializer as SerializerComponent;
2022
use Symfony\Component\Serializer\Encoder\JsonEncoder;
2123
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
@@ -25,13 +27,17 @@
2527
);
2628

2729
$connection = Connection::fromDsn(getenv('DSN'));
28-
2930
$sender = new AmqpSender($serializer, $connection);
3031
$receiver = new AmqpReceiver($serializer, $connection);
3132

33+
$worker = new Worker($receiver, new class() implements MessageBusInterface {
34+
public function dispatch($message)
35+
{
36+
echo 'Get message: '.get_class($message)."\n";
37+
sleep(30);
38+
echo "Done.\n";
39+
}
40+
});
41+
3242
echo "Receiving messages...\n";
33-
foreach ($receiver->receive() as $message) {
34-
echo 'Get message: '.get_class($message)."\n";
35-
sleep(10);
36-
echo "Done.\n";
37-
}
43+
$worker->run();

src/Symfony/Component/Messenger/Tests/Adapter/PhpAmqp/PhpAmqpIntegrationTest.php

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Messenger\Adapter\PhpAmqp\AmqpSender;
1717
use Symfony\Component\Messenger\Adapter\PhpAmqp\Connection;
1818
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
19+
use Symfony\Component\Messenger\Transport\Enhancers\MaximumCountReceiver;
1920
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
2021
use Symfony\Component\Process\PhpProcess;
2122
use Symfony\Component\Process\Process;
@@ -45,26 +46,37 @@ public function testItSendsAndReceivesMessages()
4546

4647
$connection = Connection::fromDsn(getenv('MESSENGER_AMQP_DSN'));
4748
$connection->setup();
49+
$connection->queue()->purge();
4850

4951
$sender = new AmqpSender($serializer, $connection);
5052
$receiver = new AmqpReceiver($serializer, $connection);
5153

52-
$sender->send(new DummyMessage('First'));
53-
$sender->send(new DummyMessage('Second'));
54+
$sender->send($firstMessage = new DummyMessage('First'));
55+
$sender->send($secondMessage = new DummyMessage('Second'));
5456

5557
$receivedMessages = 0;
56-
$generator = $receiver->receive();
57-
foreach ($generator as $message) {
58+
$generator = $receiver->receive(function ($message) use ($receiver, &$receivedMessages, $firstMessage, $secondMessage) {
59+
$this->assertEquals(0 == $receivedMessages ? $firstMessage : $secondMessage, $message);
60+
5861
if (2 == ++$receivedMessages) {
59-
$generator->send(AmqpReceiver::STOP);
62+
$receiver->stop();
6063
}
61-
}
62-
63-
$this->assertEquals(2, $receivedMessages);
64+
});
6465
}
6566

6667
public function testItReceivesSignals()
6768
{
69+
$serializer = new Serializer(
70+
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
71+
);
72+
73+
$connection = Connection::fromDsn(getenv('MESSENGER_AMQP_DSN'));
74+
$connection->setup();
75+
$connection->queue()->purge();
76+
77+
$sender = new AmqpSender($serializer, $connection);
78+
$sender->send(new DummyMessage('Hello'));
79+
6880
$amqpReadTimeout = 30;
6981
$dsn = getenv('MESSENGER_AMQP_DSN').'?read_timeout='.$amqpReadTimeout;
7082
$process = new PhpProcess(file_get_contents(__DIR__.'/Fixtures/long_receiver.php'), null, array(
@@ -75,10 +87,9 @@ public function testItReceivesSignals()
7587
$process->start();
7688

7789
$this->waitForOutput($process, $expectedOutput = "Receiving messages...\n");
78-
$this->assertEquals("Receiving messages...\n", $process->getOutput());
7990

8091
$signalTime = microtime(true);
81-
$timedOutTime = time() + 60;
92+
$timedOutTime = time() + 10;
8293

8394
$process->signal(15);
8495

@@ -88,14 +99,35 @@ public function testItReceivesSignals()
8899

89100
$this->assertFalse($process->isRunning());
90101
$this->assertLessThan($amqpReadTimeout, microtime(true) - $signalTime);
102+
$this->assertEquals($expectedOutput."Get message: Symfony\Component\Messenger\Asynchronous\Transport\ReceivedMessage\nDone.\n", $process->getOutput());
103+
}
104+
105+
/**
106+
* @runInSeparateProcess
107+
*/
108+
public function testItSupportsTimeoutAndTicksNullMessagesToTheHandler()
109+
{
110+
$serializer = new Serializer(
111+
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
112+
);
113+
114+
$connection = Connection::fromDsn(getenv('MESSENGER_AMQP_DSN'), array('read_timeout' => '1'));
115+
$connection->setup();
116+
$connection->queue()->purge();
117+
118+
$sender = new AmqpSender($serializer, $connection);
119+
$receiver = new MaximumCountReceiver(new AmqpReceiver($serializer, $connection), 2);
120+
$receiver->receive(function ($message) {
121+
$this->assertNull($message);
122+
});
91123
}
92124

93125
private function waitForOutput(Process $process, string $output, $timeoutInSeconds = 10)
94126
{
95127
$timedOutTime = time() + $timeoutInSeconds;
96128

97129
while (time() < $timedOutTime) {
98-
if ($process->getOutput() == $output) {
130+
if (0 === strpos($process->getOutput(), $output)) {
99131
return;
100132
}
101133

src/Symfony/Component/Messenger/Tests/DependencyInjection/MessengerPassTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ public function __invoke(DummyMessage $message): void
214214

215215
class DummyReceiver implements ReceiverInterface
216216
{
217-
public function receive(): iterable
217+
public function receive(callable $handler): void
218218
{
219219
for ($i = 0; $i < 3; ++$i) {
220-
yield new DummyMessage("Dummy $i");
220+
$handler(new DummyMessage("Dummy $i"));
221221
}
222222
}
223223

0 commit comments

Comments
 (0)