Skip to content

Commit

Permalink
Improve server API detection to prefer REST by default
Browse files Browse the repository at this point in the history
Previously, we used GraphQL by default, and we didn't wait to check - to
the initial version & config requests were both sent via GraphQL, and
then only subsequent requests switched to REST, after the version had
been checked.

Most users are using the REST server now, and it's best to simplify and
use just that single API wherever possible, so this should clean things
up a bit. Adds perhaps 11ms in startup time but that seems negligible
and there are other steps running in parallel anyway.
  • Loading branch information
pimterry committed Oct 5, 2023
1 parent 504213c commit 97cfd47
Showing 1 changed file with 31 additions and 14 deletions.
45 changes: 31 additions & 14 deletions src/services/server-api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as localForage from 'localforage';

import { RUNNING_IN_WORKER } from '../util';
import { getDeferred } from '../util/promise';
import { delay, getDeferred } from '../util/promise';
import {
versionSatisfies,
SERVER_REST_API_SUPPORTED
Expand Down Expand Up @@ -35,22 +35,39 @@ const serverReady = getDeferred();
export const announceServerReady = () => serverReady.resolve();
export const waitUntilServerReady = () => serverReady.promise;

// We initially default to the GQL API. If at the first version lookup we discover that the REST
// API is supported, this is swapped out for the REST client instead. Both work, but REST is the
// goal long-term so should be preferred where available.
let apiClient: Promise<GraphQLApiClient | RestApiClient> = authTokenPromise
.then((authToken) => new GraphQLApiClient(authToken));
export async function getServerVersion(): Promise<string> {
const client = await apiClient;
const version = await client.getServerVersion();
const apiClient: Promise<GraphQLApiClient | RestApiClient> = authTokenPromise.then(async (authToken) => {
await waitUntilServerReady();

const restClient = new RestApiClient(authToken);
const graphQLClient = new GraphQLApiClient(authToken);

// To work out which API is supported, we loop trying to get the version from
// each one (may take a couple of tries as the server starts up), and then
// check the resulting version to see what's supported.

let version: string | undefined;
while (!version) {
version = await restClient.getServerVersion().catch(() => {
console.log("Couldn't get version from REST API");

return graphQLClient.getServerVersion().catch(() => {
console.log("Couldn't get version from GraphQL API");
return undefined;
});
});

// Swap to the REST client if we receive a version where it's supported:
if (versionSatisfies(version, SERVER_REST_API_SUPPORTED) && client instanceof GraphQLApiClient) {
apiClient = authTokenPromise
.then((authToken) => new RestApiClient(authToken));
if (!version) await delay(100);
}

return version;
if (versionSatisfies(version, SERVER_REST_API_SUPPORTED)) {
return restClient;
} else {
return graphQLClient;
}
});

export async function getServerVersion(): Promise<string> {
return (await apiClient).getServerVersion();
}

export async function getConfig(proxyPort: number): Promise<ServerConfig> {
Expand Down

0 comments on commit 97cfd47

Please sign in to comment.