Skip to content

Commit

Permalink
fix(common): CHECKOUT-4412 Retry if unable to load asset chunk
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchin committed Sep 10, 2019
1 parent f10c16b commit f253041
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 16 deletions.
25 changes: 13 additions & 12 deletions src/app/checkout/Checkout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { NoopStepTracker, StepTracker } from '../analytics';
import { StaticBillingAddress } from '../billing';
import { EmptyCartMessage } from '../cart';
import { ErrorLogger, ErrorModal } from '../common/error';
import { retry } from '../common/utility';
import { CustomerInfo, CustomerSignOutEvent, CustomerViewType } from '../customer';
import { isEmbedded, EmbeddedCheckoutStylesheet } from '../embeddedCheckout';
import { withLanguage, TranslatedString, WithLanguageProps } from '../locale';
Expand All @@ -24,35 +25,35 @@ import CheckoutStepStatus from './CheckoutStepStatus';
import CheckoutStepType from './CheckoutStepType';
import CheckoutSupport from './CheckoutSupport';

const Billing = lazy(() => import(
const Billing = lazy(() => retry(() => import(
/* webpackChunkName: "billing" */
'../billing/Billing'
));
)));

const CartSummary = lazy(() => import(
const CartSummary = lazy(() => retry(() => import(
/* webpackChunkName: "cart-summary" */
'../cart/CartSummary'
));
)));

const CartSummaryDrawer = lazy(() => import(
const CartSummaryDrawer = lazy(() => retry(() => import(
/* webpackChunkName: "cart-summary-drawer" */
'../cart/CartSummaryDrawer'
));
)));

const Customer = lazy(() => import(
const Customer = lazy(() => retry(() => import(
/* webpackChunkName: "customer" */
'../customer/Customer'
));
)));

const Payment = lazy(() => import(
const Payment = lazy(() => retry(() => import(
/* webpackChunkName: "payment" */
'../payment/Payment'
));
)));

const Shipping = lazy(() => import(
const Shipping = lazy(() => retry(() => import(
/* webpackChunkName: "shipping" */
'../shipping/Shipping'
));
)));

export interface CheckoutProps {
checkoutId: string;
Expand Down
5 changes: 5 additions & 0 deletions src/app/common/utility/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
import { RetryOptions } from './retry';

export type RetryOptions = RetryOptions;

export * from './emptyData';
export { default as retry } from './retry';
38 changes: 38 additions & 0 deletions src/app/common/utility/retry.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import retry from './retry';

describe('retry()', () => {
it('retries async call for specified number of times', async () => {
const error = new Error('Request timeout');
const call = jest.fn(() => Promise.reject(error));

try {
await retry(() => call(), { count: 3, interval: 1 });
} catch (thrown) {
expect(call)
.toHaveBeenCalledTimes(3);
expect(thrown)
.toEqual(error);
}
});

it('stops retrying async call if it succeeds', async () => {
let times = 0;

const response = 'Foobar';
const error = new Error('Request timeout');
const call = jest.fn(() => {
times++;

return times === 2 ?
Promise.resolve(response) :
Promise.reject(error);
});

const output = await retry(() => call(), { interval: 1 });

expect(call)
.toHaveBeenCalledTimes(2);
expect(output)
.toEqual(response);
});
});
28 changes: 28 additions & 0 deletions src/app/common/utility/retry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const DEFAULT_OPTIONS = {
count: 5,
interval: 1000,
};

export interface RetryOptions {
count?: number;
interval?: number;
}

export default async function retry<T>(
fn: () => Promise<T>,
options?: RetryOptions
): Promise<T> {
const { count, interval } = { ...DEFAULT_OPTIONS, ...options };

try {
return await fn();
} catch (error) {
if (count === 1) {
throw error;
}

await new Promise(resolve => setTimeout(resolve, interval));

return retry(fn, { interval, count: count - 1 });
}
}
9 changes: 5 additions & 4 deletions src/app/order/OrderConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { lazy, Component, Fragment, ReactNode, Suspense } from 'react';
import { StepTracker } from '../analytics';
import { withCheckout, CheckoutContextProps } from '../checkout';
import { ErrorLogger, ErrorModal } from '../common/error';
import { retry } from '../common/utility';
import { isEmbedded, EmbeddedCheckoutStylesheet } from '../embeddedCheckout';
import { CreatedCustomer, GuestSignUpForm, SignedUpSuccessAlert, SignUpFormValues } from '../guestSignup';
import { AccountCreationFailedError, AccountCreationRequirementsError } from '../guestSignup/errors';
Expand All @@ -21,15 +22,15 @@ import OrderStatus from './OrderStatus';
import PrintLink from './PrintLink';
import ThankYouHeader from './ThankYouHeader';

const OrderSummary = lazy(() => import(
const OrderSummary = lazy(() => retry(() => import(
/* webpackChunkName: "order-summary" */
'./OrderSummary'
));
)));

const OrderSummaryDrawer = lazy(() => import(
const OrderSummaryDrawer = lazy(() => retry(() => import(
/* webpackChunkName: "order-summary-drawer" */
'./OrderSummaryDrawer'
));
)));

export interface OrderConfirmationState {
error?: Error;
Expand Down

0 comments on commit f253041

Please sign in to comment.