Loki language provider: don't cache empty array while querying (#92092)
* Loki language provider: don't cache empty array while querying * Prettier * Unfocus test * chore: add extra assertion
This commit is contained in:
@@ -268,6 +268,24 @@ describe('Language completion provider', () => {
|
||||
end: expect.any(Number),
|
||||
});
|
||||
});
|
||||
|
||||
it('should use a single promise to resolve values', async () => {
|
||||
const datasource = setup({ testkey: ['label1_val1', 'label1_val2'], label2: [] });
|
||||
const provider = await getLanguageProvider(datasource);
|
||||
const requestSpy = jest.spyOn(provider, 'request');
|
||||
const promise1 = provider.fetchLabelValues('testkey');
|
||||
const promise2 = provider.fetchLabelValues('testkey');
|
||||
const promise3 = provider.fetchLabelValues('testkeyNOPE');
|
||||
expect(requestSpy).toHaveBeenCalledTimes(2);
|
||||
|
||||
const values1 = await promise1;
|
||||
const values2 = await promise2;
|
||||
const values3 = await promise3;
|
||||
|
||||
expect(values1).toStrictEqual(values2);
|
||||
expect(values2).not.toStrictEqual(values3);
|
||||
expect(requestSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchLabels', () => {
|
||||
|
||||
@@ -31,6 +31,7 @@ export default class LokiLanguageProvider extends LanguageProvider {
|
||||
*/
|
||||
private seriesCache = new LRUCache<string, Record<string, string[]>>({ max: 10 });
|
||||
private labelsCache = new LRUCache<string, string[]>({ max: 10 });
|
||||
private labelsPromisesCache = new LRUCache<string, Promise<string[]>>({ max: 10 });
|
||||
|
||||
constructor(datasource: LokiDatasource, initialValues?: any) {
|
||||
super();
|
||||
@@ -272,18 +273,34 @@ export default class LokiLanguageProvider extends LanguageProvider {
|
||||
|
||||
const cacheKey = this.generateCacheKey(url, start, end, paramCacheKey);
|
||||
|
||||
let labelValues = this.labelsCache.get(cacheKey);
|
||||
if (!labelValues) {
|
||||
// Clear value when requesting new one. Empty object being truthy also makes sure we don't request twice.
|
||||
this.labelsCache.set(cacheKey, []);
|
||||
const res = await this.request(url, params);
|
||||
if (Array.isArray(res)) {
|
||||
labelValues = res.slice().sort();
|
||||
this.labelsCache.set(cacheKey, labelValues);
|
||||
}
|
||||
// Values in cache, return
|
||||
const labelValues = this.labelsCache.get(cacheKey);
|
||||
if (labelValues) {
|
||||
return labelValues;
|
||||
}
|
||||
|
||||
return labelValues ?? [];
|
||||
// Promise in cache, return
|
||||
let labelValuesPromise = this.labelsPromisesCache.get(cacheKey);
|
||||
if (labelValuesPromise) {
|
||||
return labelValuesPromise;
|
||||
}
|
||||
|
||||
labelValuesPromise = new Promise(async (resolve) => {
|
||||
try {
|
||||
const data = await this.request(url, params);
|
||||
if (Array.isArray(data)) {
|
||||
const labelValues = data.slice().sort();
|
||||
this.labelsCache.set(cacheKey, labelValues);
|
||||
this.labelsPromisesCache.delete(cacheKey);
|
||||
resolve(labelValues);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
resolve([]);
|
||||
}
|
||||
});
|
||||
this.labelsPromisesCache.set(cacheKey, labelValuesPromise);
|
||||
return labelValuesPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user