Open bukowskiadam opened 6 months ago
Hi, as you described in the docs (and I checked the code), the only valid options are true | string
. false
does nothing.
I've checked that here: https://github.com/bukowskiadam/axios-cache-interceptor-memory-issue/blob/e7286464f8aa036fc6eace6c35baee89824dd6b0/test/etag.js#L29
Imo this code: https://github.com/arthurfiorette/axios-cache-interceptor/blob/f0ba5ad92ef333ba146a4378780a0b27262be1c0/src/interceptors/response.ts#L135-L137 allows only to override etag, but not to delete it 🤷🏻
Hey @bukowskiadam, you're right!
I do not have enough spare time to work in this project right now... Anyone up to a PR?
Just a quick note here that we've also run into this memory leak in production and it caused us to attempt to reshape how we scale our services that were planning on using this library. We ended up having to roll back to axios-cache-adapter
to balance effort/value of the swap. If/when we have time to revisit will come back to this issue.
What happened?
Hey Arthur,
Recently we've migrated our code to axios and we've used your package to handle caching. Thank you for your work here ❤️ After the migration, we've noticed that memory consumption of our app presents a "lovely" toothsaw pattern 😬 I've spent quite a lot of time trying to figure out what's wrong.
Here is the recap - sorry for it being long.
Etag / last-modified
This is not a bug, but that caused us to store many entries forever.
Every resource with an etag header (or last-modified) in the response (the default express app adds it), is kept forever, and there is no simple way to disable it (or I haven't found one).
I've mitigated it with the following code that removes those headers and assign default stale ttl:
waiting
To mitigate the problem with stalled entries kept forever, we've tried using
MAX_ENTRIES
in the memory storage, but that didn't improve the situation but the problem was different.Where we have many parallel requests fired, and we exceed the max entries limit, the memory adapter removes some of them. But they are kept in the
axios.waiting
object. After the request is resolved they are not removed from there. Probably until you try to hit the same request.id again (the same url, method, query).I believe the problem comes from this part of the code: https://github.com/arthurfiorette/axios-cache-interceptor/blob/f0ba5ad92ef333ba146a4378780a0b27262be1c0/src/interceptors/response.ts#L93-L108
Because when you're removing the entry from the storage and it's not there, the returned value is
so this if is true, so we end the response interceptor, and we do not remove / resolve other waiting requests.
In our very specific case, the URL passed to Axios was sliced from a very long document, which caused Node to keep the reference to the original string. (slice / substring / regex match, does not create the copy of a string, but points to the fragment of the original string).
proof of concept
Here is my repo with test cases describing the two issues we had: https://github.com/bukowskiadam/axios-cache-interceptor-memory-issue
I hope it gives some working example so you can validate the problems.
What's next
(In other words: what is this issue about)
axios.waiting
memory leaketag: false
to disable handling ETag headers.Best regards, Adam
axios-cache-interceptor version
v1.5.2
Node / Browser Version
Node v20.12.2
Axios Version
v1.6.8
What storage is being used
Memory Storage
Relevant debugging log output