[Messenger] backport #54167: retry AMQPConnectionException on publish#1
Conversation
Ports the upstream Symfony 5.4/6.4 fix for symfony/symfony#48241 into this 4.4 fork. Wraps Connection::publish() in withConnectionExceptionRetry() which catches \AMQPConnectionException, drops cached channel/queues/exchanges via clear(), and retries up to 3 times with no backoff. Fixes intermittent AMQPS publish failures against AWS AmazonMQ caused by AWS NLB's 350s idle TCP timeout silently killing connections — ext-amqp's isConnected() doesn't detect the dead socket so the next publish surfaces as "Library error: a SSL error occurred". Upstream PR: symfony/symfony#54167 Upstream issue: symfony/symfony#48241
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@CodeRabbit full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
Transport/AmqpExt/Connection.php (1)
464-472: Consider logging retry attempts for observability.Silent retries can make debugging production issues harder. Adding a log entry when retries occur would help operators understand connection instability without examining metrics or traces.
Example (if a logger is available or can be injected):
// Inside the catch block, before clear(): // $this->logger?->warning('AMQP connection exception, retrying ({retries}/{maxRetries})', [...]); $this->clear();This is optional if the goal is strict parity with upstream.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Transport/AmqpExt/Connection.php` around lines 464 - 472, Add an observability log inside the AMQPConnectionException catch in Connection.php so retry attempts are recorded: inside the catch block that handles \AMQPConnectionException for the $callable() invocation, emit a warning (using $this->logger or an injected logger) that includes current $retries and $maxRetries and the exception message/stack before calling $this->clear(), then preserve the existing increment-and-goto retry behavior; reference the catch around $callable(), the $retries/$maxRetries variables, and $this->clear() when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@Transport/AmqpExt/Connection.php`:
- Around line 464-472: Add an observability log inside the
AMQPConnectionException catch in Connection.php so retry attempts are recorded:
inside the catch block that handles \AMQPConnectionException for the $callable()
invocation, emit a warning (using $this->logger or an injected logger) that
includes current $retries and $maxRetries and the exception message/stack before
calling $this->clear(), then preserve the existing increment-and-goto retry
behavior; reference the catch around $callable(), the $retries/$maxRetries
variables, and $this->clear() when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: da2fac32-ab82-4570-ba90-a86f36a6eb3c
📒 Files selected for processing (1)
Transport/AmqpExt/Connection.php
Summary
Backports symfony/symfony#54167 into this 4.4 fork to fix intermittent AMQPS publish failures against AWS AmazonMQ.
Root cause
AWS NLB's 350s idle TCP timeout on TLS listeners silently kills AMQPS connections.
ext-amqp'sisConnected()does not detect the dead socket, so the nextpublish()hits OpenSSL on an RST'd socket and surfaces asLibrary error: a SSL error occurred/stream_socket_enable_crypto()warnings. This is exactly symfony/symfony#48241.Fix
Wraps
Connection::publish()inwithConnectionExceptionRetry():\AMQPConnectionExceptionclear()to drop cached$amqpChannel/$amqpQueues/$amqpExchange/$amqpDelayExchangeclearWhenDisconnected()refactored to delegate to the newclear()helper. Style matches the fork (direct= nullassignment, notunset()).Testing
php -lpassesAmqpExtConnectionRetryTestcovering retry-on-AMQPConnectionException, exhaustion after 3 retries, andclear()semantics (4/4 green)Consumer
sweetspotio/sweetspot-api-platform#4965 will bump its composer pin to this fork HEAD once merged.
Upstream refs
Summary by CodeRabbit