Skip to content

Share the DNS timeout budget across deliverability lookups - #178

Open
ryanduguid wants to merge 1 commit into
JoshData:mainfrom
ryanduguid:fix-shared-dns-timeout-budget
Open

ryanduguid wants to merge 1 commit into
JoshData:mainfrom
ryanduguid:fix-shared-dns-timeout-budget

Conversation

@ryanduguid

@ryanduguid ryanduguid commented Oct 8, 2026 •

Copy link
Copy Markdown

Summary

Apply timeout to all DNS lookups for one email address, as requested in #101. Currently, each fallback lookup can use the full timeout again. For example:

timeout = 10 seconds
MX lookup takes 9 seconds and finds no records
next lookup gets 1 second, instead of another 10

Compute a deadline with time.monotonic() and pass the remaining time to each MX, A, AAAA or TXT lookup using dnspython's lifetime argument. When a resolver is supplied, its lifetime provides the initial timeout. Cached answers can still be returned after the time runs out. Resolver backoff and processing can make the total elapsed time exceed the timeout.

Evidence

  • The deliverability tests produce 13 failures and 16 passes on the original code. The revised code passes all 336 offline tests on Linux Python 3.10 through 3.14 and Windows Python 3.14. Typing and lint also pass.
  • Tests check the time passed to successive lookups, repeated validations, cached answers after expiry, resolver subclasses and timeout results after a fallback lookup succeeds.

Risk

Custom resolve overrides must accept the lifetime keyword argument. Overrides accepting only a domain and record type will fail. The code also stops changing the process-wide default resolver's lifetime. These compatibility changes need maintainer review.

Unverified

Live DNS tests were not run, and neither was the full suite with dnspython 2.0.0, because the test fixture needs its missing CacheKey type (focused cache and resolver checks passed on that version). Hard cancellation, concurrent changes to the resolver, macOS and hosted CI are unverified.

@JoshData

JoshData commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Much of the PR description is gibberish to me. I don't have time to try to guess what it could mean.

@ryanduguid

Copy link
Copy Markdown
Author

I've rewritten the description in plainer terms. At the moment timeout applies to each DNS lookup separately, so when the MX lookup finds nothing, each fallback lookup can use the full timeout again. This change makes timeout the total for all lookups on one address.

Two compatibility points for you to weigh: a custom resolve override now has to accept a lifetime keyword argument, and the code no longer changes the default resolver's lifetime for the whole process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants