Skip to content

fix: add clean up storage event listeners on Settings unmount to prevent memory leaks - #1179

Merged
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
hrshjswniii:BugFix/Uncleaned-Storage-Listeners-Leak
Aug 2, 2026
Merged

fix: add clean up storage event listeners on Settings unmount to prevent memory leaks#1179
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
hrshjswniii:BugFix/Uncleaned-Storage-Listeners-Leak

Conversation

@hrshjswniii

@hrshjswniii hrshjswniii commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

🚀 Program

GSSoC

📝 Description

This PR resolves memory leaks and duplicate event handler execution caused by uncleaned storage event listeners in Settings.jsx.

Key fixes:

  1. Central Subscription Helper (subscribeProfileChanges): Exported subscribeProfileChanges(callback) in useVoiceClone.js listening to voiceforge:profileChanged custom events and browser storage events. Returns an explicit cleanup function removing both listeners on component unmount.
  2. Settings Cleanup Integration (Settings.jsx): Refactored profile loading in Settings.jsx to return subscribeProfileChanges(loadProfiles) in useEffect, guaranteeing all event listeners are cleanly unbound upon unmounting.
  3. Unit Tests (useVoiceClone.test.js): Added Vitest test assertions verifying profile subscription registration and unmount cleanup.

🔗 Related Issue

Closes #1118

🔄 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🔍 SEO improvement
  • 🎨 Style / UI improvement
  • ♿ Accessibility improvement
  • 📝 Documentation
  • ⚙️ CI / configuration
  • 🧹 Refactor / cleanup

🧪 How to Test

  1. Open http://localhost:5173 in a browser.
  2. Click back and forth between Settings and Call pages 10-15 times.
  3. Perform a profile creation/import action on Settings.
  4. Verify in DevTools console that the profile update handler triggers exactly once with zero duplicate listener warnings.
  5. Run client tests: npm run test --workspace client and verify all tests pass.

✅ Checklist

  • I am contributing under GSSoC
  • My code follows the project's existing style
  • I have tested my changes in a browser
  • I have linked the related issue above
  • My PR title follows Conventional Commits format (e.g. fix: clean up storage event listeners on Settings unmount to prevent memory leaks)

Summary by cubic

Prevents memory leaks and duplicate profile updates by cleaning up storage and voiceforge:profileChanged listeners when Settings unmounts. Adds subscribeProfileChanges in useVoiceClone.js and tests to verify cleanup.

  • Bug Fixes
    • Added subscribeProfileChanges(callback) to listen to voiceforge:profileChanged and storage, returning an unsubscribe.
    • Updated Settings.jsx to use it in useEffect, removing listeners on unmount.
    • Added Vitest test useVoiceClone.test.js to assert subscription and cleanup.

Written for commit f5eda2b. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

@hrshjswniii is attempting to deploy a commit to the itzzavdhesh's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

✍️ DCO Sign-off Needed

Hey @hrshjswniii! 👋 One or more commits in this PR are missing a Signed-off-by: line.

Warning

  • f5eda2b fix: clean up storage event listeners on Settings unmount to prevent memory leaks

How to fix:

For the latest commit:

git commit --amend --signoff
git push --force-with-lease

For multiple commits, replace N with the number to update:

git rebase --signoff HEAD~N
git push --force-with-lease

This comment will update automatically after you push.


🤖 VoiceForge Automation · Updates automatically on edits

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@hrshjswniii, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 30da7606-8b8c-4d8d-83f6-00988bc4a387

📥 Commits

Reviewing files that changed from the base of the PR and between b89b5be and f5eda2b.

📒 Files selected for processing (3)
  • client/src/hooks/useVoiceClone.js
  • client/src/hooks/useVoiceClone.test.js
  • client/src/pages/Settings.jsx
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

🎉 PR Ready for Mentor Review

Hey @hrshjswniii! 👋 Your PR passed all checks and is now in the GSSoC review queue.

Note

🔗 Closing: #1118 · 📐 42 lines across 3 file(s) · 📬 Already requested or no eligible reviewer found

@sabeenaviklar @Anushreebasics @itsdakshjain @snehkris @1754riya @Mrigakshi-Rathore @Itzzavdheshh @Nitya-003 @4f4d @lovestaco, this PR is ready for your review — please confirm scope, check behavior and tests, then approve or request changes.

Important

This is not an approval. Please wait for mentor feedback before expecting a merge. If changes are requested, push them to this same branch and keep the PR focused on the linked issue.


🤖 VoiceForge Automation · Updates automatically on edits

@github-actions
github-actions Bot requested a review from lovestaco July 27, 2026 06:55

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/src/hooks/useVoiceClone.test.js">

<violation number="1" location="client/src/hooks/useVoiceClone.test.js:9">
P3: The `subscribeProfileChanges` function handles two event sources: `voiceforge:profileChanged` custom events and browser `storage` events (filtered by `e.key === ACTIVE_KEY || !e.key`). The test only covers the custom event path. The storage-event filtering logic — which has a non-trivial condition — is untested. Consider adding a test case that dispatches a `StorageEvent` for the `ACTIVE_KEY` and asserts the callback fires, and another for an unrelated key to verify filtering.</violation>

<violation number="2" location="client/src/hooks/useVoiceClone.test.js:20">
P2: Cleanup verification missing after unsubscribe — the test name says 'cleans up profile change event listeners' but never verifies the cleanup succeeded. After calling unsubscribe(), dispatch the event again and assert callback was NOT called (toHaveBeenCalledTimes(1)). Without this, a broken no-op unsubscribe would still pass.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

expect(callback).toHaveBeenCalledTimes(1);
}

unsubscribe();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Cleanup verification missing after unsubscribe — the test name says 'cleans up profile change event listeners' but never verifies the cleanup succeeded. After calling unsubscribe(), dispatch the event again and assert callback was NOT called (toHaveBeenCalledTimes(1)). Without this, a broken no-op unsubscribe would still pass.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/hooks/useVoiceClone.test.js, line 20:

<comment>Cleanup verification missing after unsubscribe — the test name says 'cleans up profile change event listeners' but never verifies the cleanup succeeded. After calling unsubscribe(), dispatch the event again and assert callback was NOT called (toHaveBeenCalledTimes(1)). Without this, a broken no-op unsubscribe would still pass.</comment>

<file context>
@@ -0,0 +1,22 @@
+      expect(callback).toHaveBeenCalledTimes(1);
+    }
+
+    unsubscribe();
+  });
+});
</file context>

expect(typeof useVoiceClone).toBe("function");
});

it("subscribes and cleans up profile change event listeners", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The subscribeProfileChanges function handles two event sources: voiceforge:profileChanged custom events and browser storage events (filtered by e.key === ACTIVE_KEY || !e.key). The test only covers the custom event path. The storage-event filtering logic — which has a non-trivial condition — is untested. Consider adding a test case that dispatches a StorageEvent for the ACTIVE_KEY and asserts the callback fires, and another for an unrelated key to verify filtering.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/hooks/useVoiceClone.test.js, line 9:

<comment>The `subscribeProfileChanges` function handles two event sources: `voiceforge:profileChanged` custom events and browser `storage` events (filtered by `e.key === ACTIVE_KEY || !e.key`). The test only covers the custom event path. The storage-event filtering logic — which has a non-trivial condition — is untested. Consider adding a test case that dispatches a `StorageEvent` for the `ACTIVE_KEY` and asserts the callback fires, and another for an unrelated key to verify filtering.</comment>

<file context>
@@ -0,0 +1,22 @@
+    expect(typeof useVoiceClone).toBe("function");
+  });
+
+  it("subscribes and cleans up profile change event listeners", () => {
+    const callback = vi.fn();
+    const unsubscribe = subscribeProfileChanges(callback);
</file context>

@Nitya-003 Nitya-003 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hrshjswniii Resolve the comments by bot.

@github-actions github-actions Bot added mentor:Nitya-003 Applied by mentor automation needs revision labels Jul 27, 2026
@github-actions

Copy link
Copy Markdown

🔄 Changes Requested

Hey @hrshjswniii! 👋 A mentor has reviewed your PR and requested some changes.

Warning

Please review the feedback above, update this same branch, and keep the PR focused on the linked issue.

Once you push your updates, the review flow will continue automatically on this same PR.


🤖 VoiceForge Automation · Updates automatically on edits

@itsdakshjain itsdakshjain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the feedback from the Cubic AI bot regarding the test file (useVoiceClone.test.js). Specifically, make sure to add assertions verifying that the cleanup function successfully removes event listeners after unsubscribing, and add test cases covering the storage event key-filtering logic.

@github-actions github-actions Bot added the mentor:itsdakshjain GSSoC: Mentor-@itsdakshjain label Jul 28, 2026

@sabeenaviklar sabeenaviklar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @hrshjswniii

Good work on the PR!
A few changes are required before the PR can be merged.

Verify Unsubscribe in Tests: The added test confirms that the callback works but doesn't verify the cleanup. Please dispatch an event after calling the unsubscribe cleanup function and assert that the callback is not triggered again.
Test Storage Filtering: Since your hook checks for a specific active profile key in storage events, please add a test to verify that the storage listener responds to the correct key and ignores unrelated key events.

@github-actions github-actions Bot added the mentor:sabeenaviklar GSSoC: Mentor-@sabeenaviklar label Jul 29, 2026

@itsdakshjain itsdakshjain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you still working on it? @hrshjswniii @itzzavdhesh

@itzzavdhesh
itzzavdhesh merged commit a9370a3 into itzzavdhesh:main Aug 2, 2026
23 of 24 checks passed
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🎊 PR Merged Successfully

Hey @hrshjswniii! 👋 Congratulations and thank you for your contribution to VoiceForge!

Note

🔗 Linked issue(s): #1118 · ✅ Marked as merged and complete

Maintainers may still handle final cleanup, release notes, or follow-up tracking after the merge.


🤖 VoiceForge Automation · Updates automatically on edits

@itzzavdhesh itzzavdhesh added enhancement New feature or request SSoC26 SSOC Hard hard ELUSOC ELUSOC VETERAN VETERAN gssoc:approved Gssoc type:accessibility type type:bug type:bug type:feature type:feature type:performance type:performance type:refactor type:refactor level:intermediate level:intermediate quality:clean quality:clean level:advanced level:advanced and removed level:intermediate level:intermediate labels Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] : Memory Leak from Uncleaned Storage Listeners in Settings

5 participants