pez-globo / pufferfish-software

All software for the Pufferfish ventilator.
Apache License 2.0
0 stars 1 forks source link

Reimplement alarm muting #428

Closed ethanjli closed 2 years ago

ethanjli commented 2 years ago

This PR resolves #372 and fixes #420 by completely reimplementing alarm muting functionality.

Main functionality

This PR makes the following changes to the communication protocol:

React component decomposition & redraw optimization

This PR makes the following related improvements to the frontend's modules/app/EventAlerts.tsx, much of which already had to be reimplemented for the alarm mute cancellation behavior:

@rohanpurohit I think the kind of decomposition done in EventAlerts.tsx is what we should do as the first goal for improving the quality of any components with giant return blocks of JSX (for understandability, maintainability, and testability), as well as any components causing extraneous redraws (for performance/responsiveness). Based on the outcomes of the refactor in this PR, I'm confident that thoughtful decomposition will solve most or all of our problems with extraneous redraws.

When we need to reuse the same component in many different places, and each place needs to duplicate the same set of useStates, we could consider moving the duplicated local states into the redux store to make the code simpler and reduce boilerplate; this may also reduce the number of places we have to pass around getter and setter callbacks, as those can probably just be replaced with selectors and action dispatchers.

The refactor in this PR doesn't use containers as I understand them (i.e. react-redux's connect), because the original code just relied on a fixed set of useSelectors and didn't need to be parameterized on interchangeable selectors (i.e. none of the React components were generic code). However, react-redux's useSelector behaves pretty similarly to connect (except for reference vs. shallow equality and some other details). When we have a react component which should work with different selectors and simultaneously need to reuse the same selector-component combination in many different places, we should use containers; otherwise, we could just combine it with different selectors using the approach I've taken in EventAlerts.tsx by passing in a selector and use it with useSelector (I believe this is what ValueSelectorDisplay does). However, there's an important caveat from react-redux's hooks documentation: "unlike connect(), useSelector() does not prevent the component from re-rendering due to its parent re-rendering, even if the component's props did not change." - this means that wherever we use useSelector in a child component, we have to make sure that the parent component, the grandparent component, the great-grandparent, etc., all avoid useSelector. (unrelatedly, that documentation provides another useful tip about React.memo() which might be very useful for removing extraneous redraws in the event log table).

etc

This PR makes the following related improvements to the backend and firmware:

This PR adds the following functionalities to the frontend:

This PR fixes the following unrelated bugs in the frontend:

This PR also makes the following readability/maintainability improvements:

ethanjli commented 2 years ago

For records-keeping:

  1. This project is licensed under Apache License v2.0 for any software, and Solderpad Hardware License v2.1 for any hardware - do you agree that your contributions to this project will be under these licenses, too? Yes
  2. Were any of these contributions also part of work you did for an employer or a client? No
  3. Does this work include, or is it based on, any third-party work which you did not create? No

@rohanpurohit Since this is a reimplementation of alarm muting functionality and a major refactor of EventAlerts.tsx, it'd be helpful to me if you could test those things with a fresh mind, as some things may have slipped past me. It might also be worth taking a look at how modules/app/EventAlerts.tsx has changed into modules/alarms/Alarms.tsx, modules/alarms/muting/AlarmMuting.tsx, and modules/logs/EventLog.tsx, as a companion to reading the "React component decomposition & redraw optimization" section of the main PR description which outlines what I did to stop the wasteful redraws. Everything else in the main PR description was stuff we already discussed in today's meeting, so you can skip everything else in the PR description.

rohanpurohit commented 2 years ago

For records-keeping:

  1. This project is licensed under Apache License v2.0 for any software, and Solderpad Hardware License v2.1 for any hardware - do you agree that your contributions to this project will be under these licenses, too? Yes
  2. Were any of these contributions also part of work you did for an employer or a client? No
  3. Does this work include, or is it based on, any third-party work which you did not create? No

@rohanpurohit Since this is a reimplementation of alarm muting functionality and a major refactor of EventAlerts.tsx, it'd be helpful to me if you could test those things with a fresh mind, as some things may have slipped past me. It might also be worth taking a look at how modules/app/EventAlerts.tsx has changed into modules/alarms/Alarms.tsx, modules/alarms/muting/AlarmMuting.tsx, and modules/logs/EventLog.tsx, as a companion to reading the "React component decomposition & redraw optimization" section of the main PR description which outlines what I did to stop the wasteful redraws. Everything else in the main PR description was stuff we already discussed in today's meeting, so you can skip everything else in the PR description.

Just did light to moderate testing on https://github.com/pez-globo/pufferfish-software/pull/428/commits/a5c60b5ed830c65d37b79ece9be7919683ddf713, and everything works as intended, there are no regressions from the refactor!

I was going to approve, but I saw that you are still making changes so did not do that!

ethanjli commented 2 years ago
  • But I still feel in some components where we dispatch actions frequently (like ValueClickers) we may not be able to avoid redraws even with really careful decomposition and or state management, maybe there we need to be effective about how we dispatch actions, for example: with a single button click like submit or something similar, in which case it redraws only once!

In general, the best we can do is that the things which change get redrawn while everything else does not. If the action dispatches only happen under less-frequent conditions, I think we can tolerate extra redraws there if we can't refactor them out, we'll have to see on a case-by-case basis - the goal of eliminating extra redraws throughout the app is so that we have reasonable responsiveness and performance in the places where reducing the rate of redraws would degrade usability

I was going to approve, but I saw that you are still making changes so did not do that!

~I'm done with changes now!~ Correction, I need to run yarn lint:fix.