feat: defer AsyncZeroconf construction until first .local lookup#99
feat: defer AsyncZeroconf construction until first .local lookup#99aiolibsbot wants to merge 2 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #99 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 9 9
Lines 655 687 +32
Branches 25 26 +1
=========================================
+ Hits 655 687 +32 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@aiolibsbot rr |
PR Review — feat: defer AsyncZeroconf construction until first .local lookupThe lazy-construction logic is correct and complete: 🟡 Important1. Same incorrect 'listener threads' claim as the CHANGES file (`src/aiohttp_asyncmdnsresolver/_impl.py`, L88)@bdraco flagged this exact wording on # When this resolver owns its zeroconf instance, defer constructing it
# (which opens mDNS multicast sockets) until the first ``.local``
# lookup. Resolvers that only handle unicast names never pay that
# cost. A caller-supplied instance is used as-is.While you're at it, the PR description's Why/How sections carry the same 'listener threads' phrasing and should be corrected too. Checklist
SummaryThe lazy-construction logic is correct and complete: Automated review by Kōan0d08f57 |
Owned AsyncZeroconf instances opened mDNS multicast sockets and started listener threads at __init__ time, even for resolvers that only ever handle unicast names. Defer construction to the first .local lookup via a _ensure_aiozc() helper; a caller-supplied instance is still used as-is. Closes aio-libs#98. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
0d08f57 to
f10fb2e
Compare
|
Thought about it and decided against accepting this PR. Better to startup the instance as soon as possible in case there is a bind failure. More likely to be seen in the log |
What
Make the owned
AsyncZeroconfinstance lazy — constructed on the first.locallookup instead of in
__init__. Implements #98.Why
_AsyncMDNSResolverBase.__init__eagerly builtAsyncZeroconf()on everyresolver, which opens mDNS multicast sockets and starts listener threads — even
for resolvers that only ever resolve unicast names (the common aiohttp case
where a connector is given an mDNS-capable resolver but the app rarely hits a
.localhost). Those resolvers now pay zero mDNS cost until they actually need it.How
_aiozcstarts as the caller-supplied instance orNone; ownership tracking(
_aiozc_owner) is unchanged._ensure_aiozc()constructs the owned instance on first use and is calledat the top of both
resolve().localbranches and in_resolve_mdns.close()already guarded_aiozc is not None, so a never-constructed resolvercloses cleanly as a no-op. The now-unused
# type: ignore[assignment]wasremoved (
warn_unused_ignores = true).AsyncZeroconf()is created inside therunning loop (during
await resolve(...)) rather than at__init__, which mayrun outside any loop.
This was filed as proposal #98 rather than shipped, because it changes a
maintainer-accepted, tested contract: PR #90's context-manager tests asserted
_aiozc is not Noneimmediately after construction. That assertion is the eagerbehavior this PR removes, so those two tests are updated to assert the lazy
contract (
_aiozc is Noneuntil first use) instead. Opening as a draft so youcan weigh that semantic change with the diff + CI matrix in front of you. I can't
run the suite locally (no zeroconf in this env), so CI is the validation gate here.
Testing
python -m py_compileon both changed files (local env can't run pytest).test_async_context_manager_closes_resolver/_dualfor the lazy contract.test_owned_zeroconf_not_constructed_until_first_use(patchesAsyncZeroconf,asserts not called at construction, called once on
_ensure_aiozc(), idempotent,closed on
close()).test_passed_in_zeroconf_used_without_constructing(caller-supplied instanceused as-is, never re-constructed).
🤖 Generated with Claude Code
Quality Report
Changes: 3 files changed, 64 insertions(+), 6 deletions(-)
Code scan: clean
Tests: failed (FAILED)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline