Skip to content

[Messenger] Refactoring failure to FailedMessage & allowing for requeue #31397

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

Conversation

weaverryan
Copy link
Member

@weaverryan weaverryan commented May 6, 2019

Q A
Branch? master
Bug fix? partially
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR symfony/symfony-docs#11236

There are a few things going on:

  1. Purely because I think it's a better implementation, I've created a new FailedMessage class and the failed messages go inside of this. This message is then routed to the failure transport.

  2. This adds the ability to "requeue" messages instead of retrying them immediately, based on feedback from Twitter.

  3. This should fix an undiscovered bug: if you "retry" and use [Messenger] Allows to register handlers on a specific transport #30958, previously, retrying would not execute the correct handlers because it would appear the message was being received from the "failure" transport, not the original transport, which has configuration to execute specific handlers.

Cheers!

@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch from 9bd0543 to 86975f5 Compare May 6, 2019 16:28
@weaverryan weaverryan added this to the 4.3 milestone May 6, 2019
@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch from 86975f5 to 4c83e1c Compare May 6, 2019 17:21
@weaverryan weaverryan requested a review from sroze as a code owner May 6, 2019 17:21
@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch from 4c83e1c to 6b19228 Compare May 6, 2019 17:22
Copy link
Member Author

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much of this PR is just a revert of part of #30970. I've highlighted those to help review.

@@ -1768,29 +1788,11 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder

$container->getDefinition('messenger.senders_locator')
->replaceArgument(0, $messageToSendersMapping)
->replaceArgument(1, ServiceLocatorTagPass::register($container, $senderReferences))
->replaceArgument(2, $messagesToSendAndHandle)
->replaceArgument(1, $messagesToSendAndHandle)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the logic from $senders = [] is a revert of #30970

if (!isset($senderAliases[$failureTransport])) {
$senderAliases[$failureTransport] = $failureTransport;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section was mostly just moved from below. The $messagesToSendersMapping is the new part: it adds routing for the FailedMessage class to whatever the failure transport is.


<tag name="console.command" command="messenger:failed:remove" />
</service>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into a new file so we can conditionally import that file (instead importing, then removing if the failure transport is disabled).

@@ -9,8 +9,7 @@

<!-- Asynchronous -->
<service id="messenger.senders_locator" class="Symfony\Component\Messenger\Transport\Sender\SendersLocator">
<argument type="collection" /> <!-- Per message senders map -->
<argument /> <!-- senders locator -->
<argument type="collection" /> <!-- Per message sender iterators -->
<argument type="collection" /> <!-- Messages to send and handle -->
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

$this->assertEquals(new Reference('audit'), $sendersLocator->getArgument(0)['audit']->getValues()[0]);
'amqp' => new Reference('messenger.transport.amqp'),
'audit' => new Reference('audit'),
], $sendersMapping[DummyMessage::class]->getValues());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

}

return false;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

});

return new SendersLocator($sendersMap, $container, $sendAndHandle);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whole class is a revert of #30970

$this->assertTrue($stampToRedeliverToSender1->shouldRedeliverToSender('App\Sender1', null));
$this->assertFalse($stampToRedeliverToSender1->shouldRedeliverToSender('App\Sender2', null));
}

public function testGetters()
{
$stamp = new RedeliveryStamp(10, 'sender_alias');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

});

return $container;
$this->assertSame(['dummy' => $sender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a')))));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

}

throw new UnknownSenderException(sprintf('Unknown sender alias "%s".', $alias));
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert of #30970

@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch 4 times, most recently from 8e62086 to d4f483f Compare May 6, 2019 18:54
use Symfony\Component\Messenger\Transport\Sender\SendersLocator;
use Symfony\Component\Messenger\Worker;

class FailureIntegrationTest extends TestCase
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is a bit crazy. There are various layers that interact, and this proves the work together:

  1. The ability to send a message to multiple transports but some handlers are only called on some transports
  2. The failure transport and the requeuing of messages
  3. The failure transport and retrying messages (instead of requeuing) and making sure the correct handlers are still called.

@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch 2 times, most recently from 6020703 to 1b0b49d Compare May 7, 2019 15:26
@Tobion
Copy link
Contributor

Tobion commented May 7, 2019

I like the new implementation. But now that FailedMessage are routed using the standard config, does it not mean that the FailedMessage will also be routed to transports configured by the user using the wildcard, e.g. * => amqp. So the FailedMessage would go to the failure transport as well as amqp. Which will probably fail again and then send the message to both transports, creating an endless loop.

@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch from 1b0b49d to c776abd Compare May 7, 2019 19:11
@weaverryan weaverryan force-pushed the failure-transport-message-requeue branch from c776abd to 3ab3a85 Compare May 7, 2019 19:12
Copy link
Contributor

@sroze sroze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on Slack, I think this approach as multiple downsides:

  1. It doesn't work with * as @Tobion spotted well
  2. It forces the failure transport to only use the PHP serialize serializer (because Symfony Serializer couldn't know how to deserialize the FailedMessage message; especially its inner Envelope)
  3. It forces the entirety of the "system" to only have one "failure transport"

Also, all of this change is trigged by the point 2) of the pull-request description, which, IMHO, could be simply achieved by dispatching the message again (without the ReceivedStamp). I agree that we need to look at 3) which might be a bug though.

@@ -1745,19 +1743,41 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder

$messageToSendersMapping = [];
$messagesToSendAndHandle = [];
if ($config['failure_transport']) {
$failureTransport = $config['failure_transport'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line could be in the if :)

@weaverryan
Copy link
Member Author

After talking with Sam & Nicolas (and @Tobion's feedback), I'm closing this PR. Most of this code was a refactoring, which didn't contain enough objective improvements over the previous implementation.

We can propose requeue for 4.4, as it's a new feature.

And for:

  1. This should fix an undiscovered bug: if you "retry" and use [Messenger] Allows to register handlers on a specific transport #30958, previously, retrying would not execute the correct handlers because it would appear the message was being received from the "failure" transport, not the original transport, which has configuration to execute specific handlers.

I'll attempt to fix this independently in another PR.

@weaverryan weaverryan closed this May 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants