Possible fix for pessimistic logs
parent
bfb98d14fb
commit
7802c91aaf
|
@ -71,10 +71,10 @@ describe("dispatchNetworkDown", () => {
|
||||||
it("does not falsely mark network of being down", () => {
|
it("does not falsely mark network of being down", () => {
|
||||||
// This test uses mocked state.
|
// This test uses mocked state.
|
||||||
// Please see `jest.mock` calls above.
|
// Please see `jest.mock` calls above.
|
||||||
dispatchNetworkDown("bot.mqtt", now(), "already_complete");
|
dispatchNetworkDown("bot.mqtt", now());
|
||||||
expect(store.dispatch).not.toHaveBeenCalled();
|
expect(store.dispatch).not.toHaveBeenCalled();
|
||||||
resetStats();
|
resetStats();
|
||||||
dispatchNetworkDown("bot.mqtt", now(), "not_complete");
|
dispatchNetworkDown("bot.mqtt", now());
|
||||||
expect(store.dispatch).toHaveBeenCalled();
|
expect(store.dispatch).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,14 +50,14 @@ function fakeBot(): Farmbot {
|
||||||
|
|
||||||
function expectStale() {
|
function expectStale() {
|
||||||
expect(dispatchNetworkDown)
|
expect(dispatchNetworkDown)
|
||||||
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER, "TESTS");
|
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectActive() {
|
function expectActive() {
|
||||||
expect(dispatchNetworkUp)
|
expect(dispatchNetworkUp)
|
||||||
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER, "TESTS");
|
.toHaveBeenCalledWith("bot.mqtt", ANY_NUMBER);
|
||||||
expect(dispatchNetworkUp)
|
expect(dispatchNetworkUp)
|
||||||
.toHaveBeenCalledWith("user.mqtt", ANY_NUMBER, "TESTS");
|
.toHaveBeenCalledWith("user.mqtt", ANY_NUMBER);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("ping util", () => {
|
describe("ping util", () => {
|
||||||
|
@ -68,12 +68,12 @@ describe("ping util", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks the bot's connection to MQTT as 'stale'", () => {
|
it("marks the bot's connection to MQTT as 'stale'", () => {
|
||||||
markStale("TESTS");
|
markStale();
|
||||||
expectStale();
|
expectStale();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("marks the bot's connection to MQTT as 'active'", () => {
|
it("marks the bot's connection to MQTT as 'active'", () => {
|
||||||
markActive("TESTS");
|
markActive();
|
||||||
expectActive();
|
expectActive();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { networkUp, networkDown } from "../actions";
|
||||||
|
|
||||||
describe("connectivity reducer", () => {
|
describe("connectivity reducer", () => {
|
||||||
const newState = () => {
|
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);
|
return connectivityReducer(DEFAULT_STATE, action);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ describe("connectivity reducer", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles an `up` QoS ping", () => {
|
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;
|
const { yep } = state.pings;
|
||||||
expect(yep).toBeTruthy();
|
expect(yep).toBeTruthy();
|
||||||
if (yep) {
|
if (yep) {
|
||||||
|
@ -28,7 +28,7 @@ describe("connectivity reducer", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles a `down` QoS ping", () => {
|
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;
|
const { yep } = state.pings;
|
||||||
expect(yep).toBeTruthy();
|
expect(yep).toBeTruthy();
|
||||||
if (yep) {
|
if (yep) {
|
||||||
|
|
|
@ -5,10 +5,10 @@ import { ReduxAction } from "../redux/interfaces";
|
||||||
type NetChange = ReduxAction<EdgeStatus>;
|
type NetChange = ReduxAction<EdgeStatus>;
|
||||||
|
|
||||||
const change = (state: "up" | "down") =>
|
const change = (state: "up" | "down") =>
|
||||||
(name: Edge, at = (new Date()).getTime(), qosPingId?: string): NetChange => {
|
(name: Edge, at = (new Date()).getTime()): NetChange => {
|
||||||
return {
|
return {
|
||||||
type: Actions.NETWORK_EDGE_CHANGE,
|
type: Actions.NETWORK_EDGE_CHANGE,
|
||||||
payload: { name, status: { state, at }, qosPingId }
|
payload: { name, status: { state, at } }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,36 +29,29 @@ function bumpThrottle(edge: Edge, now: number) {
|
||||||
|
|
||||||
export const dispatchQosStart = (id: string) => {
|
export const dispatchQosStart = (id: string) => {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
type: Actions.START_QOS_PING,
|
type: Actions.PING_START,
|
||||||
payload: { id }
|
payload: { id }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export let dispatchNetworkUp = (edge: Edge, at: number, qosPingId?: string) => {
|
export let dispatchNetworkUp = (edge: Edge, at: number) => {
|
||||||
if (shouldThrottle(edge, at)) { return; }
|
if (shouldThrottle(edge, at)) { return; }
|
||||||
store.dispatch(networkUp(edge, at, qosPingId));
|
store.dispatch(networkUp(edge, at));
|
||||||
bumpThrottle(edge, at);
|
bumpThrottle(edge, at);
|
||||||
};
|
};
|
||||||
|
|
||||||
const pingAlreadyComplete = (qosPingId?: string) => {
|
export let dispatchNetworkDown = (edge: Edge, at: number) => {
|
||||||
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) => {
|
|
||||||
if (shouldThrottle(edge, at)) { return; }
|
if (shouldThrottle(edge, at)) { return; }
|
||||||
// If a ping is marked as "completed", then there
|
store.dispatch(networkDown(edge, at));
|
||||||
// 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));
|
|
||||||
bumpThrottle(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);
|
||||||
|
};
|
||||||
|
|
|
@ -12,7 +12,6 @@ export interface ConnectionStatus {
|
||||||
export interface EdgeStatus {
|
export interface EdgeStatus {
|
||||||
name: Edge;
|
name: Edge;
|
||||||
status: ConnectionStatus;
|
status: ConnectionStatus;
|
||||||
qosPingId?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Name of a connection between two points. "." can be read as "to".
|
/** Name of a connection between two points. "." can be read as "to".
|
||||||
|
|
|
@ -2,7 +2,9 @@ import { Farmbot, uuid } from "farmbot";
|
||||||
import {
|
import {
|
||||||
dispatchNetworkDown,
|
dispatchNetworkDown,
|
||||||
dispatchNetworkUp,
|
dispatchNetworkUp,
|
||||||
dispatchQosStart
|
dispatchQosStart,
|
||||||
|
pingOK,
|
||||||
|
pingNO
|
||||||
} from "./index";
|
} from "./index";
|
||||||
import { isNumber } from "lodash";
|
import { isNumber } from "lodash";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
@ -22,13 +24,13 @@ export function readPing(bot: Farmbot, direction: Direction): number | undefined
|
||||||
return isNumber(val) ? val : undefined;
|
return isNumber(val) ? val : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markStale(qosPingId: string) {
|
export function markStale() {
|
||||||
dispatchNetworkDown("bot.mqtt", now(), qosPingId);
|
dispatchNetworkDown("bot.mqtt", now());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markActive(qosPingId: string) {
|
export function markActive() {
|
||||||
dispatchNetworkUp("user.mqtt", now(), qosPingId);
|
dispatchNetworkUp("user.mqtt", now());
|
||||||
dispatchNetworkUp("bot.mqtt", now(), qosPingId);
|
dispatchNetworkUp("bot.mqtt", now());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isInactive(last: number, now_: number): boolean {
|
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) {
|
export function sendOutboundPing(bot: Farmbot) {
|
||||||
const id = uuid();
|
const id = uuid();
|
||||||
const ok = () => markActive(id);
|
const ok = () => pingOK(id, now()); markActive();
|
||||||
const no = () => markStale(id);
|
const no = () => pingNO(id); markStale();
|
||||||
dispatchQosStart(id);
|
dispatchQosStart(id);
|
||||||
bot.ping().then(ok, no);
|
bot.ping().then(ok, no);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,22 +19,23 @@ export const DEFAULT_STATE: ConnectionState = {
|
||||||
|
|
||||||
export let connectivityReducer =
|
export let connectivityReducer =
|
||||||
generateReducer<ConnectionState>(DEFAULT_STATE)
|
generateReducer<ConnectionState>(DEFAULT_STATE)
|
||||||
.add<{ id: string }>(Actions.START_QOS_PING, (s, { payload }) => {
|
.add<{ id: string }>(Actions.PING_START, (s, { payload }) => {
|
||||||
return {
|
return {
|
||||||
...s,
|
...s,
|
||||||
pings: startPing(s.pings, payload.id)
|
pings: startPing(s.pings, payload.id)
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.add<EdgeStatus>(Actions.NETWORK_EDGE_CHANGE, (s, { payload }) => {
|
.add<{ id: string, at: number }>(Actions.PING_OK, (s, { payload }) => {
|
||||||
const { qosPingId, status } = payload;
|
s.pings = completePing(s.pings, payload.id, payload.at);
|
||||||
if (qosPingId) {
|
|
||||||
if (status.state == "up") {
|
|
||||||
s.pings = completePing(s.pings, qosPingId, status.at);
|
|
||||||
} else {
|
|
||||||
s.pings = failPing(s.pings, qosPingId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
s.uptime[payload.name] = payload.status;
|
||||||
return s;
|
return s;
|
||||||
})
|
})
|
||||||
|
|
|
@ -995,5 +995,7 @@ export enum Actions {
|
||||||
NETWORK_EDGE_CHANGE = "NETWORK_EDGE_CHANGE",
|
NETWORK_EDGE_CHANGE = "NETWORK_EDGE_CHANGE",
|
||||||
RESET_NETWORK = "RESET_NETWORK",
|
RESET_NETWORK = "RESET_NETWORK",
|
||||||
SET_CONSISTENCY = "SET_CONSISTENCY",
|
SET_CONSISTENCY = "SET_CONSISTENCY",
|
||||||
START_QOS_PING = "START_QOS_PING"
|
PING_START = "PING_START",
|
||||||
|
PING_OK = "PING_OK",
|
||||||
|
PING_NO = "PING_NO"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue