Possible fix for pessimistic logs

pull/1427/head
Rick Carlino 2019-09-11 16:58:53 -05:00
parent bfb98d14fb
commit 7802c91aaf
9 changed files with 51 additions and 54 deletions

View File

@ -71,10 +71,10 @@ describe("dispatchNetworkDown", () => {
it("does not falsely mark network of being down", () => {
// This test uses mocked state.
// Please see `jest.mock` calls above.
dispatchNetworkDown("bot.mqtt", now(), "already_complete");
dispatchNetworkDown("bot.mqtt", now());
expect(store.dispatch).not.toHaveBeenCalled();
resetStats();
dispatchNetworkDown("bot.mqtt", now(), "not_complete");
dispatchNetworkDown("bot.mqtt", now());
expect(store.dispatch).toHaveBeenCalled();
});
});

View File

@ -50,14 +50,14 @@ function fakeBot(): Farmbot {
function expectStale() {
expect(dispatchNetworkDown)
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER, "TESTS");
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER);
}
function expectActive() {
expect(dispatchNetworkUp)
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER, "TESTS");
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER);
expect(dispatchNetworkUp)
.toHaveBeenCalledWith("user.mqtt", ANY_NUMBER, "TESTS");
.toHaveBeenCalledWith("user.mqtt", ANY_NUMBER);
}
describe("ping util", () => {
@ -68,12 +68,12 @@ describe("ping util", () => {
});
it("marks the bot's connection to MQTT as 'stale'", () => {
markStale("TESTS");
markStale();
expectStale();
});
it("marks the bot's connection to MQTT as 'active'", () => {
markActive("TESTS");
markActive();
expectActive();
});

View File

@ -4,7 +4,7 @@ import { networkUp, networkDown } from "../actions";
describe("connectivity reducer", () => {
const newState = () => {
const action = { type: Actions.START_QOS_PING, payload: { id: "yep" } };
const action = { type: Actions.PING_START, payload: { id: "yep" } };
return connectivityReducer(DEFAULT_STATE, action);
};
@ -19,7 +19,7 @@ describe("connectivity reducer", () => {
});
it("handles an `up` QoS ping", () => {
const state = connectivityReducer(newState(), networkUp("bot.mqtt", 1234, "yep"));
const state = connectivityReducer(newState(), networkUp("bot.mqtt", 1234));
const { yep } = state.pings;
expect(yep).toBeTruthy();
if (yep) {
@ -28,7 +28,7 @@ describe("connectivity reducer", () => {
});
it("handles a `down` QoS ping", () => {
const state = connectivityReducer(newState(), networkDown("bot.mqtt", 1234, "yep"));
const state = connectivityReducer(newState(), networkDown("bot.mqtt", 1234));
const { yep } = state.pings;
expect(yep).toBeTruthy();
if (yep) {

View File

@ -5,10 +5,10 @@ import { ReduxAction } from "../redux/interfaces";
type NetChange = ReduxAction<EdgeStatus>;
const change = (state: "up" | "down") =>
(name: Edge, at = (new Date()).getTime(), qosPingId?: string): NetChange => {
(name: Edge, at = (new Date()).getTime()): NetChange => {
return {
type: Actions.NETWORK_EDGE_CHANGE,
payload: { name, status: { state, at }, qosPingId }
payload: { name, status: { state, at } }
};
};

View File

@ -29,36 +29,29 @@ function bumpThrottle(edge: Edge, now: number) {
export const dispatchQosStart = (id: string) => {
store.dispatch({
type: Actions.START_QOS_PING,
type: Actions.PING_START,
payload: { id }
});
};
export let dispatchNetworkUp = (edge: Edge, at: number, qosPingId?: string) => {
export let dispatchNetworkUp = (edge: Edge, at: number) => {
if (shouldThrottle(edge, at)) { return; }
store.dispatch(networkUp(edge, at, qosPingId));
store.dispatch(networkUp(edge, at));
bumpThrottle(edge, at);
};
const pingAlreadyComplete = (qosPingId?: string) => {
if (qosPingId) {
const allPings = store.getState().bot.connectivity.pings;
const thePing = allPings[qosPingId];
return (thePing && thePing.kind == "complete");
}
return false;
};
export let dispatchNetworkDown = (edge: Edge, at: number, qosPingId?: string) => {
export let dispatchNetworkDown = (edge: Edge, at: number) => {
if (shouldThrottle(edge, at)) { return; }
// If a ping is marked as "completed", then there
// is no way that the network is down. A common
// use case for this is the timeout callback
// in the QoS tester. The timeout always triggers,
// so we need to add a means of cancelling the
// "network down" action if the request completed
// before the timeout.
if (pingAlreadyComplete(qosPingId)) { return; }
store.dispatch(networkDown(edge, at, qosPingId));
store.dispatch(networkDown(edge, at));
bumpThrottle(edge, at);
};
export const pingOK = (id: string, at: number) => {
const action = { type: Actions.PING_OK, payload: { id, at } };
store.dispatch(action);
};
export const pingNO = (id: string) => {
const action = { type: Actions.PING_OK, payload: { id } };
store.dispatch(action);
};

View File

@ -12,7 +12,6 @@ export interface ConnectionStatus {
export interface EdgeStatus {
name: Edge;
status: ConnectionStatus;
qosPingId?: string;
}
/** Name of a connection between two points. "." can be read as "to".

View File

@ -2,7 +2,9 @@ import { Farmbot, uuid } from "farmbot";
import {
dispatchNetworkDown,
dispatchNetworkUp,
dispatchQosStart
dispatchQosStart,
pingOK,
pingNO
} from "./index";
import { isNumber } from "lodash";
import axios from "axios";
@ -22,13 +24,13 @@ export function readPing(bot: Farmbot, direction: Direction): number | undefined
return isNumber(val) ? val : undefined;
}
export function markStale(qosPingId: string) {
dispatchNetworkDown("bot.mqtt", now(), qosPingId);
export function markStale() {
dispatchNetworkDown("bot.mqtt", now());
}
export function markActive(qosPingId: string) {
dispatchNetworkUp("user.mqtt", now(), qosPingId);
dispatchNetworkUp("bot.mqtt", now(), qosPingId);
export function markActive() {
dispatchNetworkUp("user.mqtt", now());
dispatchNetworkUp("bot.mqtt", now());
}
export function isInactive(last: number, now_: number): boolean {
@ -37,8 +39,8 @@ export function isInactive(last: number, now_: number): boolean {
export function sendOutboundPing(bot: Farmbot) {
const id = uuid();
const ok = () => markActive(id);
const no = () => markStale(id);
const ok = () => pingOK(id, now()); markActive();
const no = () => pingNO(id); markStale();
dispatchQosStart(id);
bot.ping().then(ok, no);
}

View File

@ -19,22 +19,23 @@ export const DEFAULT_STATE: ConnectionState = {
export let connectivityReducer =
generateReducer<ConnectionState>(DEFAULT_STATE)
.add<{ id: string }>(Actions.START_QOS_PING, (s, { payload }) => {
.add<{ id: string }>(Actions.PING_START, (s, { payload }) => {
return {
...s,
pings: startPing(s.pings, payload.id)
};
})
.add<EdgeStatus>(Actions.NETWORK_EDGE_CHANGE, (s, { payload }) => {
const { qosPingId, status } = payload;
if (qosPingId) {
if (status.state == "up") {
s.pings = completePing(s.pings, qosPingId, status.at);
} else {
s.pings = failPing(s.pings, qosPingId);
}
}
.add<{ id: string, at: number }>(Actions.PING_OK, (s, { payload }) => {
s.pings = completePing(s.pings, payload.id, payload.at);
return s;
})
.add<{ id: string }>(Actions.PING_NO, (s, { payload }) => {
s.pings = failPing(s.pings, payload.id);
return s;
})
.add<EdgeStatus>(Actions.NETWORK_EDGE_CHANGE, (s, { payload }) => {
s.uptime[payload.name] = payload.status;
return s;
})

View File

@ -995,5 +995,7 @@ export enum Actions {
NETWORK_EDGE_CHANGE = "NETWORK_EDGE_CHANGE",
RESET_NETWORK = "RESET_NETWORK",
SET_CONSISTENCY = "SET_CONSISTENCY",
START_QOS_PING = "START_QOS_PING"
PING_START = "PING_START",
PING_OK = "PING_OK",
PING_NO = "PING_NO"
}