Skip to content

Commit

Permalink
Add basic in-memory caching
Browse files Browse the repository at this point in the history
  • Loading branch information
kpollich committed Nov 9, 2023
1 parent 68f4d4b commit 57245aa
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 15 deletions.
9 changes: 1 addition & 8 deletions x-pack/plugins/fleet/server/routes/agent/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,14 +357,7 @@ export const getAvailableVersionsHandler: RequestHandler = async (context, reque
const availableVersions = await AgentService.getAvailableVersions();
const body: GetAvailableVersionsResponse = { items: availableVersions };

// This endpoint is cached to avoid reaching out to disk and the live product versions API
// for every single request
const CACHE_DURATION_SECONDS = 60 * 60 * 2; // 2 hours

return response.ok({
body,
headers: { 'cache-control': `max-age=${CACHE_DURATION_SECONDS}` },
});
return response.ok({ body });
} catch (error) {
return defaultFleetErrorHandler({ error, response });
}
Expand Down
12 changes: 6 additions & 6 deletions x-pack/plugins/fleet/server/services/agents/versions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('getAvailableVersions', () => {
mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);
mockedFetch.mockResolvedValueOnce(emptyResponse);

const res = await getAvailableVersions({ includeCurrentVersion: true });
const res = await getAvailableVersions({ includeCurrentVersion: true, ignoreCache: true });

expect(res).toEqual(['300.0.0', '8.1.0', '8.0.0', '7.17.0']);
});
Expand All @@ -56,7 +56,7 @@ describe('getAvailableVersions', () => {
mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);
mockedFetch.mockResolvedValueOnce(emptyResponse);

const res = await getAvailableVersions({ includeCurrentVersion: true });
const res = await getAvailableVersions({ includeCurrentVersion: true, ignoreCache: true });
expect(res).toEqual(['300.0.0-SNAPSHOT', '8.1.0', '8.0.0', '7.17.0']);
});

Expand All @@ -70,7 +70,7 @@ describe('getAvailableVersions', () => {
mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);
mockedFetch.mockResolvedValueOnce(emptyResponse);

const res = await getAvailableVersions();
const res = await getAvailableVersions({ ignoreCache: true });

expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']);
});
Expand All @@ -80,7 +80,7 @@ describe('getAvailableVersions', () => {
mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`);
mockedFetch.mockResolvedValueOnce(emptyResponse);

const res = await getAvailableVersions({ includeCurrentVersion: false });
const res = await getAvailableVersions({ includeCurrentVersion: false, ignoreCache: true });

expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']);
});
Expand All @@ -95,7 +95,7 @@ describe('getAvailableVersions', () => {
mockedReadFile.mockRejectedValue({ code: 'ENOENT' });
mockedFetch.mockResolvedValueOnce(emptyResponse);

const res = await getAvailableVersions();
const res = await getAvailableVersions({ ignoreCache: true });

expect(res).toEqual(['300.0.0']);
});
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('getAvailableVersions', () => {
),
} as any);

const res = await getAvailableVersions();
const res = await getAvailableVersions({ ignoreCache: true });

// Should sort, uniquify and filter out versions < 7.17
expect(res).toEqual(['8.10.0', '8.9.2', '8.1.0', '8.0.0', '7.17.0']);
Expand Down
24 changes: 23 additions & 1 deletion x-pack/plugins/fleet/server/services/agents/versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const AGENT_VERSION_BUILD_FILE = 'x-pack/plugins/fleet/target/agent_versions_lis
// Endpoint maintained by the web-team and hosted on the elastic website
const PRODUCT_VERSIONS_URL = 'https://www.elastic.co/api/product_versions';

// Cache available versions in memory for 1 hour
const CACHE_DURATION = 1000 * 60 * 60;
let CACHED_AVAILABLE_VERSIONS: string[] | undefined;
let LAST_FETCHED: number | undefined;

export const getLatestAvailableVersion = async (
includeCurrentVersion?: boolean
): Promise<string> => {
Expand All @@ -35,12 +40,26 @@ export const getLatestAvailableVersion = async (

export const getAvailableVersions = async ({
includeCurrentVersion,
ignoreCache = false, // This is only here to allow us to ignore the cache in tests
}: {
includeCurrentVersion?: boolean;
ignoreCache?: boolean;
} = {}): Promise<string[]> => {
const logger = appContextService.getLogger();
const config = appContextService.getConfig();

if (LAST_FETCHED && !ignoreCache) {
const msSinceLastFetched = Date.now() - (LAST_FETCHED || 0);

if (msSinceLastFetched < CACHE_DURATION && CACHED_AVAILABLE_VERSIONS !== undefined) {
logger.debug(`Cache is valid, returning cached available versions`);

return CACHED_AVAILABLE_VERSIONS;
}

logger.debug('Cache has expired, fetching available versions from disk + API');
}

const config = appContextService.getConfig();
const kibanaVersion = appContextService.getKibanaVersion();

let availableVersions: string[] = [];
Expand Down Expand Up @@ -81,6 +100,9 @@ export const getAvailableVersions = async ({
availableVersions = [kibanaVersion];
}

CACHED_AVAILABLE_VERSIONS = availableVersions;
LAST_FETCHED = Date.now();

return availableVersions;
};

Expand Down

0 comments on commit 57245aa

Please sign in to comment.