Skip to content

Commit c8420cf

Browse files
refactor: separate nodes selectors and utils (#472)
1 parent 30f8bc5 commit c8420cf

File tree

5 files changed

+127
-115
lines changed

5 files changed

+127
-115
lines changed

src/containers/Nodes/Nodes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import {AdditionalNodesInfo, isUnavailableNode, NodesUptimeFilterValues} from '.
2222

2323
import {
2424
getNodes,
25-
getFilteredPreparedNodesList,
2625
setNodesUptimeFilter,
2726
setSearchValue,
2827
resetNodesState,
2928
getComputeNodes,
3029
} from '../../store/reducers/nodes/nodes';
30+
import {selectFilteredNodes} from '../../store/reducers/nodes/selectors';
3131
import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
3232

3333
import {isDatabaseEntityType} from '../Tenant/utils/schema';
@@ -63,7 +63,7 @@ export const Nodes = ({path, type, additionalNodesInfo = {}}: NodesProps) => {
6363
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
6464
const {autorefresh} = useTypedSelector((state) => state.schema);
6565

66-
const nodes = useTypedSelector(getFilteredPreparedNodesList);
66+
const nodes = useTypedSelector(selectFilteredNodes);
6767

6868
const [useNodesEndpoint] = useSetting(USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY);
6969

src/store/reducers/nodes/nodes.ts

Lines changed: 4 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,12 @@
11
import type {Reducer} from 'redux';
2-
import {createSelector, Selector} from 'reselect';
3-
import {escapeRegExp} from 'lodash/fp';
42

53
import '../../../services/api';
6-
import {HOUR_IN_SECONDS} from '../../../utils/constants';
7-
import {calcUptime, calcUptimeInSeconds} from '../../../utils';
84
import {NodesUptimeFilterValues} from '../../../utils/nodes';
9-
import {EFlag} from '../../../types/api/enums';
105

11-
import type {ProblemFilterValue} from '../settings/types';
126
import {createRequestActionTypes, createApiRequest} from '../../utils';
13-
import {ProblemFilterValues} from '../settings/settings';
147

15-
import type {
16-
NodesAction,
17-
NodesApiRequestParams,
18-
NodesHandledResponse,
19-
NodesPreparedEntity,
20-
NodesStateSlice,
21-
NodesState,
22-
} from './types';
8+
import type {NodesAction, NodesApiRequestParams, NodesState} from './types';
9+
import {prepareComputeNodesData, prepareNodesData} from './utils';
2310

2411
export const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
2512

@@ -97,56 +84,15 @@ export function getNodes({tenant, visibleEntities, type = 'any'}: NodesApiReques
9784
return createApiRequest({
9885
request: window.api.getNodes({tenant, visibleEntities, type}),
9986
actions: FETCH_NODES,
100-
dataHandler: (data): NodesHandledResponse => {
101-
const rawNodes = data.Nodes || [];
102-
103-
const preparedNodes = rawNodes.map((node) => {
104-
return {
105-
...node?.SystemState,
106-
Tablets: node?.Tablets,
107-
NodeId: node?.NodeId,
108-
Uptime: calcUptime(node?.SystemState?.StartTime),
109-
TenantName: node?.SystemState?.Tenants?.[0],
110-
};
111-
});
112-
113-
return {
114-
Nodes: preparedNodes,
115-
TotalNodes: Number(data.TotalNodes) || preparedNodes.length,
116-
};
117-
},
87+
dataHandler: prepareNodesData,
11888
});
11989
}
12090

12191
export function getComputeNodes(path: string) {
12292
return createApiRequest({
12393
request: window.api.getCompute(path),
12494
actions: FETCH_NODES,
125-
dataHandler: (data): NodesHandledResponse => {
126-
const preparedNodes: NodesPreparedEntity[] = [];
127-
128-
if (data.Tenants) {
129-
for (const tenant of data.Tenants) {
130-
if (tenant && tenant.Nodes) {
131-
const tenantNodes = tenant.Nodes.map((node) => {
132-
return {
133-
...node,
134-
TenantName: tenant.Name,
135-
SystemState: node?.Overall,
136-
Uptime: calcUptime(node?.StartTime),
137-
};
138-
});
139-
140-
preparedNodes.push(...tenantNodes);
141-
}
142-
}
143-
}
144-
145-
return {
146-
Nodes: preparedNodes,
147-
TotalNodes: preparedNodes.length,
148-
};
149-
},
95+
dataHandler: prepareComputeNodesData,
15096
});
15197
}
15298

@@ -175,58 +121,4 @@ export const setSearchValue = (value: string) => {
175121
} as const;
176122
};
177123

178-
const getNodesUptimeFilter = (state: NodesStateSlice) => state.nodes.nodesUptimeFilter;
179-
const getSearchValue = (state: NodesStateSlice) => state.nodes.searchValue;
180-
const getNodesList = (state: NodesStateSlice) => state.nodes.data;
181-
182-
const filterNodesByProblemsStatus = (
183-
nodesList: NodesPreparedEntity[] = [],
184-
problemFilter: ProblemFilterValue,
185-
) => {
186-
if (problemFilter === ProblemFilterValues.ALL) {
187-
return nodesList;
188-
}
189-
190-
return nodesList.filter(({SystemState}) => {
191-
return SystemState && SystemState !== EFlag.Green;
192-
});
193-
};
194-
195-
export const filterNodesByUptime = <T extends {StartTime?: string}>(
196-
nodesList: T[] = [],
197-
nodesUptimeFilter: NodesUptimeFilterValues,
198-
) => {
199-
if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
200-
return nodesList;
201-
}
202-
return nodesList.filter(({StartTime}) => {
203-
return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
204-
});
205-
};
206-
207-
const filterNodesBySearchValue = (nodesList: NodesPreparedEntity[] = [], searchValue: string) => {
208-
if (!searchValue) {
209-
return nodesList;
210-
}
211-
const re = new RegExp(escapeRegExp(searchValue), 'i');
212-
213-
return nodesList.filter((node) => {
214-
return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
215-
});
216-
};
217-
218-
export const getFilteredPreparedNodesList: Selector<
219-
NodesStateSlice,
220-
NodesPreparedEntity[] | undefined
221-
> = createSelector(
222-
[getNodesList, getNodesUptimeFilter, getSearchValue, (state) => state.settings.problemFilter],
223-
(nodesList, uptimeFilter, searchValue, problemFilter) => {
224-
let result = filterNodesByUptime(nodesList, uptimeFilter);
225-
result = filterNodesByProblemsStatus(result, problemFilter);
226-
result = filterNodesBySearchValue(result, searchValue);
227-
228-
return result;
229-
},
230-
);
231-
232124
export default nodes;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {Selector, createSelector} from 'reselect';
2+
import {escapeRegExp} from 'lodash';
3+
4+
import {EFlag} from '../../../types/api/enums';
5+
import {calcUptimeInSeconds} from '../../../utils';
6+
import {HOUR_IN_SECONDS} from '../../../utils/constants';
7+
import {NodesUptimeFilterValues} from '../../../utils/nodes';
8+
9+
import type {ProblemFilterValue} from '../settings/types';
10+
import type {NodesPreparedEntity, NodesStateSlice} from './types';
11+
import {ProblemFilterValues} from '../settings/settings';
12+
13+
// ==== Filters ====
14+
15+
const filterNodesByProblemsStatus = (
16+
nodesList: NodesPreparedEntity[] = [],
17+
problemFilter: ProblemFilterValue,
18+
) => {
19+
if (problemFilter === ProblemFilterValues.ALL) {
20+
return nodesList;
21+
}
22+
23+
return nodesList.filter(({SystemState}) => {
24+
return SystemState && SystemState !== EFlag.Green;
25+
});
26+
};
27+
28+
export const filterNodesByUptime = <T extends {StartTime?: string}>(
29+
nodesList: T[] = [],
30+
nodesUptimeFilter: NodesUptimeFilterValues,
31+
) => {
32+
if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
33+
return nodesList;
34+
}
35+
return nodesList.filter(({StartTime}) => {
36+
return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
37+
});
38+
};
39+
40+
const filterNodesBySearchValue = (nodesList: NodesPreparedEntity[] = [], searchValue: string) => {
41+
if (!searchValue) {
42+
return nodesList;
43+
}
44+
const re = new RegExp(escapeRegExp(searchValue), 'i');
45+
46+
return nodesList.filter((node) => {
47+
return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
48+
});
49+
};
50+
51+
// ==== Simple selectors ====
52+
53+
const selectNodesUptimeFilter = (state: NodesStateSlice) => state.nodes.nodesUptimeFilter;
54+
const selectSearchValue = (state: NodesStateSlice) => state.nodes.searchValue;
55+
const selectNodesList = (state: NodesStateSlice) => state.nodes.data;
56+
57+
// ==== Complex selectors ====
58+
59+
export const selectFilteredNodes: Selector<NodesStateSlice, NodesPreparedEntity[] | undefined> =
60+
createSelector(
61+
[
62+
selectNodesList,
63+
selectNodesUptimeFilter,
64+
selectSearchValue,
65+
(state) => state.settings.problemFilter,
66+
],
67+
(nodesList, uptimeFilter, searchValue, problemFilter) => {
68+
let result = filterNodesByUptime(nodesList, uptimeFilter);
69+
result = filterNodesByProblemsStatus(result, problemFilter);
70+
result = filterNodesBySearchValue(result, searchValue);
71+
72+
return result;
73+
},
74+
);

src/store/reducers/nodes/utils.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type {TComputeInfo} from '../../../types/api/compute';
2+
import type {TNodesInfo} from '../../../types/api/nodes';
3+
import {calcUptime} from '../../../utils';
4+
5+
import type {NodesHandledResponse, NodesPreparedEntity} from './types';
6+
7+
export const prepareComputeNodesData = (data: TComputeInfo): NodesHandledResponse => {
8+
const preparedNodes: NodesPreparedEntity[] = [];
9+
10+
if (data.Tenants) {
11+
for (const tenant of data.Tenants) {
12+
tenant.Nodes?.forEach((node) => {
13+
preparedNodes.push({
14+
...node,
15+
TenantName: tenant.Name,
16+
SystemState: node?.Overall,
17+
Uptime: calcUptime(node?.StartTime),
18+
});
19+
});
20+
}
21+
}
22+
23+
return {
24+
Nodes: preparedNodes,
25+
TotalNodes: preparedNodes.length,
26+
};
27+
};
28+
29+
export const prepareNodesData = (data: TNodesInfo): NodesHandledResponse => {
30+
const rawNodes = data.Nodes || [];
31+
32+
const preparedNodes = rawNodes.map((node) => {
33+
return {
34+
...node.SystemState,
35+
Tablets: node.Tablets,
36+
NodeId: node.NodeId,
37+
Uptime: calcUptime(node.SystemState?.StartTime),
38+
TenantName: node.SystemState?.Tenants?.[0],
39+
};
40+
});
41+
42+
return {
43+
Nodes: preparedNodes,
44+
TotalNodes: Number(data.TotalNodes) ?? preparedNodes.length,
45+
};
46+
};

src/store/reducers/storage/selectors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type {
1515
StorageStateSlice,
1616
UsageFilter,
1717
} from './types';
18-
import {filterNodesByUptime} from '../nodes/nodes';
18+
import {filterNodesByUptime} from '../nodes/selectors';
1919

2020
// ==== Prepare data ====
2121
const FLAGS_POINTS = {

0 commit comments

Comments
 (0)