Skip to content

Commit e321eed

Browse files
committed
fix(compass-global-writes): handle loading error COMPASS-8446
1 parent 618a683 commit e321eed

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

@@ -586,6 +610,25 @@ const reducer: Reducer<RootState, Action> = (state = initialState, action) => {
586610
};
587611
}
588612

613+
if (
614+
isAction<LoadingFailedAction>(
615+
action,
616+
GlobalWritesActionTypes.LoadingFailed
617+
) &&
618+
(state.status === ShardingStatuses.NOT_READY ||
619+
state.status === ShardingStatuses.SHARDING)
620+
) {
621+
if (state.pollingTimeout) {
622+
throw new Error('Polling was not stopped');
623+
}
624+
return {
625+
...state,
626+
status: ShardingStatuses.LOADING_ERROR,
627+
error: action.error,
628+
pollingTimeout: state.pollingTimeout,
629+
};
630+
}
631+
589632
return state;
590633
};
591634

@@ -614,17 +657,11 @@ export const fetchClusterShardingData =
614657
'Error fetching cluster sharding data',
615658
(error as Error).message
616659
);
617-
openToast(
618-
`global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
619-
{
620-
title: `Failed to fetch sharding information: ${
621-
(error as Error).message
622-
}`,
623-
dismissible: true,
624-
timeout: 5000,
625-
variant: 'important',
626-
}
627-
);
660+
handleLoadingError({
661+
error: error as Error,
662+
id: `global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
663+
description: 'Failed to fetch sharding information',
664+
});
628665
}
629666
};
630667

@@ -799,6 +836,39 @@ const stopPollingForShardKey = (): GlobalWritesThunkAction<
799836
};
800837
};
801838

839+
const handleLoadingError = ({
840+
error,
841+
id,
842+
description,
843+
}: {
844+
error: Error;
845+
id: string;
846+
description: string;
847+
}): GlobalWritesThunkAction<void, LoadingFailedAction> => {
848+
return (dispatch, getState) => {
849+
const { status } = getState();
850+
const isPolling = status === ShardingStatuses.SHARDING;
851+
const isInitialLoad = status === ShardingStatuses.NOT_READY;
852+
const errorMessage = `${description} ${error.message}`;
853+
if (isInitialLoad || isPolling) {
854+
if (isPolling) {
855+
dispatch(stopPollingForShardKey());
856+
}
857+
dispatch({
858+
type: GlobalWritesActionTypes.LoadingFailed,
859+
error: errorMessage,
860+
});
861+
return;
862+
}
863+
openToast(id, {
864+
title: errorMessage,
865+
dismissible: true,
866+
timeout: 5000,
867+
variant: 'important',
868+
});
869+
};
870+
};
871+
802872
export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
803873
Promise<void>,
804874
NamespaceShardingErrorFetchedAction | NamespaceShardKeyFetchedAction
@@ -852,15 +922,11 @@ export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
852922
'Error fetching shard key',
853923
(error as Error).message
854924
);
855-
openToast(
856-
`global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
857-
{
858-
title: `Failed to fetch shard key: ${(error as Error).message}`,
859-
dismissible: true,
860-
timeout: 5000,
861-
variant: 'important',
862-
}
863-
);
925+
handleLoadingError({
926+
error: error as Error,
927+
id: `global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
928+
description: 'Failed to fetch shard key',
929+
});
864930
}
865931
};
866932
};

0 commit comments

Comments
 (0)