{{ message }}
Repository navigation
fix(mails): give each concurrent send its own kept-alive SMTP session - #13722
Merged
Merged
Conversation
The smtp registry entry was one SMTP adapter with keepAlive on, cached for the life of the worker process. Workers run up to _APP_WORKER_MAX_COROUTINES jobs at once, so concurrent sends wrote into the same socket and desynchronised the session. The entry is now a utopia-php/pools pool of adapters sized to the coroutine count, and the mails and notifications workers borrow one for the length of a send. A project's own SMTP is dialled for one send, so it no longer asks for keepAlive it never uses.
Contributor
✨ Benchmark resultsComparing
Per-scenario breakdown & investigation detailsMetrics below reflect the current branch (after). Δ P95 compares against the base.
Top API waits (after) |
HarshMN2345
approved these changes
Sep 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What does this PR do?
The
smtpregistry entry becomes autopia-php/poolspool ofSMTPadapters, sized to_APP_WORKER_MAX_COROUTINES, and the mails and notifications workers borrow one adapter throughPool::use()for the length of a send. A project's own SMTP config is still dialled per send, now withkeepAlive: false, since that adapter is never held.Why
The entry was one
SMTPadapter withkeepAlive: true, cached for the life of the worker process. Workers run up to_APP_WORKER_MAX_COROUTINESjobs at once, so concurrent sends wrote into the same socket and desynchronised the session. A kept-alive session belongs to one send at a time, and the pool is what enforces that.This is the consumer-side half of utopia-php/monorepo#282, which makes the kept session survive a server-side idle close by probing it before reuse. That fix lands with the next
utopia-php/messagingrelease and needs no further change here; this PR works against the currently released 2.1 as well.Test plan
tests/unit/Platform/Workers/MailsTest.phpandNotificationsTest.phpregister the spy adapter through aPoolon theStackadapter and pass unchanged in behaviour.Related PRs and issues