@@ -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