1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

Fix/embedded proxy memory leak (#2345)

* Fixes a memory leak where events would trigger the data polling to restart. Any event would setup another polling interval, which would strain our database. Separated the logic for fetching the data and the polling, and made sure that the polling was only initialized once.
This commit is contained in:
Fredrik Strand Oseberg 2022-11-08 12:35:53 +01:00 committed by GitHub
parent c6f906159b
commit f76ac0edb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 3 deletions

View File

@ -73,7 +73,7 @@ export class ProxyRepository
}
async start(): Promise<void> {
await this.loadDataForToken();
await this.dataPolling();
// Reload cached token data whenever something relevant has changed.
// For now, simply reload all the data on any EventStore event.
@ -88,11 +88,15 @@ export class ProxyRepository
clearTimeout(this.timer);
}
private async loadDataForToken() {
private async dataPolling() {
this.timer = setTimeout(async () => {
await this.loadDataForToken();
await this.dataPolling();
}, this.randomizeDelay(this.interval, this.interval * 2)).unref();
await this.loadDataForToken();
}
private async loadDataForToken() {
try {
this.features = await this.featuresForToken();
this.segments = await this.segmentsForToken();

View File

@ -10,6 +10,7 @@ import {
import { startOfHour } from 'date-fns';
import { IConstraint, IStrategyConfig } from '../../../../lib/types/model';
import { ProxyRepository } from '../../../../lib/proxy/proxy-repository';
import { FEATURE_UPDATED } from '../../../../lib/types/events';
let app: IUnleashTest;
let db: ITestDb;
@ -898,3 +899,33 @@ test('Should change fetch interval', async () => {
expect(spy.mock.calls.length > 30).toBe(true);
jest.useRealTimers();
});
test('Should not recursively set off timers on events', async () => {
jest.useFakeTimers();
const frontendToken = await createApiToken(ApiTokenType.FRONTEND);
const user = await app.services.apiTokenService.getUserForToken(
frontendToken.secret,
);
const spy = jest.spyOn(ProxyRepository.prototype as any, 'dataPolling');
const proxyRepository = new ProxyRepository(
{
getLogger,
frontendApi: { refreshIntervalInMs: 5000 },
},
db.stores,
app.services,
user,
);
await proxyRepository.start();
db.stores.eventStore.emit(FEATURE_UPDATED);
jest.advanceTimersByTime(10000);
proxyRepository.stop();
expect(spy.mock.calls.length < 3).toBe(true);
jest.useRealTimers();
});