Skip to content

Commit e61e093

Browse files
committed
fix(compass-global-writes): handle loading error COMPASS-8446
1 parent 0d21433 commit e61e093

File tree

3 files changed

+117
-20
lines changed

3 files changed

+117
-20
lines changed

packages/compass-global-writes/src/components/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import ShardKeyInvalid from './states/shard-key-invalid';
1616
import ShardKeyMismatch from './states/shard-key-mismatch';
1717
import ShardingError from './states/sharding-error';
1818
import IncompleteShardingSetup from './states/incomplete-sharding-setup';
19+
import LoadingError from './states/loading-error';
1920

2021
const containerStyles = css({
2122
paddingLeft: spacing[400],
@@ -101,6 +102,10 @@ function ShardingStateView({
101102
return <IncompleteShardingSetup />;
102103
}
103104

105+
if (shardingStatus === ShardingStatuses.LOADING_ERROR) {
106+
return <LoadingError />;
107+
}
108+
104109
return null;
105110
}
106111

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import { ErrorSummary } from '@mongodb-js/compass-components';
3+
import { connect } from 'react-redux';
4+
import { type RootState, ShardingStatuses } from '../../store/reducer';
5+
import { containerStyles } from '../common-styles';
6+
7+
interface LoadingErrorProps {
8+
error: string;
9+
}
10+
11+
export function LoadingError({ error }: LoadingErrorProps) {
12+
return (
13+
<div className={containerStyles}>
14+
<ErrorSummary errors={error} />
15+
</div>
16+
);
17+
}
18+
19+
export default connect((state: RootState) => {
20+
if (state.status !== ShardingStatuses.LOADING_ERROR) {
21+
throw new Error('Error not found in LoadingError');
22+
}
23+
return {
24+
error: state.error,
25+
};
26+
})(LoadingError);

packages/compass-global-writes/src/store/reducer.ts

Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,20 @@ enum GlobalWritesActionTypes {
4545
UnmanagingNamespaceStarted = 'global-writes/UnmanagingNamespaceStarted',
4646
UnmanagingNamespaceFinished = 'global-writes/UnmanagingNamespaceFinished',
4747
UnmanagingNamespaceErrored = 'global-writes/UnmanagingNamespaceErrored',
48+
49+
LoadingFailed = 'global-writes/LoadingFailed',
4850
}
4951

5052
type ManagedNamespaceFetchedAction = {
5153
type: GlobalWritesActionTypes.ManagedNamespaceFetched;
5254
managedNamespace?: ManagedNamespace;
5355
};
5456

57+
type LoadingFailedAction = {
58+
type: GlobalWritesActionTypes.LoadingFailed;
59+
error: string;
60+
};
61+
5562
type NamespaceShardingErrorFetchedAction = {
5663
type: GlobalWritesActionTypes.NamespaceShardingErrorFetched;
5764
error: string;
@@ -120,6 +127,11 @@ export enum ShardingStatuses {
120127
*/
121128
NOT_READY = 'NOT_READY',
122129

130+
/**
131+
* The status could not be determined because loading failed
132+
*/
133+
LOADING_ERROR = 'LOADING_ERROR',
134+
123135
/**
124136
* Namespace is not geo-sharded.
125137
*/
@@ -204,11 +216,19 @@ export type RootState = {
204216
managedNamespace?: ManagedNamespace;
205217
shardZones: ShardZoneData[];
206218
} & (
219+
| {
220+
status: ShardingStatuses.LOADING_ERROR;
221+
shardKey?: ShardKey;
222+
shardingError?: never;
223+
pollingTimeout?: never;
224+
error: string;
225+
}
207226
| {
208227
status: ShardingStatuses.NOT_READY;
209228
shardKey?: never;
210229
shardingError?: never;
211230
pollingTimeout?: never;
231+
error?: never;
212232
}
213233
| {
214234
status:
@@ -222,6 +242,7 @@ export type RootState = {
222242
shardKey?: ShardKey;
223243
shardingError?: never;
224244
pollingTimeout?: never;
245+
error?: never;
225246
}
226247
| {
227248
status: ShardingStatuses.SHARDING;
@@ -232,6 +253,7 @@ export type RootState = {
232253
shardKey?: ShardKey;
233254
shardingError?: never;
234255
pollingTimeout?: NodeJS.Timeout;
256+
error?: never;
235257
}
236258
| {
237259
status:
@@ -241,6 +263,7 @@ export type RootState = {
241263
shardKey?: never;
242264
shardingError: string;
243265
pollingTimeout?: never;
266+
error?: never;
244267
}
245268
| {
246269
status:
@@ -254,6 +277,7 @@ export type RootState = {
254277
shardKey: ShardKey;
255278
shardingError?: never;
256279
pollingTimeout?: never;
280+
error?: never;
257281
}
258282
);
259283

@@ -556,6 +580,25 @@ const reducer: Reducer<RootState, Action> = (state = initialState, action) => {
556580
};
557581
}
558582

583+
if (
584+
isAction<LoadingFailedAction>(
585+
action,
586+
GlobalWritesActionTypes.LoadingFailed
587+
) &&
588+
(state.status === ShardingStatuses.NOT_READY ||
589+
state.status === ShardingStatuses.SHARDING)
590+
) {
591+
if (state.pollingTimeout) {
592+
throw new Error('Polling was not stopped');
593+
}
594+
return {
595+
...state,
596+
status: ShardingStatuses.LOADING_ERROR,
597+
error: action.error,
598+
pollingTimeout: state.pollingTimeout,
599+
};
600+
}
601+
559602
return state;
560603
};
561604

@@ -584,17 +627,11 @@ export const fetchClusterShardingData =
584627
'Error fetching cluster sharding data',
585628
(error as Error).message
586629
);
587-
openToast(
588-
`global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
589-
{
590-
title: `Failed to fetch sharding information: ${
591-
(error as Error).message
592-
}`,
593-
dismissible: true,
594-
timeout: 5000,
595-
variant: 'important',
596-
}
597-
);
630+
handleLoadingError({
631+
error: error as Error,
632+
id: `global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
633+
description: 'Failed to fetch sharding information',
634+
});
598635
}
599636
};
600637

@@ -769,6 +806,39 @@ const stopPollingForShardKey = (): GlobalWritesThunkAction<
769806
};
770807
};
771808

809+
const handleLoadingError = ({
810+
error,
811+
id,
812+
description,
813+
}: {
814+
error: Error;
815+
id: string;
816+
description: string;
817+
}): GlobalWritesThunkAction<void, LoadingFailedAction> => {
818+
return (dispatch, getState) => {
819+
const { status } = getState();
820+
const isPolling = status === ShardingStatuses.SHARDING;
821+
const isInitialLoad = status === ShardingStatuses.NOT_READY;
822+
const errorMessage = `${description} ${error.message}`;
823+
if (isInitialLoad || isPolling) {
824+
if (isPolling) {
825+
dispatch(stopPollingForShardKey());
826+
}
827+
dispatch({
828+
type: GlobalWritesActionTypes.LoadingFailed,
829+
error: errorMessage,
830+
});
831+
return;
832+
}
833+
openToast(id, {
834+
title: errorMessage,
835+
dismissible: true,
836+
timeout: 5000,
837+
variant: 'important',
838+
});
839+
};
840+
};
841+
772842
export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
773843
Promise<void>,
774844
NamespaceShardingErrorFetchedAction | NamespaceShardKeyFetchedAction
@@ -822,15 +892,11 @@ export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
822892
'Error fetching shard key',
823893
(error as Error).message
824894
);
825-
openToast(
826-
`global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
827-
{
828-
title: `Failed to fetch shard key: ${(error as Error).message}`,
829-
dismissible: true,
830-
timeout: 5000,
831-
variant: 'important',
832-
}
833-
);
895+
handleLoadingError({
896+
error: error as Error,
897+
id: `global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
898+
description: 'Failed to fetch shard key',
899+
});
834900
}
835901
};
836902
};

0 commit comments

Comments
 (0)