fixed race condition on web socket status updates
This commit is contained in:
parent
50103d5a0c
commit
a2ac900f3e
1 changed files with 47 additions and 1 deletions
|
|
@ -32,6 +32,28 @@ import { cloneDeep } from "lodash";
|
||||||
import LoadingScreen from "app/LoadingScreen";
|
import LoadingScreen from "app/LoadingScreen";
|
||||||
import TeamDialog from "teams/TeamDialog";
|
import TeamDialog from "teams/TeamDialog";
|
||||||
|
|
||||||
|
type TimestampedReading = {
|
||||||
|
timestamp?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTimestampMillis = (timestamp?: string): number | undefined => {
|
||||||
|
if (!timestamp) return undefined;
|
||||||
|
const parsed = Date.parse(timestamp);
|
||||||
|
return Number.isNaN(parsed) ? undefined : parsed;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pickNewestReading = <T extends TimestampedReading>(
|
||||||
|
current: T | null | undefined,
|
||||||
|
incoming: T | null | undefined
|
||||||
|
): T | null | undefined => {
|
||||||
|
const currentTs = getTimestampMillis(current?.timestamp);
|
||||||
|
const incomingTs = getTimestampMillis(incoming?.timestamp);
|
||||||
|
|
||||||
|
if (incomingTs === undefined) return current ?? incoming;
|
||||||
|
if (currentTs === undefined) return incoming ?? current;
|
||||||
|
return incomingTs >= currentTs ? incoming : current;
|
||||||
|
};
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
buttonBox: {
|
buttonBox: {
|
||||||
|
|
@ -212,7 +234,31 @@ export default function Devices() {
|
||||||
prev.map((d) => {
|
prev.map((d) => {
|
||||||
if (d.id().toString() !== deviceId) return d
|
if (d.id().toString() !== deviceId) return d
|
||||||
const updated = Device.clone(d)
|
const updated = Device.clone(d)
|
||||||
updated.status = status
|
const incomingStatus = pond.DeviceStatus.fromObject(status)
|
||||||
|
const currentStatus = d.status ?? pond.DeviceStatus.create()
|
||||||
|
|
||||||
|
// Guard against out-of-order websocket events by keeping whichever
|
||||||
|
// reading has the newest timestamp for each independently-updated sensor.
|
||||||
|
incomingStatus.plenum = pickNewestReading(currentStatus.plenum, incomingStatus.plenum)
|
||||||
|
incomingStatus.sen5x = pickNewestReading(currentStatus.sen5x, incomingStatus.sen5x)
|
||||||
|
incomingStatus.co = pickNewestReading(currentStatus.co, incomingStatus.co)
|
||||||
|
incomingStatus.co2 = pickNewestReading(currentStatus.co2, incomingStatus.co2)
|
||||||
|
incomingStatus.no2 = pickNewestReading(currentStatus.no2, incomingStatus.no2)
|
||||||
|
incomingStatus.o2 = pickNewestReading(currentStatus.o2, incomingStatus.o2)
|
||||||
|
incomingStatus.lel = pickNewestReading(currentStatus.lel, incomingStatus.lel)
|
||||||
|
incomingStatus.h2s = pickNewestReading(currentStatus.h2s, incomingStatus.h2s)
|
||||||
|
|
||||||
|
const currentLastActive = getTimestampMillis(currentStatus.lastActive)
|
||||||
|
const incomingLastActive = getTimestampMillis(incomingStatus.lastActive)
|
||||||
|
if (
|
||||||
|
currentLastActive !== undefined &&
|
||||||
|
incomingLastActive !== undefined &&
|
||||||
|
incomingLastActive < currentLastActive
|
||||||
|
) {
|
||||||
|
incomingStatus.lastActive = currentStatus.lastActive
|
||||||
|
}
|
||||||
|
|
||||||
|
updated.status = incomingStatus
|
||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue