Skip to content

Commit edaaadc

Browse files
committed
fix(compass-global-writes): handle loading error COMPASS-8446
1 parent 9c7339f commit edaaadc

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:
@@ -220,6 +240,7 @@ export type RootState = {
220240
// and then unmanaged
221241
shardingError?: never;
222242
pollingTimeout?: never;
243+
error?: never;
223244
}
224245
| {
225246
status: ShardingStatuses.SHARDING;
@@ -230,6 +251,7 @@ export type RootState = {
230251
shardKey?: ShardKey;
231252
shardingError?: never;
232253
pollingTimeout?: NodeJS.Timeout;
254+
error?: never;
233255
}
234256
| {
235257
status:
@@ -239,6 +261,7 @@ export type RootState = {
239261
shardKey?: never;
240262
shardingError: string;
241263
pollingTimeout?: never;
264+
error?: never;
242265
}
243266
| {
244267
status:
@@ -252,6 +275,7 @@ export type RootState = {
252275
shardKey: ShardKey;
253276
shardingError?: never;
254277
pollingTimeout?: never;
278+
error?: never;
255279
}
256280
);
257281

@@ -599,6 +623,25 @@ const reducer: Reducer<RootState, Action> = (state = initialState, action) => {
599623
};
600624
}
601625

626+
if (
627+
isAction<LoadingFailedAction>(
628+
action,
629+
GlobalWritesActionTypes.LoadingFailed
630+
) &&
631+
(state.status === ShardingStatuses.NOT_READY ||
632+
state.status === ShardingStatuses.SHARDING)
633+
) {
634+
if (state.pollingTimeout) {
635+
throw new Error('Polling was not stopped');
636+
}
637+
return {
638+
...state,
639+
status: ShardingStatuses.LOADING_ERROR,
640+
error: action.error,
641+
pollingTimeout: state.pollingTimeout,
642+
};
643+
}
644+
602645
return state;
603646
};
604647

@@ -627,17 +670,11 @@ export const fetchClusterShardingData =
627670
'Error fetching cluster sharding data',
628671
(error as Error).message
629672
);
630-
openToast(
631-
`global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
632-
{
633-
title: `Failed to fetch sharding information: ${
634-
(error as Error).message
635-
}`,
636-
dismissible: true,
637-
timeout: 5000,
638-
variant: 'important',
639-
}
640-
);
673+
handleLoadingError({
674+
error: error as Error,
675+
id: `global-writes-fetch-shard-info-error-${connectionInfoRef.current.id}-${namespace}`,
676+
description: 'Failed to fetch sharding information',
677+
});
641678
}
642679
};
643680

@@ -812,6 +849,39 @@ const stopPollingForShardKey = (): GlobalWritesThunkAction<
812849
};
813850
};
814851

852+
const handleLoadingError = ({
853+
error,
854+
id,
855+
description,
856+
}: {
857+
error: Error;
858+
id: string;
859+
description: string;
860+
}): GlobalWritesThunkAction<void, LoadingFailedAction> => {
861+
return (dispatch, getState) => {
862+
const { status } = getState();
863+
const isPolling = status === ShardingStatuses.SHARDING;
864+
const isInitialLoad = status === ShardingStatuses.NOT_READY;
865+
const errorMessage = `${description} ${error.message}`;
866+
if (isInitialLoad || isPolling) {
867+
if (isPolling) {
868+
dispatch(stopPollingForShardKey());
869+
}
870+
dispatch({
871+
type: GlobalWritesActionTypes.LoadingFailed,
872+
error: errorMessage,
873+
});
874+
return;
875+
}
876+
openToast(id, {
877+
title: errorMessage,
878+
dismissible: true,
879+
timeout: 5000,
880+
variant: 'important',
881+
});
882+
};
883+
};
884+
815885
export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
816886
Promise<void>,
817887
NamespaceShardingErrorFetchedAction | NamespaceShardKeyFetchedAction
@@ -865,15 +935,11 @@ export const fetchNamespaceShardKey = (): GlobalWritesThunkAction<
865935
'Error fetching shard key',
866936
(error as Error).message
867937
);
868-
openToast(
869-
`global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
870-
{
871-
title: `Failed to fetch shard key: ${(error as Error).message}`,
872-
dismissible: true,
873-
timeout: 5000,
874-
variant: 'important',
875-
}
876-
);
938+
handleLoadingError({
939+
error: error as Error,
940+
id: `global-writes-fetch-shard-key-error-${connectionInfoRef.current.id}-${namespace}`,
941+
description: 'Failed to fetch shard key',
942+
});
877943
}
878944
};
879945
};

0 commit comments

Comments
 (0)