From 2f7dd54e370467ab7833e02a90e2c41e3964c9fd Mon Sep 17 00:00:00 2001 From: Pagan Gazzard Date: Mon, 4 May 2020 14:40:12 +0100 Subject: [PATCH] Cache username for a given auth to avoid fetching it every time Change-type: patch --- lib/events.ts | 47 +++++++++++++++++++++++++++++++++++----- tests/balena-api-mock.ts | 2 +- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/events.ts b/lib/events.ts index 5087ca56..0f7cf061 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -29,6 +29,11 @@ const getMixpanel = _.once((balenaUrl: string) => { }); }); +interface CachedUsername { + token: string; + username: string; +} + /** * Mixpanel.com analytics tracking (information on balena CLI usage). * @@ -48,14 +53,44 @@ export async function trackCommand(commandSignature: string) { Sentry.configureScope((scope) => { scope.setExtra('command', commandSignature); }); - const balena = getBalenaSdk(); - const balenaUrlPromise = balena.settings.get('balenaUrl'); + const settings = await import('balena-settings-client'); + const balenaUrl = settings.get('balenaUrl') as string; + return Bluebird.props({ - balenaUrl: balenaUrlPromise, - username: balena.auth.whoami().catchReturn(undefined), - mixpanel: balenaUrlPromise.then(getMixpanel), + username: (async () => { + const getStorage = await import('balena-settings-storage'); + const dataDirectory = settings.get('dataDirectory') as string; + const storage = getStorage({ dataDirectory }); + let token; + try { + token = await storage.get('token'); + } catch { + // If we can't get a token then we can't get a username + return; + } + try { + const result = (await storage.get('cachedUsername')) as CachedUsername; + if (result.token === token) { + return result.username; + } + } catch { + // ignore + } + try { + const balena = getBalenaSdk(); + const username = await balena.auth.whoami(); + storage.set('cachedUsername', { + token, + username, + } as CachedUsername); + return username; + } catch { + return; + } + })(), + mixpanel: getMixpanel(balenaUrl), }) - .then(({ username, balenaUrl, mixpanel }) => { + .then(({ username, mixpanel }) => { Sentry.configureScope((scope) => { scope.setUser({ id: username, diff --git a/tests/balena-api-mock.ts b/tests/balena-api-mock.ts index eabac375..09227ffe 100644 --- a/tests/balena-api-mock.ts +++ b/tests/balena-api-mock.ts @@ -336,7 +336,7 @@ export class BalenaAPIMock extends NockMock { // User details are cached in the SDK // so often we don't know if we can expect the whoami request - public expectGetWhoAmI(opts: ScopeOpts = {}) { + public expectGetWhoAmI(opts: ScopeOpts = { optional: true }) { this.optGet('/user/v1/whoami', opts).reply(200, { id: 99999, username: 'gh_user',