Skip to content

Commit d65c885

Browse files
authored
fix(poller): Resource leak in IssueListOverview (#102053)
Replication steps: 1. Go to IssueList. Set filter by project-1. 2. Turn on realtime. 3. See the network requests for project-1. 4. Select filter by project-2. 5. See the network requests both project-1 and project-2. `CursorPoller` has a recursive `setTimeout` method. If the poller is not cleaned up for `project-1`, the recursive method will keep calling itself and preventing garbage collector from killing it.
1 parent 6e9bc81 commit d65c885

File tree

2 files changed

+9
-8
lines changed

2 files changed

+9
-8
lines changed

static/app/utils/cursorPoller.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,10 @@ class CursorPoller {
4848
}
4949

5050
enable() {
51-
this.active = true;
51+
// Proactively cleanup to prevent multiple setTimeout per class instance
52+
this.disable();
5253

53-
// Proactively clear timeout and last request
54-
if (this.timeoutId) {
55-
window.clearTimeout(this.timeoutId);
56-
}
57-
if (this.lastRequest) {
58-
this.lastRequest.cancel();
59-
}
54+
this.active = true;
6055
this.timeoutId = window.setTimeout(this.poll.bind(this), this.getDelay());
6156
}
6257

static/app/views/issueList/overview.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ function IssueListOverview({
176176
);
177177

178178
useEffect(() => {
179+
// Either cleanup or reuse the poller to prevent a resource leak.
180+
if (pollerRef.current) {
181+
pollerRef.current.setEndpoint(parseLinkHeader(pageLinks)?.previous?.href!);
182+
return;
183+
}
184+
179185
pollerRef.current = new CursorPoller({
180186
linkPreviousHref: parseLinkHeader(pageLinks)?.previous?.href!,
181187
success: onRealtimePoll,

0 commit comments

Comments
 (0)