8000 Merge branch '6.3' into 6.4 · symfony/symfony@d65c4af · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d65c4af

Browse files
Merge branch '6.3' into 6.4
* 6.3: fix #51235 - fix the order of merging of serializationContext and self::CONTEXT_DENORMALIZE [HttpClient] Fix Static Code Analyzer issue with JsonMockResponse [Messenger] Fix exiting `FailedMessagesRetryCommand` [Serializer] Fix reindex normalizedData array in AbstractObjectNormalizer::denormalize() [Validator] Fix `File::$extensions`’ PHPDoc [Mime] Fix email (de)serialization issues [Serializer] Fix parsing XML root node attributes fix parsing of payload timestamp to DateTimeImmutable Fix routing to multiple fallback transports Fix missing stamps in delayed message handling [DoctrineBridge] Ignore invalid stores in `LockStoreSchemaListener` raised by `StoreFactory`
2 parents 3850658 + 10c8260 commit d65c4af

File tree

34 files changed

+305
-50
lines changed

34 files changed

+305
-50
lines changed

src/Symfony/Bridge/Doctrine/SchemaListener/LockStoreSchemaListener.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Doctrine\SchemaListener;
1313

1414
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
15+
use Symfony\Component\Lock\Exception\InvalidArgumentException;
1516
use Symfony\Component\Lock\PersistingStoreInterface;
1617
use Symfony\Component\Lock\Store\DoctrineDbalStore;
1718

@@ -28,12 +29,20 @@ public function postGenerateSchema(GenerateSchemaEventArgs $event): void
2829
{
2930
$connection = $event->getEntityManager()->getConnection();
3031

31-
foreach ($this->stores as $store) {
32-
if (!$store instanceof DoctrineDbalStore) {
33-
continue;
32+
$storesIterator = new \ArrayIterator($this->stores);
33+
while ($storesIterator->valid()) {
34+
try {
35+
$store = $storesIterator->current();
36+
if (!$store instanceof DoctrineDbalStore) {
37+
continue;
38+
}
39+
40+
$store->configureSchema($event->getSchema(), $this->getIsSameDatabaseChecker($connection));
41+
} catch (InvalidArgumentException) {
42+
// no-op
3443
}
3544

36-
$store->configureSchema($event->getSchema(), $this->getIsSameDatabaseChecker($connection));
45+
$storesIterator->next();
3746
}
3847
}
3948
}

src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
1818
use PHPUnit\Framework\TestCase;
1919
use Symfony\Bridge\Doctrine\SchemaListener\LockStoreSchemaListener;
20+
use Symfony\Component\Lock\Exception\InvalidArgumentException;
2021
use Symfony\Component\Lock\Store\DoctrineDbalStore;
2122

2223
class LockStoreSchemaListenerTest extends TestCase
@@ -39,4 +40,20 @@ public function testPostGenerateSchemaLockPdo()
3940
$subscriber = new LockStoreSchemaListener([$lockStore]);
4041
$subscriber->postGenerateSchema($event);
4142
}
43+
44+
public function testPostGenerateSchemaWithInvalidLockStore()
45+
{
46+
$entityManager = $this->createMock(EntityManagerInterface::class);
47+
$entityManager->expects($this->once())
48+
->method('getConnection')
49+
->willReturn($this->createMock(Connection::class));
50+
$event = new GenerateSchemaEventArgs($entityManager, new Schema());
51+
52+
$subscriber = new LockStoreSchemaListener((static function (): \Generator {
53+
yield $this->createMock(DoctrineDbalStore::class);
54+
55+
throw new InvalidArgumentException('Unsupported Connection');
56+
})());
57+
$subscriber->postGenerateSchema($event);
58+
}
4259
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,6 +2122,16 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
21222122
$container->getDefinition('messenger.transport.beanstalkd.factory')->addTag('messenger.transport_factory');
21232123
}
21242124

2125+
if ($config['stop_worker_on_signals'] && $this->hasConsole()) {
2126+
$container->getDefinition('console.command.messenger_consume_messages')
2127+
->replaceArgument(8, $config['stop_worker_on_signals']);
2128+
$container->getDefinition('console.command.messenger_failed_messages_retry')
2129+
->replaceArgument(6, $config['stop_worker_on_signals']);
2130+
}
2131+
2132+
if ($this->hasConsole() && $container->hasDefinition('messenger.listener.stop_worker_signals_listener')) {
2133+
$container->getDefinition('messenger.listener.stop_worker_signals_listener')->clearTag('kernel.event_subscriber');
2134+
}
21252135
if (!class_exists(StopWorkerOnSignalsListener::class)) {
21262136
$container->removeDefinition('messenger.listener.stop_worker_signals_listener');
21272137
} elseif ($config['stop_worker_on_signals']) {

src/Symfony/Bundle/FrameworkBundle/Resources/config/console.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@
165165
service('messenger.listener.reset_services')->nullOnInvalid(),
166166
[], // Bus names
167167
service('messenger.rate_limiter_locator')->nullOnInvalid(),
168+
null,
168169
])
169170
->tag('console.command')
170171
->tag('monolog.logger', ['channel' => 'messenger'])
@@ -196,6 +197,7 @@
196197
service('event_dispatcher'),
197198
service('logger')->nullOnInvalid(),
198199
service('messenger.transport.native_php_serializer')->nullOnInvalid(),
200+
null,
199201
])
200202
->tag('console.command')
201203
->tag('monolog.logger', ['channel' => 'messenger'])

src/Symfony/Component/HttpClient/Response/JsonMockResponse.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
class JsonMockResponse extends MockResponse
1717
{
18+
/**
19+
* @param mixed $body Any value that `json_encode()` can serialize
20+
*/
1821
public function __construct(mixed $body = [], array $info = [])
1922
{
2023
try {

src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private function mapQueryString(Request $request, string $type, MapQueryString $
161161
return null;
162162
}
163163

164-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->serializationContext);
164+
return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
165165
}
166166

167167
private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object
@@ -175,7 +175,7 @@ private function mapRequestPayload(Request $request, string $type, MapRequestPay
175175
}
176176

177177
if ($data = $request->request->all()) {
178-
return $this->serializer->denormalize($data, $type, null, self::CONTEXT_DENORMALIZE + $attribute->serializationContext);
178+
return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE);
179179
}
180180

181181
if ('' === $data = $request->getContent()) {

src/Symfony/Component/Mailer/Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public function convert(array $payload): AbstractMailerEvent
5050
};
5151
$event = new MailerEngagementEvent($name, $payload['id'], $payload);
5252
}
53-
if (!$date = \DateTimeImmutable::createFromFormat('U.u', $payload['timestamp'])) {
54-
throw new ParseException(sprintf('Invalid date "%s".', $payload['timestamp']));
53+
if (!$date = \DateTimeImmutable::createFromFormat('U.u', sprintf('%.6F', $payload['timestamp']))) {
54+
throw new ParseException(sprintf('Invalid date "%s".', sprintf('%.6F', $payload['timestamp'])));
5555
}
5656
$event->setDate($date);
5757
$event->setRecipientEmail($payload['recipient']);

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676'));
1010

1111
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"event-data": {
88
"id": "CPgfbmQMTCKtHW6uIWtuVe",
9-
"timestamp": 1521472262.908181,
9+
"timestamp": 1521472262.000002,
1010
"log-level": "info",
1111
"event": "delivered",
1212
"delivery-status": {

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFro 10000 mFormat('U.u', 1521472262.908181));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521472262.000002'));
1010
$wh->setReason('OK');
1111

1212
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676'));
1010

1111
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/permanent_failure.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233195.375624));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233195.375624'));
1010
$wh->setReason('No Such User Here');
1111

1212
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233123.501324));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233123.501324'));
1010

1111
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/suppression_failure.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233195.375624));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233195.375624'));
1010
$wh->setReason('Not delivering to previously bounced address');
1111

1212
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/temporary_failure.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521472262.908181));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521472262.908181'));
1010
$wh->setReason("4.2.2 The email account that you tried to reach is over quota. Please direct\n4.2.2 the recipient to\n4.2.2 https://support.example.com/mail/?p=422");
1111

1212
return $wh;

src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
$wh->setRecipientEmail('alice@example.com');
77
$wh->setTags(['my_tag_1', 'my_tag_2']);
88
$wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']);
9-
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676));
9+
$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676'));
1010

1111
return $wh;

src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php

Lines changed: 31 additions & 4 deletions
235
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Psr\Log\LoggerInterface;
1616
use Symfony\Component\Console\Attribute\AsCommand;
1717
use Symfony\Component\Console\Command\Command;
18+
use Symfony\Component\Console\Command\SignalableCommandInterface;
1819
use Symfony\Component\Console\Completion\CompletionInput;
1920
use Symfony\Component\Console\Completion\CompletionSuggestions;
2021
use Symfony\Component\Console\Exception\InvalidOptionException;
@@ -39,7 +40,7 @@
3940
* @author Samuel Roze <samuel.roze@gmail.com>
4041
*/
4142
#[AsCommand(name: 'messenger:consume', description: 'Consume messages')]
42-
class ConsumeMessagesCommand extends Command
43+
class ConsumeMessagesCommand extends Command implements SignalableCommandInterface
4344
{
4445
private RoutableMessageBus $routableBus;
4546
private ContainerInterface $receiverLocator;
@@ -49,8 +50,10 @@ class ConsumeMessagesCommand extends Command
4950
private ?ResetServicesListener $resetServicesListener;
5051
private array $busIds;
5152
private ?ContainerInterface $rateLimiterLocator;
53+
private ?array $signals;
54+
private ?Worker $worker = null;
5255

53-
public function __construct(RoutableMessageBus $routableBus, ContainerInterface $receiverLocator, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger = null, array $receiverNames = [], ResetServicesListener $resetServicesListener = null, array $busIds = [], ContainerInterface $rateLimiterLocator = null)
56+
public function __construct(RoutableMessageBus $routableBus, ContainerInterface $receiverLocator, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger = null, array $receiverNames = [], ResetServicesListener $resetServicesListener = null, array $busIds = [], ContainerInterface $rateLimiterLocator = null, array $signals = null)
5457
{
5558
$this->routableBus = $routableBus;
5659
$this->receiverLocator = $receiverLocator;
@@ -60,6 +63,7 @@ public function __construct(RoutableMessageBus $routableBus, ContainerInterface
6063
$this->resetServicesListener = $resetServicesListener;
6164
$this->busIds = $busIds;
6265
$this->rateLimiterLocator = $rateLimiterLocator;
66+
$this->signals = $signals;
6367

6468
parent::__construct();
6569
}
@@ -222,14 +226,19 @@ protected function execute(InputInterface $input, OutputInterface $output): int
222226

223227
$bus = $input->getOption('bus') ? $this->routableBus->getMessageBus($input->getOption('bus')) : $this->routableBus;
224228

225-
$worker = new Worker($receivers, $bus, $this->eventDispatcher, $this->logger, $rateLimiters);
229+
$this->worker = new Worker($receivers, $bus, $this->eventDispatcher, $this->logger, $rateLimiters);
226230
$options = [
227231
'sleep' => $input->getOption('sleep') * 1000000,
228232
];
229233
if ($queues = $input->getOption('queues')) {
230234
$options['queues'] = $queues;
231
}
232-
$worker->run($options);
236+
237+
try {
238+
$this->worker->run($options);
239+
} finally {
240+
$this->worker = null;
241+
}
233242

234243
return 0;
235244
}
@@ -247,6 +256,24 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti
247256
}
248257
}
249258

259+
public function getSubscribedSignals(): array
260+
{
261+
return $this->signals ?? [\SIGTERM, \SIGINT];
262+
}
263+
264+
public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
265+
{
266+
if (!$this->worker) {
267+
return false;
268+
}
269+
270+
$this->logger?->info('Received signal {signal}.', ['signal' => $signal, 'transport_names' => $this->worker->getMetadata()->getTransportNames()]);
271+
272+
$this->worker->stop();
273+
274+
return 0;
275+
}
276+
250277
private function convertToBytes(string $memoryLimit): int
251278
{
252279
$memoryLimit = strtolower($memoryLimit);

src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Log\LoggerInterface;
1515
use Symfony\Component\Console\Attribute\AsCommand;
16+
use Symfony\Component\Console\Command\SignalableCommandInterface;
1617
use Symfony\Component\Console\Exception\RuntimeException;
1718
use Symfony\Component\Console\Input\InputArgument;
1819
use Symfony\Component\Console\Input\InputInterface;
@@ -36,17 +37,20 @@
3637
* @author Ryan Weaver <ryan@symfonycasts.com>
3738
*/
3839
#[AsCommand(name: 'messenger:failed:retry', description: 'Retry one or more messages from the failure transport')]
39-
class FailedMessagesRetryCommand extends AbstractFailedMessagesCommand
40+
class FailedMessagesRetryCommand extends AbstractFailedMessagesCommand implements SignalableCommandInterface
4041
{
4142
private EventDispatcherInterface $eventDispatcher;
4243
private MessageBusInterface $messageBus;
4344
private ?LoggerInterface $logger;
45+
private ?array $signals;
46+
private ?Worker $worker = null;
4447

45-
public function __construct(?string $globalReceiverName, ServiceProviderInterface $failureTransports, MessageBusInterface $messageBus, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger = null, PhpSerializer $phpSerializer = null)
48+
public function __construct(?string $globalReceiverName, ServiceProviderInterface $failureTransports, MessageBusInterface $messageBus, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger = null, PhpSerializer $phpSerializer = null, array $signals = null)
4649
{
4750
$this->eventDispatcher = $eventDispatcher;
4851
$this->messageBus = $messageBus;
4952
$this->logger = $logger;
53+
$this->signals = $signals;
5054

5155
parent::__construct($globalReceiverName, $failureTransports, $phpSerializer);
5256
}
@@ -123,6 +127,24 @@ protected function execute(InputInterface $input, OutputInterface $output): int
123127
return 0;
124128
}
125129

130+
public function getSubscribedSignals(): array
131+
{
132+
return $this->signals ?? [\SIGTERM, \SIGINT];
133+
}
134+
135+
public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
136+
{
137+
if (!$this->worker) {
138+
return false;
139+
}
140+
141+
$this->logger?->info('Received signal {signal}.', ['signal' => $signal, 'transport_names' => $this->worker->getMetadata()->getTransportNames()]);
142+
143+
$this->worker->stop();
144+
145+
return 0;
146+
}
147+
126148
private function runInteractive(string $failureTransportName, SymfonyStyle $io, bool $shouldForce): void
127149
{
128150
$receiver = $this->failureTransports->get($failureTransportName);
@@ -187,16 +209,17 @@ private function runWorker(string $failureTransportName, ReceiverInterface $rece
187209
};
188210
$this->eventDispatcher->addListener(WorkerMessageReceivedEvent::class, $listener);
189211

190-
$worker = new Worker(
212+
$this->worker = new Worker(
191213
[$failureTransportName => $receiver],
192214
$this->messageBus,
193215
$this->eventDispatcher,
194216
$this->logger
195217
);
196218

197219
try {
198-
$worker->run();
220+
$this->worker->run();
199221
} finally {
222+
$this->worker = null;
200223
$this->eventDispatcher->removeListener(WorkerMessageReceivedEvent::class, $listener);
201224
}
202225

0 commit comments

Comments
 (0)
0