Skip to content

Memory leak when using cache feature. #792

@clement-buchart

Description

@clement-buchart

Hello,

We are facing a memory leak in our production environment, using got and it's cache feature (with a KeyvRedis storage backend).

A heap dump revealed that most memory is retained by multiple error event listener on the single KeyvRedis instance.
Further analysis showed that for each request, a new CacheableRequest is instantiated :

if (options.cache) {
	const cacheableRequest = new CacheableRequest(fn.request, options.cache);
	const cacheRequest = cacheableRequest(options, handleResponse);

	cacheRequest.once('error', error => {
		if (error instanceof CacheableRequest.RequestError) {
			emitError(new RequestError(error, options));
		} else {
			emitError(new CacheError(error, options));
		}
	});

	cacheRequest.once('request', handleRequest);
}

Then, for each CacheableRequest, a new Keyv is instantiated :

this.cache = new Keyv({
	uri: typeof cacheAdapter === 'string' && cacheAdapter,
	store: typeof cacheAdapter !== 'string' && cacheAdapter,
	namespace: 'cacheable-request'
});

KeyvRedis being an EventEmitter, a eventListener is registered.

if (typeof this.opts.store.on === 'function') {
	this.opts.store.on('error', err => this.emit('error', err));
}

The full context of the request being retained by this event listener.

Is there something wrong with the way we use got ? Is there a way to prevent CacheableRequest to be instantiated for each request ?

We tried using got.create, but that didn't work.

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething does not work as it shouldexternalThe issue related to an external project✭ help wanted ✭

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions