From 2155daa935398ecf7bd6c530ca10577b1c01e189 Mon Sep 17 00:00:00 2001 From: somebody1234 Date: Thu, 7 Sep 2023 22:59:02 +1000 Subject: [PATCH] Fix unnecessary `/versions` calls (#7747) - Fixes https://github.com/enso-org/cloud-v2/issues/659 `getProjectDetails` was calling `listVersions` to get a fallback IDE version, creating a lot of unnecessary requests to the backend, *especially* because `getProjectDetails` is called periodically when a project is opening. In this PR, the implementation has been changed to cache the fallback version for one day, meaning the extra `listVersions` calls should now only ever happen once per client per day. # Important Notes None --- .../src/dashboard/remoteBackend.ts | 72 +++++++++++++------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/remoteBackend.ts b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/remoteBackend.ts index 193b6c7cc7..7e113218c1 100644 --- a/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/remoteBackend.ts +++ b/app/ide-desktop/lib/dashboard/src/authentication/src/dashboard/remoteBackend.ts @@ -20,6 +20,9 @@ const STATUS_SUCCESS_LAST = 299 /** HTTP status indicating that the server encountered a fatal exception. */ const STATUS_SERVER_ERROR = 500 +/** The number of milliseconds in one day. */ +const ONE_DAY_MS = 86_400_000 + /** Default HTTP body for an "open project" request. */ const DEFAULT_OPEN_PROJECT_BODY: backendModule.OpenProjectRequestBody = { forceCreate: false, @@ -194,9 +197,16 @@ interface ListVersionsResponseBody { // === RemoteBackend === // ===================== +/** Information for a cached default version. */ +interface DefaultVersionInfo { + version: backendModule.VersionNumber + lastUpdatedEpochMs: number +} + /** Class for sending requests to the Cloud backend API endpoints. */ export class RemoteBackend extends backendModule.Backend { readonly type = backendModule.BackendType.remote + protected defaultVersions: Partial> = {} /** Create a new instance of the {@link RemoteBackend} API client. * @@ -471,29 +481,19 @@ export class RemoteBackend extends backendModule.Backend { } else { const project = await response.json() const ideVersion = - project.ide_version ?? - ( - await this.listVersions({ - versionType: backendModule.VersionType.ide, - default: true, - }) - )[0]?.number - if (ideVersion == null) { - return this.throw('No IDE version found') - } else { - return { - ...project, - ideVersion, - engineVersion: project.engine_version, - jsonAddress: - project.address != null - ? backendModule.Address(`${project.address}json`) - : null, - binaryAddress: - project.address != null - ? backendModule.Address(`${project.address}binary`) - : null, - } + project.ide_version ?? (await this.getDefaultVersion(backendModule.VersionType.ide)) + return { + ...project, + ideVersion, + engineVersion: project.engine_version, + jsonAddress: + project.address != null + ? backendModule.Address(`${project.address}json`) + : null, + binaryAddress: + project.address != null + ? backendModule.Address(`${project.address}binary`) + : null, } } } @@ -775,6 +775,32 @@ export class RemoteBackend extends backendModule.Backend { } } + /** Get the default version given the type of version (IDE or backend). */ + protected async getDefaultVersion(versionType: backendModule.VersionType) { + const cached = this.defaultVersions[versionType] + const nowEpochMs = Number(new Date()) + if (cached != null && nowEpochMs - cached.lastUpdatedEpochMs < ONE_DAY_MS) { + return cached.version + } else { + const version = ( + await this.listVersions({ + versionType, + default: true, + }) + )[0]?.number + if (version == null) { + throw new Error(`No default ${versionType} version found.`) + } else { + const info: DefaultVersionInfo = { + version, + lastUpdatedEpochMs: nowEpochMs, + } + this.defaultVersions[versionType] = info + return info.version + } + } + } + /** Send an HTTP GET request to the given path. */ private get(path: string) { return this.client.get(`${config.ACTIVE_CONFIG.apiUrl}/${path}`)