feat: improve performance responding to queries (#1217) · python-zeroconf/python-zeroconf@69b33be
@@ -46,7 +46,7 @@
4646from ..const import (
4747_ADDRESS_RECORD_TYPES,
4848_CLASS_IN,
49-_CLASS_UNIQUE,
49+_CLASS_IN_UNIQUE,
5050_DNS_HOST_TTL,
5151_DNS_OTHER_TTL,
5252_FLAGS_QR_QUERY,
@@ -388,7 +388,7 @@ def _unpack_text_into_properties(self) -> None:
388388389389def get_name(self) -> str:
390390"""Name accessor"""
391-return self.name[: len(self.name) - len(self.type) - 1]
391+return self._name[: len(self._name) - len(self.type) - 1]
392392393393def _get_ip_addresses_from_cache_lifo(
394394self, zc: 'Zeroconf', now: float, type: int
@@ -409,15 +409,21 @@ def _get_ip_addresses_from_cache_lifo(
409409410410def _set_ipv6_addresses_from_cache(self, zc: 'Zeroconf', now: float) -> None:
411411"""Set IPv6 addresses from the cache."""
412-self._ipv6_addresses = cast(
413-"List[IPv6Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
414- )
412+if TYPE_CHECKING:
413+self._ipv6_addresses = cast(
414+"List[IPv6Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
415+ )
416+else:
417+self._ipv6_addresses = self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA)
415418416419def _set_ipv4_addresses_from_cache(self, zc: 'Zeroconf', now: float) -> None:
417420"""Set IPv4 addresses from the cache."""
418-self._ipv4_addresses = cast(
419-"List[IPv4Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
420- )
421+if TYPE_CHECKING:
422+self._ipv4_addresses = cast(
423+"List[IPv4Address]", self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
424+ )
425+else:
426+self._ipv4_addresses = self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A)
421427422428def update_record(self, zc: 'Zeroconf', now: float, record: Optional[DNSRecord]) -> None:
423429"""Updates service information from a DNS record.
@@ -523,9 +529,9 @@ def dns_addresses(
523529created: Optional[float] = None,
524530 ) -> List[DNSAddress]:
525531"""Return matching DNSAddress from ServiceInfo."""
526-name = self.server or self.name
532+name = self.server or self._name
527533ttl = override_ttl if override_ttl is not None else self.host_ttl
528-class_ = _CLASS_IN | _CLASS_UNIQUE
534+class_ = _CLASS_IN_UNIQUE
529535version_value = version.value
530536return [
531537DNSAddress(
@@ -546,30 +552,33 @@ def dns_pointer(self, override_ttl: Optional[int] = None, created: Optional[floa
546552_TYPE_PTR,
547553_CLASS_IN,
548554override_ttl if override_ttl is not None else self.other_ttl,
549-self.name,
555+self._name,
550556created,
551557 )
552558553559def dns_service(self, override_ttl: Optional[int] = None, created: Optional[float] = None) -> DNSService:
554560"""Return DNSService from ServiceInfo."""
561+port = self.port
562+if TYPE_CHECKING:
563+assert isinstance(port, int)
555564return DNSService(
556-self.name,
565+self._name,
557566_TYPE_SRV,
558-_CLASS_IN | _CLASS_UNIQUE,
567+_CLASS_IN_UNIQUE,
559568override_ttl if override_ttl is not None else self.host_ttl,
560569self.priority,
561570self.weight,
562-cast(int, self.port),
563-self.server or self.name,
571+port,
572+self.server or self._name,
564573created,
565574 )
566575567576def dns_text(self, override_ttl: Optional[int] = None, created: Optional[float] = None) -> DNSText:
568577"""Return DNSText from ServiceInfo."""
569578return DNSText(
570-self.name,
579+self._name,
571580_TYPE_TXT,
572-_CLASS_IN | _CLASS_UNIQUE,
581+_CLASS_IN_UNIQUE,
573582override_ttl if override_ttl is not None else self.other_ttl,
574583self.text,
575584created,
@@ -580,11 +589,11 @@ def dns_nsec(
580589 ) -> DNSNsec:
581590"""Return DNSNsec from ServiceInfo."""
582591return DNSNsec(
583-self.name,
592+self._name,
584593_TYPE_NSEC,
585-_CLASS_IN | _CLASS_UNIQUE,
594+_CLASS_IN_UNIQUE,
586595override_ttl if override_ttl is not None else self.host_ttl,
587-self.name,
596+self._name,
588597missing_types,
589598created,
590599 )
@@ -593,12 +602,11 @@ def get_address_and_nsec_records(
593602self, override_ttl: Optional[int] = None, created: Optional[float] = None
594603 ) -> Set[DNSRecord]:
595604"""Build a set of address records and NSEC records for non-present record types."""
596-seen_types: Set[int] = set()
605+missing_types: Set[int] = _ADDRESS_RECORD_TYPES.copy()
597606records: Set[DNSRecord] = set()
598607for dns_address in self.dns_addresses(override_ttl, IPVersion.All, created):
599-seen_types.add(dns_address.type)
608+missing_types.discard(dns_address.type)
600609records.add(dns_address)
601-missing_types: Set[int] = _ADDRESS_RECORD_TYPES - seen_types
602610if missing_types:
603611assert self.server is not None, "Service server must be set for NSEC record."
604612records.add(self.dns_nsec(list(missing_types), override_ttl, created))
@@ -616,7 +624,7 @@ def set_server_if_missing(self) -> None:
616624 This function is for backwards compatibility.
617625 """
618626if self.server is None:
619-self.server = self.name
627+self.server = self._name
620628self.server_key = self.server.lower()
621629622630def load_from_cache(self, zc: 'Zeroconf', now: Optional[float] = None) -> bool:
@@ -627,10 +635,10 @@ def load_from_cache(self, zc: 'Zeroconf', now: Optional[float] = None) -> bool:
627635if not now:
628636now = current_time_millis()
629637original_server_key = self.server_key
630-cached_srv_record = zc.cache.get_by_details(self.name, _TYPE_SRV, _CLASS_IN)
638+cached_srv_record = zc.cache.get_by_details(self._name, _TYPE_SRV, _CLASS_IN)
631639if cached_srv_record:
632640self._process_record_threadsafe(zc, cached_srv_record, now)
633-cached_txt_record = zc.cache.get_by_details(self.name, _TYPE_TXT, _CLASS_IN)
641+cached_txt_record = zc.cache.get_by_details(self._name, _TYPE_TXT, _CLASS_IN)
634642if cached_txt_record:
635643self._process_record_threadsafe(zc, cached_txt_record, now)
636644if original_server_key == self.server_key:
@@ -732,18 +740,21 @@ def generate_request_query(
732740 ) -> DNSOutgoing:
733741"""Generate the request query."""
734742out = DNSOutgoing(_FLAGS_QR_QUERY)
735-out.add_question_or_one_cache(zc.cache, now, self.name, _TYPE_SRV, _CLASS_IN)
736-out.add_question_or_one_cache(zc.cache, now, self.name, _TYPE_TXT, _CLASS_IN)
737-out.add_question_or_all_cache(zc.cache, now, self.server or self.name, _TYPE_A, _CLASS_IN)
738-out.add_question_or_all_cache(zc.cache, now, self.server or self.name, _TYPE_AAAA, _CLASS_IN)
743+name = self._name
744+server_or_name = self.server or name
745+cache = zc.cache
746+out.add_question_or_one_cache(cache, now, name, _TYPE_SRV, _CLASS_IN)
747+out.add_question_or_one_cache(cache, now, name, _TYPE_TXT, _CLASS_IN)
748+out.add_question_or_all_cache(cache, now, server_or_name, _TYPE_A, _CLASS_IN)
749+out.add_question_or_all_cache(cache, now, server_or_name, _TYPE_AAAA, _CLASS_IN)
739750if question_type == DNSQuestionType.QU:
740751for question in out.questions:
741752question.unicast = True
742753return out
743754744755def __eq__(self, other: object) -> bool:
745756"""Tests equality of service name"""
746-return isinstance(other, ServiceInfo) and other.name == self.name
757+return isinstance(other, ServiceInfo) and other._name == self._name
747758748759def __repr__(self) -> str:
749760"""String representation"""