Bug description
DefaultDictWithTimeout.__refresh() in pr_agent/servers/utils.py has an inverted guard condition on line 67. The comparison uses > when it should use <:
def __refresh(self):
if self.__ttl is None:
return
request_time = self.__time()
if request_time - self.__last_refresh > self.__refresh_interval: # ← inverted
return
# cleanup logic below — only reached when NOT enough time has passed
When enough time has passed since the last refresh (i.e., cleanup is needed), the method returns early. The cleanup logic only runs when the interval has NOT elapsed — when there's nothing to clean up.
Impact
_duplicate_push_triggers and _pending_task_duplicate_push_conditions in the GitHub App server accumulate every processed PR URL and never release them. On long-running server instances, this is a memory leak that grows linearly with the number of PRs processed.
Steps to reproduce
from pr_agent.servers.utils import DefaultDictWithTimeout
import time
d = DefaultDictWithTimeout(list, ttl=1, refresh_interval=0.5)
d["key1"].append("val")
time.sleep(2) # well past TTL
d["key2"] # triggers __refresh via __getitem__
print("key1" in d) # True — should be False, key1's TTL expired
Fix
PR #2255 — change > to < on line 67.
Bug description
DefaultDictWithTimeout.__refresh()inpr_agent/servers/utils.pyhas an inverted guard condition on line 67. The comparison uses>when it should use<:When enough time has passed since the last refresh (i.e., cleanup is needed), the method returns early. The cleanup logic only runs when the interval has NOT elapsed — when there's nothing to clean up.
Impact
_duplicate_push_triggersand_pending_task_duplicate_push_conditionsin the GitHub App server accumulate every processed PR URL and never release them. On long-running server instances, this is a memory leak that grows linearly with the number of PRs processed.Steps to reproduce
Fix
PR #2255 — change
>to<on line 67.