[Telemetry] Cache the report generation promise (#146679)

Resolves https://github.com/elastic/kibana/issues/146676
This commit is contained in:
Alejandro Fernández Haro 2022-12-01 16:14:46 +01:00 committed by GitHub
parent df41bfa9fe
commit 24de7178ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 7 deletions

View file

@ -136,6 +136,15 @@ describe('Telemetry Collection Manager', () => {
).toBeInstanceOf(TelemetrySavedObjectsClient);
});
test('caches the promise calling `getStats` for concurrent requests', async () => {
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
{ clusterUuid: 'clusterUuid' },
]);
collectionStrategy.statsGetter.mockResolvedValue([basicStats]);
await Promise.all([setupApi.getStats(config), setupApi.getStats(config)]);
expect(collectionStrategy.statsGetter).toHaveBeenCalledTimes(1);
});
it('calls getStats with passed refreshCache config', async () => {
const getStatsCollectionConfig: jest.SpyInstance<
TelemetryCollectionManagerPlugin['getStatsCollectionConfig']
@ -270,6 +279,15 @@ describe('Telemetry Collection Manager', () => {
getStatsCollectionConfig.mockRestore();
});
test('does not cache the promise calling `getStats` for concurrent requests', async () => {
collectionStrategy.clusterDetailsGetter.mockResolvedValue([
{ clusterUuid: 'clusterUuid' },
]);
collectionStrategy.statsGetter.mockResolvedValue([basicStats]);
await Promise.all([setupApi.getStats(config), setupApi.getStats(config)]);
expect(collectionStrategy.statsGetter).toHaveBeenCalledTimes(2);
});
});
describe('getOptInStats', () => {

View file

@ -340,20 +340,47 @@ export class TelemetryCollectionManagerPlugin
}
const cacheKey = this.createCacheKey(collectionSource, clustersDetails);
const cachedUsageStatsPayload = this.cacheManager.getFromCache<UsageStatsPayload[]>(cacheKey);
if (cachedUsageStatsPayload) {
return this.updateFetchedAt(cachedUsageStatsPayload);
const cachedUsageStatsPromise =
this.cacheManager.getFromCache<Promise<UsageStatsPayload[]>>(cacheKey);
if (cachedUsageStatsPromise) {
return this.updateFetchedAt(await cachedUsageStatsPromise);
}
const statsFromCollectionPromise = this.getStatsFromCollection(
clustersDetails,
collection,
statsCollectionConfig
);
this.cacheManager.setCache(cacheKey, statsFromCollectionPromise);
try {
const stats = await statsFromCollectionPromise;
return this.updateFetchedAt(stats);
} catch (err) {
this.logger.debug(
`Failed to generate the telemetry report (${err.message}). Resetting the cache...`
);
this.cacheManager.resetCache();
throw err;
}
}
private async getStatsFromCollection(
clustersDetails: ClusterDetails[],
collection: CollectionStrategy,
statsCollectionConfig: StatsCollectionConfig
) {
const context: StatsCollectionContext = {
logger: this.logger.get(collection.title),
version: this.version,
};
const { title: collectionSource } = collection;
const now = new Date().toISOString();
const stats = await collection.statsGetter(clustersDetails, statsCollectionConfig, context);
const usageStatsPayload = stats.map((stat) => ({
return stats.map((stat) => ({
collectionSource,
cacheDetails: { updatedAt: now, fetchedAt: now },
...stat,
}));
this.cacheManager.setCache(cacheKey, usageStatsPayload);
return this.updateFetchedAt(usageStatsPayload);
}
}