summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-03-27 15:46:33 +0100
committerAndrej Mihajlov <and@mullvad.net>2019-04-01 13:55:12 +0200
commitc54a8e8af8ed5e53151ded7f66d9eea7cf7a5d20 (patch)
tree6a155396bedff004b0f733ad7fc304b8cc215336 /gui/src/renderer
parentbcf731749bddebb2eb25ccc6a5b83b45de8fdb0e (diff)
downloadmullvadvpn-c54a8e8af8ed5e53151ded7f66d9eea7cf7a5d20.tar.xz
mullvadvpn-c54a8e8af8ed5e53151ded7f66d9eea7cf7a5d20.zip
Fix tests
Diffstat (limited to 'gui/src/renderer')
-rw-r--r--gui/src/renderer/app.tsx121
-rw-r--r--gui/src/renderer/lib/account-data-cache.ts118
-rw-r--r--gui/src/renderer/lib/auth-failure.ts3
3 files changed, 122 insertions, 120 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 7d2cd2a69a..54b2743467 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -25,11 +25,11 @@ import { IWindowShapeParameters } from '../main/window-controller';
import { loadTranslations } from '../shared/gettext';
import { IGuiSettingsState } from '../shared/gui-settings-state';
import { IpcRendererEventChannel } from '../shared/ipc-event-channel';
+import AccountDataCache, { AccountFetchRetryAction } from './lib/account-data-cache';
import AccountExpiry from './lib/account-expiry';
import {
AccountToken,
- IAccountData,
ILocation,
IRelayList,
ISettings,
@@ -38,6 +38,8 @@ import {
TunnelStateTransition,
} from '../shared/daemon-rpc-types';
+type AccountVerification = { status: 'verified' } | { status: 'deferred'; error: Error };
+
export default class AppRenderer {
private memoryHistory = createMemoryHistory();
private reduxStore = configureStore(this.memoryHistory);
@@ -597,120 +599,3 @@ export default class AppRenderer {
this.reduxActions.settings.updateAutoStart(autoStart);
}
}
-
-type AccountVerification = { status: 'verified' } | { status: 'deferred'; error: Error };
-export enum AccountFetchRetryAction {
- stop,
- retry,
-}
-interface IAccountFetchWatcher {
- onFinish: () => void;
- onError: (error: Error) => AccountFetchRetryAction;
-}
-
-// An account data cache that helps to throttle RPC requests to get_account_data and retain the
-// cached value for 1 minute.
-export class AccountDataCache {
- private currentAccount?: AccountToken;
- private expiresAt?: Date;
- private fetchAttempt = 0;
- private fetchRetryTimeout?: NodeJS.Timeout;
- private watchers: IAccountFetchWatcher[] = [];
-
- constructor(
- private fetchHandler: (token: AccountToken) => Promise<IAccountData>,
- private updateHandler: (data?: IAccountData) => void,
- ) {}
-
- public fetch(accountToken: AccountToken, watcher?: IAccountFetchWatcher) {
- // invalidate cache if account token has changed
- if (accountToken !== this.currentAccount) {
- this.invalidate();
- this.currentAccount = accountToken;
- }
-
- // Only fetch is value has expired
- if (this.isExpired()) {
- if (watcher) {
- this.watchers.push(watcher);
- }
-
- this.performFetch(accountToken);
- } else if (watcher) {
- watcher.onFinish();
- }
- }
-
- public invalidate() {
- if (this.fetchRetryTimeout) {
- clearTimeout(this.fetchRetryTimeout);
- this.fetchRetryTimeout = undefined;
- this.fetchAttempt = 0;
- }
-
- this.expiresAt = undefined;
- this.updateHandler();
- this.notifyWatchers((watcher) => {
- watcher.onError(new Error('Cancelled'));
- });
- }
-
- private setValue(value: IAccountData) {
- this.expiresAt = new Date(Date.now() + 60 * 1000); // 60s expiration
- this.updateHandler(value);
- this.notifyWatchers((watcher) => watcher.onFinish());
- }
-
- private isExpired() {
- return !this.expiresAt || this.expiresAt < new Date();
- }
-
- private async performFetch(accountToken: AccountToken) {
- try {
- // it's possible for invalidate() to be called or for a fetch for a different account token
- // to start before this fetch completes, so checking if the current account token is the one
- // used is necessary below.
- const accountData = await this.fetchHandler(accountToken);
-
- if (this.currentAccount === accountToken) {
- this.setValue(accountData);
- }
- } catch (error) {
- if (this.currentAccount === accountToken) {
- this.handleFetchError(accountToken, error);
- }
- }
- }
-
- private handleFetchError(accountToken: AccountToken, error: any) {
- let shouldRetry = true;
-
- this.notifyWatchers((watcher) => {
- if (watcher.onError(error) === AccountFetchRetryAction.stop) {
- shouldRetry = false;
- }
- });
-
- if (shouldRetry) {
- this.scheduleRetry(accountToken);
- }
- }
-
- private scheduleRetry(accountToken: AccountToken) {
- this.fetchAttempt += 1;
-
- // tslint:disable-next-line
- const delay = Math.min(2048, 1 << (this.fetchAttempt + 2)) * 1000;
-
- log.warn(`Failed to fetch account data. Retrying in ${delay} ms`);
-
- this.fetchRetryTimeout = global.setTimeout(() => {
- this.fetchRetryTimeout = undefined;
- this.performFetch(accountToken);
- }, delay);
- }
-
- private notifyWatchers(notify: (watcher: IAccountFetchWatcher) => void) {
- this.watchers.splice(0).forEach(notify);
- }
-}
diff --git a/gui/src/renderer/lib/account-data-cache.ts b/gui/src/renderer/lib/account-data-cache.ts
new file mode 100644
index 0000000000..51154c9792
--- /dev/null
+++ b/gui/src/renderer/lib/account-data-cache.ts
@@ -0,0 +1,118 @@
+import log from 'electron-log';
+import { AccountToken, IAccountData } from '../../shared/daemon-rpc-types';
+
+export enum AccountFetchRetryAction {
+ stop,
+ retry,
+}
+interface IAccountFetchWatcher {
+ onFinish: () => void;
+ onError: (error: Error) => AccountFetchRetryAction;
+}
+
+// An account data cache that helps to throttle RPC requests to get_account_data and retain the
+// cached value for 1 minute.
+export default class AccountDataCache {
+ private currentAccount?: AccountToken;
+ private expiresAt?: Date;
+ private fetchAttempt = 0;
+ private fetchRetryTimeout?: NodeJS.Timeout;
+ private watchers: IAccountFetchWatcher[] = [];
+
+ constructor(
+ private fetchHandler: (token: AccountToken) => Promise<IAccountData>,
+ private updateHandler: (data?: IAccountData) => void,
+ ) {}
+
+ public fetch(accountToken: AccountToken, watcher?: IAccountFetchWatcher) {
+ // invalidate cache if account token has changed
+ if (accountToken !== this.currentAccount) {
+ this.invalidate();
+ this.currentAccount = accountToken;
+ }
+
+ // Only fetch is value has expired
+ if (this.isExpired()) {
+ if (watcher) {
+ this.watchers.push(watcher);
+ }
+
+ this.performFetch(accountToken);
+ } else if (watcher) {
+ watcher.onFinish();
+ }
+ }
+
+ public invalidate() {
+ if (this.fetchRetryTimeout) {
+ clearTimeout(this.fetchRetryTimeout);
+ this.fetchRetryTimeout = undefined;
+ this.fetchAttempt = 0;
+ }
+
+ this.expiresAt = undefined;
+ this.updateHandler();
+ this.notifyWatchers((watcher) => {
+ watcher.onError(new Error('Cancelled'));
+ });
+ }
+
+ private setValue(value: IAccountData) {
+ this.expiresAt = new Date(Date.now() + 60 * 1000); // 60s expiration
+ this.updateHandler(value);
+ this.notifyWatchers((watcher) => watcher.onFinish());
+ }
+
+ private isExpired() {
+ return !this.expiresAt || this.expiresAt < new Date();
+ }
+
+ private async performFetch(accountToken: AccountToken) {
+ try {
+ // it's possible for invalidate() to be called or for a fetch for a different account token
+ // to start before this fetch completes, so checking if the current account token is the one
+ // used is necessary below.
+ const accountData = await this.fetchHandler(accountToken);
+
+ if (this.currentAccount === accountToken) {
+ this.setValue(accountData);
+ }
+ } catch (error) {
+ if (this.currentAccount === accountToken) {
+ this.handleFetchError(accountToken, error);
+ }
+ }
+ }
+
+ private handleFetchError(accountToken: AccountToken, error: any) {
+ let shouldRetry = true;
+
+ this.notifyWatchers((watcher) => {
+ if (watcher.onError(error) === AccountFetchRetryAction.stop) {
+ shouldRetry = false;
+ }
+ });
+
+ if (shouldRetry) {
+ this.scheduleRetry(accountToken);
+ }
+ }
+
+ private scheduleRetry(accountToken: AccountToken) {
+ this.fetchAttempt += 1;
+
+ // tslint:disable-next-line
+ const delay = Math.min(2048, 1 << (this.fetchAttempt + 2)) * 1000;
+
+ log.warn(`Failed to fetch account data. Retrying in ${delay} ms`);
+
+ this.fetchRetryTimeout = global.setTimeout(() => {
+ this.fetchRetryTimeout = undefined;
+ this.performFetch(accountToken);
+ }, delay);
+ }
+
+ private notifyWatchers(notify: (watcher: IAccountFetchWatcher) => void) {
+ this.watchers.splice(0).forEach(notify);
+ }
+}
diff --git a/gui/src/renderer/lib/auth-failure.ts b/gui/src/renderer/lib/auth-failure.ts
index ae381d5677..6428d0f65a 100644
--- a/gui/src/renderer/lib/auth-failure.ts
+++ b/gui/src/renderer/lib/auth-failure.ts
@@ -18,8 +18,7 @@ export function parseAuthFailure(rawFailureMessage?: string): IAuthFailure {
if (results && results.length === 3) {
const kind = parseRawFailureKind(results[1]);
- const message =
- kind === AuthFailureKind.unknown ? rawFailureMessage : messageForFailureKind(kind);
+ const message = kind === AuthFailureKind.unknown ? results[2] : messageForFailureKind(kind);
return {
kind,