Skip to content

Commit 7eec3e8

Browse files
committed
refactor: extract QuestionHistory eviction into a cdef helper
1 parent ad93f34 commit 7eec3e8

2 files changed

Lines changed: 20 additions & 10 deletions

File tree

src/zeroconf/_history.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ cdef class QuestionHistory:
1212

1313
cpdef void add_question_at_time(self, DNSQuestion question, double now, cython.set known_answers)
1414

15+
@cython.locals(oldest=DNSQuestion, oldest_entry=cython.tuple, oldest_than=double)
16+
cdef void _evict_to_make_room(self, double now)
17+
1518
@cython.locals(than=double, previous_question=cython.tuple, previous_known_answers=cython.set)
1619
cpdef bint suppresses(self, DNSQuestion question, double now, cython.set known_answers)
1720

src/zeroconf/_history.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,8 @@ def __init__(self) -> None:
4040

4141
def add_question_at_time(self, question: DNSQuestion, now: _float, known_answers: set[DNSRecord]) -> None:
4242
"""Remember a question with known answers."""
43-
# Bound history size between the periodic 10s cleanup ticks. When at
44-
# cap, peek at the oldest insertion (dict is ordered) — only run the
45-
# full O(n) async_expire sweep if it could actually reclaim something,
46-
# else a sustained flood at cap turns each insert into a wasted scan.
4743
if question not in self._history and len(self._history) >= _MAX_QUESTION_HISTORY_ENTRIES:
48-
oldest = next(iter(self._history))
49-
oldest_than, _ = self._history[oldest]
50-
if now - oldest_than > _DUPLICATE_QUESTION_INTERVAL:
51-
self.async_expire(now)
52-
while len(self._history) >= _MAX_QUESTION_HISTORY_ENTRIES:
53-
del self._history[next(iter(self._history))]
44+
self._evict_to_make_room(now)
5445
self._history[question] = (now, known_answers)
5546

5647
def suppresses(self, question: DNSQuestion, now: _float, known_answers: set[DNSRecord]) -> bool:
@@ -86,3 +77,19 @@ def async_expire(self, now: _float) -> None:
8677
def clear(self) -> None:
8778
"""Clear the history."""
8879
self._history.clear()
80+
81+
def _evict_to_make_room(self, now: _float) -> None:
82+
"""Drop expired or oldest entries when the history is at cap.
83+
84+
Peeks at the oldest insertion (dict is ordered) — only runs the
85+
full O(n) async_expire sweep if it could actually reclaim
86+
something, else a sustained flood at cap turns each insert into
87+
a wasted scan. Falls back to oldest-first eviction.
88+
"""
89+
oldest = next(iter(self._history))
90+
oldest_entry = self._history[oldest]
91+
oldest_than = oldest_entry[0]
92+
if now - oldest_than > _DUPLICATE_QUESTION_INTERVAL:
93+
self.async_expire(now)
94+
while len(self._history) >= _MAX_QUESTION_HISTORY_ENTRIES:
95+
del self._history[next(iter(self._history))]

0 commit comments

Comments
 (0)