summaryrefslogtreecommitdiff
path: root/opendc-web
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-20 11:04:34 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-20 16:07:06 +0200
commit0b3d0ba3193ebcdeadc6a4b0a192eeb06e9add29 (patch)
treef01e4990efd17b1ab0ed520ec39cd3aa5a0a0b09 /opendc-web
parent98bc4c3e9458aea98890b770493f14327a7bc7c4 (diff)
fix(web/ui): Do not fail on stale Redux state
This change fixes an issue where switching between different topologies would fail due to stale Redux state. We have updated the components to take into account that ids may not exist in the Redux store.
Diffstat (limited to 'opendc-web')
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js34
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js11
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js17
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js4
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js2
-rw-r--r--opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js4
6 files changed, 42 insertions, 30 deletions
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js
index be1f3e45..a1ca7426 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/RackEnergyFillContainer.js
@@ -3,24 +3,26 @@ import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import RackFillBar from './elements/RackFillBar'
-function RackSpaceFillContainer({ tileId, ...props }) {
+function RackSpaceFillContainer({ rackId, ...props }) {
const fillFraction = useSelector((state) => {
+ const rack = state.topology.racks[rackId]
+ if (!rack) {
+ return 0
+ }
+
+ const { machines, cpus, gpus, memories, storages } = state.topology
let energyConsumptionTotal = 0
- const rack = state.topology.racks[state.topology.tiles[tileId].rack]
- const machineIds = rack.machines
- machineIds.forEach((machineId) => {
- if (machineId !== null) {
- const machine = state.topology.machines[machineId]
- machine.cpus.forEach((id) => (energyConsumptionTotal += state.topology.cpus[id].energyConsumptionW))
- machine.gpus.forEach((id) => (energyConsumptionTotal += state.topology.gpus[id].energyConsumptionW))
- machine.memories.forEach(
- (id) => (energyConsumptionTotal += state.topology.memories[id].energyConsumptionW)
- )
- machine.storages.forEach(
- (id) => (energyConsumptionTotal += state.topology.storages[id].energyConsumptionW)
- )
+
+ for (const machineId of rack.machines) {
+ if (!machineId) {
+ continue
}
- })
+ const machine = machines[machineId]
+ machine.cpus.forEach((id) => (energyConsumptionTotal += cpus[id].energyConsumptionW))
+ machine.gpus.forEach((id) => (energyConsumptionTotal += gpus[id].energyConsumptionW))
+ machine.memories.forEach((id) => (energyConsumptionTotal += memories[id].energyConsumptionW))
+ machine.storages.forEach((id) => (energyConsumptionTotal += storages[id].energyConsumptionW))
+ }
return Math.min(1, energyConsumptionTotal / rack.powerCapacityW)
})
@@ -28,7 +30,7 @@ function RackSpaceFillContainer({ tileId, ...props }) {
}
RackSpaceFillContainer.propTypes = {
- tileId: PropTypes.string.isRequired,
+ rackId: PropTypes.string.isRequired,
}
export default RackSpaceFillContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js
index 0c15d54b..2039a9d3 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/RackSpaceFillContainer.js
@@ -25,13 +25,18 @@ import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import RackFillBar from './elements/RackFillBar'
-function RackSpaceFillContainer({ tileId, ...props }) {
- const rack = useSelector((state) => state.topology.racks[state.topology.tiles[tileId].rack])
+function RackSpaceFillContainer({ rackId, ...props }) {
+ const rack = useSelector((state) => state.topology.racks[rackId])
+
+ if (!rack) {
+ return null
+ }
+
return <RackFillBar {...props} type="space" fillFraction={rack.machines.length / rack.capacity} />
}
RackSpaceFillContainer.propTypes = {
- tileId: PropTypes.string.isRequired,
+ rackId: PropTypes.string.isRequired,
}
export default RackSpaceFillContainer
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js
index 65189891..191318ee 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/RoomContainer.js
@@ -27,15 +27,16 @@ import { goFromBuildingToRoom } from '../../../redux/actions/interaction-level'
import RoomGroup from './groups/RoomGroup'
function RoomContainer({ roomId, ...props }) {
- const state = useSelector((state) => {
- return {
- interactionLevel: state.interactionLevel,
- currentRoomInConstruction: state.construction.currentRoomInConstruction,
- room: state.topology.rooms[roomId],
- }
- })
+ const interactionLevel = useSelector((state) => state.interactionLevel)
+ const currentRoomInConstruction = useSelector((state) => state.construction.currentRoomInConstruction)
+ const room = useSelector((state) => state.topology.rooms[roomId])
const dispatch = useDispatch()
- return <RoomGroup {...props} {...state} onClick={() => dispatch(goFromBuildingToRoom(roomId))} />
+
+ if (!room) {
+ return null
+ }
+
+ return <RoomGroup {...props} interactionLevel={interactionLevel} currentRoomInConstruction={currentRoomInConstruction} room={room} onClick={() => dispatch(goFromBuildingToRoom(roomId))} />
}
RoomContainer.propTypes = {
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js
index ef5af263..0788b894 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/TileContainer.js
@@ -31,6 +31,10 @@ function TileContainer({ tileId, ...props }) {
const dispatch = useDispatch()
const tile = useSelector((state) => state.topology.tiles[tileId])
+ if (!tile) {
+ return null
+ }
+
const onClick = (tile) => {
if (tile.rack) {
dispatch(goFromRoomToRack(tile.id))
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js b/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js
index 143f70c2..106d8d3d 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/WallContainer.js
@@ -27,7 +27,7 @@ import WallGroup from './groups/WallGroup'
function WallContainer({ roomId, ...props }) {
const tiles = useSelector((state) => {
- return state.topology.rooms[roomId].tiles.map((tileId) => state.topology.tiles[tileId])
+ return state.topology.rooms[roomId]?.tiles.map((tileId) => state.topology.tiles[tileId]) ?? []
})
return <WallGroup {...props} tiles={tiles} />
}
diff --git a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js
index dad2d62d..ed942661 100644
--- a/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js
+++ b/opendc-web/opendc-web-ui/src/components/topologies/map/groups/RackGroup.js
@@ -11,8 +11,8 @@ function RackGroup({ tile }) {
<Group>
<TileObject positionX={tile.positionX} positionY={tile.positionY} color={RACK_BACKGROUND_COLOR} />
<Group>
- <RackSpaceFillContainer tileId={tile.id} positionX={tile.positionX} positionY={tile.positionY} />
- <RackEnergyFillContainer tileId={tile.id} positionX={tile.positionX} positionY={tile.positionY} />
+ <RackSpaceFillContainer rackId={tile.rack} positionX={tile.positionX} positionY={tile.positionY} />
+ <RackEnergyFillContainer rackId={tile.rack} positionX={tile.positionX} positionY={tile.positionY} />
</Group>
</Group>
)