Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AC3: Memory leak in watchQuery retains context object in memory even after unsubscribe #7149

Closed
dotansimha opened this issue Oct 11, 2020 · 6 comments · Fixed by #7157
Closed
Assignees

Comments

@dotansimha
Copy link
Contributor

dotansimha commented Oct 11, 2020

Intended outcome:

Object passed as context to watchQuery method should be released when unsubscribe is called, instead of being retrained in memory.

I'm opening this because this seems like another symptom of a related issue, but with a testable reproduction, and including the heap snapshots files.

I believe this is very related to what @Torsten85 posted here: #6985 (comment)

Actual outcome:
context object are retained in memory by AC3:
image

How to reproduce the issue:
Use watchQuery with context set. Apollo keeps reference to that object even if query has done, and unsubscribe has been called (and all references has been destructed).

You can find a complete reproduction (as a Jest test + instructions) here:
https://github.com/dotansimha/apollo-very-pessimism

Versions
>=3

@dotansimha
Copy link
Contributor Author

Updated the reproduction with the heap snapshot file (https://github.com/dotansimha/apollo-very-pessimism#heap-snapshot)

@kamilkisiela
Copy link
Contributor

kamilkisiela commented Oct 12, 2020

We managed to fix the leak by patching optimism and @apollo/client packages (patches).

In optimism:

diff --git a/node_modules/optimism/lib/bundle.esm.js b/node_modules/optimism/lib/bundle.esm.js
index 99c5962..546fa35 100644
--- a/node_modules/optimism/lib/bundle.esm.js
+++ b/node_modules/optimism/lib/bundle.esm.js
@@ -510,6 +510,10 @@ function wrap(originalFunction, options) {
             return entry.peek();
         }
     };
+    optimistic.delete = function (key) {
+        const k = makeCacheKey(key);
+        cache.delete(k)
+    }
     return optimistic;
 }

In @apollo/client:

diff --git a/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js b/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js
index b421d3a..6618215 100644
--- a/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js
+++ b/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js
@@ -129,6 +129,8 @@ var InMemoryCache = (function (_super) {
             this.maybeBroadcastWatch(watch);
         }
         return function () {
+            _this.watchDep.dirty(watch);
+            _this.maybeBroadcastWatch.delete(watch);
             _this.watches.delete(watch);
         };
     };

Above changes are related to #7086. Cleaning up the records in dep and wrap functions of optimism when watch is completed makes sure it doesn't hold a reference to QueryInfo => ObservableQuery => ObservableQuery.options => options.context anymore.

@benjamn
Copy link
Member

benjamn commented Oct 13, 2020

Thanks to @dotansimha's reproduction and @kamilkisiela's proposed solution, I'm confident this leak is fixed in @apollo/client@3.2.4 and @apollo/client@3.3.0-beta.12. Thanks a ton!

@benjamn
Copy link
Member

benjamn commented Oct 13, 2020

@dotansimha As a side note, the weak reference approach you used in your reproduction (using weak-napi) is 🤯 —definitely using that the next time I need to write a memory leak regression test that runs in Node!

@dotansimha
Copy link
Contributor Author

dotansimha commented Oct 14, 2020

Thank you @benjamn !
Btw, you can take a look at the rest of the branches in my reproduction, we added more use cases (watchQuery + mutation that effects it, subscription and some more).

@kamilkisiela you found something else with mutations that throws error, right?

Maybe these tests can be wrapped and move to this repo? just to make sure CI does that as well and we are not experiencing any regression. We have a few thoughts around that, we can help with that. Let me know how that's sounds, we can schedule a meeting for that :)

@kamilkisiela
Copy link
Contributor

@dotansimha yes, quick LARGE coffee and then I'm going to create a reproduction with a fix.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants