fix: skip NSEC records in ServiceBrowser to suppress spurious updates#1762
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1762 +/- ##
=======================================
Coverage 99.77% 99.77%
=======================================
Files 33 33
Lines 3509 3511 +2
Branches 493 494 +1
=======================================
+ Hits 3501 3503 +2
Misses 5 5
Partials 3 3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR prevents ServiceBrowser from emitting spurious ServiceStateChange.Updated events when NSEC records arrive for already-known services (per RFC 6762 §6.1), and adds a regression test to ensure NSEC does not trigger update callbacks.
Changes:
- Ignore
_TYPE_NSECrecords inServiceBrowser.async_update_recordsto avoid enqueueing non-address updates. - Add a Cython-typed
_TYPE_NSECdeclaration for fast comparisons in the browser hot path. - Add a regression test asserting that injecting an NSEC record does not produce an
update_servicecallback.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| tests/services/test_browser.py | Adds regression coverage to ensure NSEC does not produce update callbacks |
| src/zeroconf/_services/browser.py | Skips NSEC records during record processing to prevent spurious updates |
| src/zeroconf/_services/browser.pxd | Declares _TYPE_NSEC as cython.uint for efficient comparisons |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bdraco
left a comment
There was a problem hiding this comment.
remove the fixed time.sleep and use proper sync
PR Review — fix: skip NSEC records in ServiceBrowser to suppress spurious updatesTight, well-targeted fix: skip NSEC in 🟢 Suggestions1. Unrelated change to PyPy IPv6 timeout (`tests/__init__.py`, L66)The bump from 2. Document or assert the assumption that the bundled insert does not race with an Updated callback (`tests/services/test_browser.py`, L1138-1153)The test relies on a non-obvious property: a single multicast packet carrying Two low-cost hardening options:
Neither blocks merge — just makes the failure mode more diagnostic if the surrounding behaviour ever shifts. Checklist
SummaryTight, well-targeted fix: skip NSEC in |
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
d90444c to
47f97d2
Compare
NSEC records assert the non-existence of a record type (RFC 6762 §6.1), not a state change. The browser was firing ServiceStateChange.Updated for every NSEC record arriving for a known service, surfacing as "Updated non address record" warnings and unnecessary update_service callbacks. Skip them in async_update_records.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Rebase with requested adjustmentsBranch StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
f47827a to
5557174
Compare
Summary
NSEC records assert non-existence of a record type (RFC 6762 §6.1), not a state change.
ServiceBrowser.async_update_recordswas firingServiceStateChange.Updatedfor every NSEC arriving on a known service, producing the "Updated non address record" warnings reported in #1328 and triggering unnecessaryupdate_servicecallbacks.Fixes #1328
Changes
type == _TYPE_NSECinServiceBrowser.async_update_recordsbefore the generic non-address branch enqueues an update.cdef cython.uint _TYPE_NSECtobrowser.pxdso the hot-path comparison stays a C int compare under Cython.test_service_browser_nsec_record_does_not_trigger_updateinjects an NSEC for a known service and asserts only the originaladd_servicecallback fires.Test plan
master, passes with the fix applied.poetry run pytest --timeout=60 -q tests— 386 passed, 2 skipped.poetry run ruff check/ruff format --checkclean on touched files.Generated by Kōan /fix
Quality Report
Changes: 3 files changed, 69 insertions(+)
Code scan: clean
Tests: passed (4 PASSED)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline