Skip to content

Commit dbda037

Browse files
committed
feat: optimize processing of records in RecordUpdateListener
These classes used to process a single record at a time, but since we now process them all in batches, we can remove all the breakout functions
1 parent 0c5e5cf commit dbda037

3 files changed

Lines changed: 36 additions & 58 deletions

File tree

src/zeroconf/_services/browser.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
cast,
4040
)
4141

42-
from .._dns import DNSPointer, DNSQuestion, DNSQuestionType, DNSRecord
42+
from .._dns import DNSPointer, DNSQuestion, DNSQuestionType
4343
from .._logger import log
4444
from .._protocol.outgoing import DNSOutgoing
4545
from .._services import (
@@ -383,50 +383,46 @@ def _enqueue_callback(
383383
):
384384
self._pending_handlers[key] = state_change
385385

386-
def _async_process_record_update(
387-
self, now: float, record: DNSRecord, old_record: Optional[DNSRecord]
388-
) -> None:
389-
"""Process a single record update from a batch of updates."""
390-
record_type = record.type
391-
392-
if record_type is _TYPE_PTR:
393-
if TYPE_CHECKING:
394-
record = cast(DNSPointer, record)
395-
for type_ in self.types.intersection(cached_possible_types(record.name)):
396-
if old_record is None:
397-
self._enqueue_callback(ServiceStateChange.Added, type_, record.alias)
398-
elif record.is_expired(now):
399-
self._enqueue_callback(ServiceStateChange.Removed, type_, record.alias)
400-
else:
401-
self.reschedule_type(type_, now, record.get_expiration_time(_EXPIRE_REFRESH_TIME_PERCENT))
402-
return
403-
404-
# If its expired or already exists in the cache it cannot be updated.
405-
if old_record or record.is_expired(now):
406-
return
407-
408-
if record_type in _ADDRESS_RECORD_TYPES:
409-
# Iterate through the DNSCache and callback any services that use this address
410-
for type_, name in self._names_matching_types(
411-
{service.name for service in self.zc.cache.async_entries_with_server(record.name)}
412-
):
413-
self._enqueue_callback(ServiceStateChange.Updated, type_, name)
414-
return
415-
416-
for type_, name in self._names_matching_types((record.name,)):
417-
self._enqueue_callback(ServiceStateChange.Updated, type_, name)
418-
419386
def async_update_records(self, zc: 'Zeroconf', now: float, records: List[RecordUpdate]) -> None:
420387
"""Callback invoked by Zeroconf when new information arrives.
421388
422389
Updates information required by browser in the Zeroconf cache.
423390
424-
Ensures that there is are no unecessary duplicates in the list.
391+
Ensures that there is are no unnecessary duplicates in the list.
425392
426393
This method will be run in the event loop.
427394
"""
428-
for record in records:
429-
self._async_process_record_update(now, record[0], record[1])
395+
for record_update in records:
396+
record, old_record = record_update
397+
record_type = record.type
398+
399+
if record_type is _TYPE_PTR:
400+
if TYPE_CHECKING:
401+
record = cast(DNSPointer, record)
402+
for type_ in self.types.intersection(cached_possible_types(record.name)):
403+
if old_record is None:
404+
self._enqueue_callback(ServiceStateChange.Added, type_, record.alias)
405+
elif record.is_expired(now):
406+
self._enqueue_callback(ServiceStateChange.Removed, type_, record.alias)
407+
else:
408+
expire_time = record.get_expiration_time(_EXPIRE_REFRESH_TIME_PERCENT)
409+
self.reschedule_type(type_, now, expire_time)
410+
continue
411+
412+
# If its expired or already exists in the cache it cannot be updated.
413+
if old_record or record.is_expired(now):
414+
continue
415+
416+
if record_type in _ADDRESS_RECORD_TYPES:
417+
# Iterate through the DNSCache and callback any services that use this address
418+
for type_, name in self._names_matching_types(
419+
{service.name for service in self.zc.cache.async_entries_with_server(record.name)}
420+
):
421+
self._enqueue_callback(ServiceStateChange.Updated, type_, name)
422+
continue
423+
424+
for type_, name in self._names_matching_types((record.name,)):
425+
self._enqueue_callback(ServiceStateChange.Updated, type_, name)
430426

431427
@abstractmethod
432428
def async_update_records_complete(self) -> None:

src/zeroconf/_services/info.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -410,35 +410,17 @@ def _set_ipv4_addresses_from_cache(self, zc: 'Zeroconf', now: float) -> None:
410410
else:
411411
self._ipv4_addresses = self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
412412

413-
def update_record(self, zc: 'Zeroconf', now: float, record: Optional[DNSRecord]) -> None:
414-
"""Updates service information from a DNS record.
415-
416-
This method is deprecated and will be removed in a future version.
417-
update_records should be implemented instead.
418-
419-
This method will be run in the event loop.
420-
"""
421-
if record is not None:
422-
self._process_record_threadsafe(zc, record, now)
423-
424413
def async_update_records(self, zc: 'Zeroconf', now: float, records: List[RecordUpdate]) -> None:
425414
"""Updates service information from a DNS record.
426415
427416
This method will be run in the event loop.
428417
"""
429418
new_records_futures = self._new_records_futures
430-
if self._process_records_threadsafe(zc, now, records) and new_records_futures:
431-
_resolve_all_futures_to_none(new_records_futures)
432-
433-
def _process_records_threadsafe(self, zc: 'Zeroconf', now: float, records: List[RecordUpdate]) -> bool:
434-
"""Thread safe record updating.
435-
436-
Returns True if new records were added.
437-
"""
438419
updated: bool = False
439420
for record_update in records:
440421
updated |= self._process_record_threadsafe(zc, record_update.new, now)
441-
return updated
422+
if updated and new_records_futures:
423+
_resolve_all_futures_to_none(new_records_futures)
442424

443425
def _process_record_threadsafe(self, zc: 'Zeroconf', record: DNSRecord, now: float) -> bool:
444426
"""Thread safe record updating.

src/zeroconf/_updates.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def async_update_records(self, zc: 'Zeroconf', now: float, records: List[RecordU
5656
All records that are received in a single packet are passed
5757
to update_records.
5858
59-
This implementation is a compatiblity shim to ensure older code
59+
This implementation is a compatibility shim to ensure older code
6060
that uses RecordUpdateListener as a base class will continue to
6161
get calls to update_record. This method will raise
6262
NotImplementedError in a future version.

0 commit comments

Comments
 (0)