feat: improve performance responding to queries (#1217) · python-zeroconf/python-zeroconf@69b33be

@@ -46,7 +46,7 @@

4646

from ..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:

388388389389

def 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]

392392393393

def _get_ip_addresses_from_cache_lifo(

394394

self, zc: 'Zeroconf', now: float, type: int

@@ -409,15 +409,21 @@ def _get_ip_addresses_from_cache_lifo(

409409410410

def _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)

415418416419

def _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)

421427422428

def 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(

523529

created: 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

527533

ttl = override_ttl if override_ttl is not None else self.host_ttl

528-

class_ = _CLASS_IN | _CLASS_UNIQUE

534+

class_ = _CLASS_IN_UNIQUE

529535

version_value = version.value

530536

return [

531537

DNSAddress(

@@ -546,30 +552,33 @@ def dns_pointer(self, override_ttl: Optional[int] = None, created: Optional[floa

546552

_TYPE_PTR,

547553

_CLASS_IN,

548554

override_ttl if override_ttl is not None else self.other_ttl,

549-

self.name,

555+

self._name,

550556

created,

551557

)

552558553559

def 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)

555564

return DNSService(

556-

self.name,

565+

self._name,

557566

_TYPE_SRV,

558-

_CLASS_IN | _CLASS_UNIQUE,

567+

_CLASS_IN_UNIQUE,

559568

override_ttl if override_ttl is not None else self.host_ttl,

560569

self.priority,

561570

self.weight,

562-

cast(int, self.port),

563-

self.server or self.name,

571+

port,

572+

self.server or self._name,

564573

created,

565574

)

566575567576

def dns_text(self, override_ttl: Optional[int] = None, created: Optional[float] = None) -> DNSText:

568577

"""Return DNSText from ServiceInfo."""

569578

return DNSText(

570-

self.name,

579+

self._name,

571580

_TYPE_TXT,

572-

_CLASS_IN | _CLASS_UNIQUE,

581+

_CLASS_IN_UNIQUE,

573582

override_ttl if override_ttl is not None else self.other_ttl,

574583

self.text,

575584

created,

@@ -580,11 +589,11 @@ def dns_nsec(

580589

) -> DNSNsec:

581590

"""Return DNSNsec from ServiceInfo."""

582591

return DNSNsec(

583-

self.name,

592+

self._name,

584593

_TYPE_NSEC,

585-

_CLASS_IN | _CLASS_UNIQUE,

594+

_CLASS_IN_UNIQUE,

586595

override_ttl if override_ttl is not None else self.host_ttl,

587-

self.name,

596+

self._name,

588597

missing_types,

589598

created,

590599

)

@@ -593,12 +602,11 @@ def get_address_and_nsec_records(

593602

self, 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()

597606

records: Set[DNSRecord] = set()

598607

for 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)

600609

records.add(dns_address)

601-

missing_types: Set[int] = _ADDRESS_RECORD_TYPES - seen_types

602610

if missing_types:

603611

assert self.server is not None, "Service server must be set for NSEC record."

604612

records.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

"""

618626

if self.server is None:

619-

self.server = self.name

627+

self.server = self._name

620628

self.server_key = self.server.lower()

621629622630

def 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:

627635

if not now:

628636

now = current_time_millis()

629637

original_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)

631639

if cached_srv_record:

632640

self._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)

634642

if cached_txt_record:

635643

self._process_record_threadsafe(zc, cached_txt_record, now)

636644

if original_server_key == self.server_key:

@@ -732,18 +740,21 @@ def generate_request_query(

732740

) -> DNSOutgoing:

733741

"""Generate the request query."""

734742

out = 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)

739750

if question_type == DNSQuestionType.QU:

740751

for question in out.questions:

741752

question.unicast = True

742753

return out

743754744755

def __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

747758748759

def __repr__(self) -> str:

749760

"""String representation"""