[mod] e-mails plus explicites (titre + motif erreur)
This commit is contained in:
@@ -4,23 +4,33 @@ import Axios from "axios";
|
||||
import {mail} from "../../mail";
|
||||
import {Watcher} from "../../types/state";
|
||||
|
||||
export function urlWatcher(conf: Conf, checkValidity: (data: any) => Promise<void>) {
|
||||
export function urlWatcher(conf: Conf, checkValidity: (data: any) => Promise<UrlWatcherResult>) {
|
||||
|
||||
return async (urlConf: ConfURL): Promise<Watcher> => {
|
||||
return async (urlConf: ConfURL,
|
||||
getOkTitle: () => string,
|
||||
getKoTitle: () => string,
|
||||
getRecoveredTitle: () => string): Promise<Watcher> => {
|
||||
|
||||
let nodeDownRes: () => void
|
||||
let nodeDownPromise: Promise<void> = new Promise(res => nodeDownRes = res)
|
||||
|
||||
async function checkResult(data: any) {
|
||||
const validity = await checkValidity(data)
|
||||
if (validity.error) {
|
||||
throw new UrlWatcherError('Validity error')
|
||||
}
|
||||
}
|
||||
|
||||
return watcherLoop(
|
||||
urlConf.name,
|
||||
async () => {
|
||||
let interval: NodeJS.Timer;
|
||||
const res = await Axios.get(urlConf.address)
|
||||
await checkValidity(res.data)
|
||||
await checkResult(res.data)
|
||||
interval = setInterval(async () => {
|
||||
try {
|
||||
const res = await Axios.get(urlConf.address)
|
||||
await checkValidity(res.data)
|
||||
await checkResult(res.data)
|
||||
} catch (e) {
|
||||
if (interval) {
|
||||
clearInterval(interval)
|
||||
@@ -36,21 +46,45 @@ export function urlWatcher(conf: Conf, checkValidity: (data: any) => Promise<voi
|
||||
|
||||
conf.reconnectionDelays,
|
||||
|
||||
mail.onEstablished(conf, urlConf.address),
|
||||
mail.onEstablished(conf, urlConf.address, getOkTitle()),
|
||||
|
||||
// When a disconnection is detected
|
||||
mail.onDisconnect(conf, urlConf.address),
|
||||
(waitingDelay: number, error?: any) => {
|
||||
let koTitle: string|undefined
|
||||
let koMessage: (() => string)|undefined
|
||||
if (error && error instanceof UrlWatcherError) {
|
||||
koTitle = getKoTitle()
|
||||
koMessage = () => `<p>${error.errorMessage}</p>`
|
||||
}
|
||||
return mail.onDisconnect(conf, urlConf.address, koTitle, koMessage)(waitingDelay)
|
||||
},
|
||||
|
||||
async () => {
|
||||
console.log('Trying to connect to %s', urlConf.address)
|
||||
},
|
||||
|
||||
mail.onRestartSuccess(conf, urlConf.address),
|
||||
|
||||
async (e) => {
|
||||
console.error(e.message || e)
|
||||
}
|
||||
mail.onRestartSuccess(conf, urlConf.address, getRecoveredTitle()),
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class UrlWatcherError {
|
||||
|
||||
constructor (public errorMessage: string) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class UrlWatcherResult {
|
||||
error?: string
|
||||
|
||||
public static ok() {
|
||||
return {}
|
||||
}
|
||||
|
||||
public static ko(errorMessage: string) {
|
||||
return { error: errorMessage }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Conf, ConfBMA} from "../../types/conf";
|
||||
import {urlWatcher} from '../abstract/url-watcher'
|
||||
import {urlWatcher, UrlWatcherResult} from '../abstract/url-watcher'
|
||||
import {moment} from 'duniter/app/lib/common-libs/moment'
|
||||
|
||||
export function bmaWatcher(conf: Conf) {
|
||||
@@ -11,12 +11,16 @@ export function bmaWatcher(conf: Conf) {
|
||||
return urlWatcher(conf, async (data) => {
|
||||
const block = data as { medianTime: number }
|
||||
if (bmaServer.maxLate && moment().unix() - block.medianTime > bmaServer.maxLate) {
|
||||
throw 'Server is late'
|
||||
return UrlWatcherResult.ko('Server is late')
|
||||
}
|
||||
return UrlWatcherResult.ok()
|
||||
})({
|
||||
name: `BMA ${bmaServer.address}`,
|
||||
address: bmaServer.address + URL_PATH,
|
||||
frequency: bmaServer.frequency
|
||||
})
|
||||
},
|
||||
() => `[OK] BMA of ${bmaServer.address}`,
|
||||
() => `[FAILURE] BMA of ${bmaServer.address}`,
|
||||
() => `[RECOVERED] BMA of ${bmaServer.address}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
import {Conf, ConfHead} from "../../types/conf";
|
||||
import {urlWatcher} from '../abstract/url-watcher'
|
||||
import {urlWatcher, UrlWatcherResult} from '../abstract/url-watcher'
|
||||
import {WS2PHead} from "duniter/app/modules/ws2p/lib/WS2PCluster";
|
||||
|
||||
function handleLateness(confHead: ConfHead, mainHeads: HeadMetric[], observedHead?: TrameWS2P) {
|
||||
function handleLateness(confHead: ConfHead, mainHeads: HeadMetric[], observedHead?: TrameWS2P): UrlWatcherResult {
|
||||
if (!mainHeads.length) {
|
||||
throw 'Observed pubkey ${confHead.observedPubkey}: no consensus found'
|
||||
return UrlWatcherResult.ko('Observed pubkey ${confHead.observedPubkey}: no consensus found')
|
||||
}
|
||||
if (!observedHead) {
|
||||
throw `Observed pubkey ${confHead.observedPubkey} not found in heads`
|
||||
return UrlWatcherResult.ko(`Observed pubkey ${confHead.observedPubkey} not found in heads`)
|
||||
}
|
||||
const matchingHeads = mainHeads.filter(h => h.blockstamp === observedHead.blockstamp)
|
||||
if (!matchingHeads.length) {
|
||||
// Check how much late is the node
|
||||
const farAwayHeads = mainHeads.filter(h => h.blockNumber - observedHead.blockNumber >= confHead.maxLateBlocks)
|
||||
if (farAwayHeads.length) {
|
||||
throw `Observed pubkey ${confHead.observedPubkey} is too late for ${farAwayHeads.length} consensus by at least ${confHead.maxLateBlocks}`
|
||||
return UrlWatcherResult.ko(`Observed pubkey ${confHead.observedPubkey} is too late for ${farAwayHeads.length} consensus by at least ${confHead.maxLateBlocks}`)
|
||||
}
|
||||
}
|
||||
return UrlWatcherResult.ok()
|
||||
}
|
||||
|
||||
export function headWatcher(conf: Conf) {
|
||||
|
||||
const URL_PATH = '/network/ws2p/heads'
|
||||
const KEY_LENGTH = 10
|
||||
|
||||
return async (confHead: ConfHead) => {
|
||||
|
||||
@@ -29,12 +31,15 @@ export function headWatcher(conf: Conf) {
|
||||
const heads = data as { heads: WS2PHead[] }
|
||||
const mainHeads = getMain(heads)
|
||||
const observedHead = getObserved(heads, confHead.observedPubkey)
|
||||
handleLateness(confHead, mainHeads, observedHead)
|
||||
return handleLateness(confHead, mainHeads, observedHead)
|
||||
})({
|
||||
name: `head watcher ${confHead.address} => ${confHead.observedPubkey.substr(0, 10)}`,
|
||||
name: `head watcher ${confHead.address} => ${confHead.observedPubkey.substr(0, KEY_LENGTH)}`,
|
||||
address: confHead.address + URL_PATH,
|
||||
frequency: confHead.frequency
|
||||
})
|
||||
},
|
||||
() => `[OK] HEADS of ${confHead.observedPubkey.substr(0, KEY_LENGTH)}`,
|
||||
() => `[FAILURE] HEADS of ${confHead.observedPubkey.substr(0, KEY_LENGTH)}`,
|
||||
() => `[RECOVERED] HEADS of ${confHead.observedPubkey.substr(0, KEY_LENGTH)}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Conf, ConfDprobeHeartbeat} from "../../types/conf";
|
||||
import {urlWatcher} from '../abstract/url-watcher'
|
||||
import {urlWatcher, UrlWatcherResult} from '../abstract/url-watcher'
|
||||
import {moment} from 'duniter/app/lib/common-libs/moment'
|
||||
|
||||
export function dprobeHeartbeat(conf: Conf) {
|
||||
@@ -10,8 +10,12 @@ export function dprobeHeartbeat(conf: Conf) {
|
||||
const last = moment(data, 'YYYY-MM-DD HH:mm:ss\n')
|
||||
const past = moment().diff(last)
|
||||
if (past > dconf.lastBeat) {
|
||||
throw 'Delay is over'
|
||||
return UrlWatcherResult.ko('Delay is over')
|
||||
}
|
||||
})(dconf)
|
||||
return UrlWatcherResult.ok()
|
||||
})(dconf,
|
||||
() => `[OK] hearbeat is up-to-date`,
|
||||
() => `[FAILURE] hearbeat`,
|
||||
() => `[RECOVERED] hearbeat`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export function webDiffWatcher(conf: Conf) {
|
||||
() => mail.onEstablished(conf, target, 'webdiff successfully started')(webDiffConf.cc),
|
||||
|
||||
// When a disconnection is detected
|
||||
(waitingDelay: number) => mail.onDisconnect(conf, target, 'Diff detected', (waitingDelay: number) => `
|
||||
(waitingDelay: number) => mail.onDisconnect(conf, target, 'Diff detected', undefined, (waitingDelay: number) => `
|
||||
${htmlDiff}
|
||||
<p>
|
||||
Waiting ${(waitingDelay / 1000).toFixed(0)} seconds before trying to reconnect.
|
||||
@@ -78,10 +78,6 @@ export function webDiffWatcher(conf: Conf) {
|
||||
},
|
||||
|
||||
() => mail.onRestartSuccess(conf, target)(webDiffConf.cc),
|
||||
|
||||
async (e) => {
|
||||
console.error(e.message)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {Conf, ConfWWMeta} from "../../types/conf";
|
||||
import {urlWatcher} from '../abstract/url-watcher'
|
||||
import {urlWatcher, UrlWatcherResult} from '../abstract/url-watcher'
|
||||
|
||||
function handleLateness(confHead: ConfWWMeta, data: WWMetaJson) {
|
||||
const diff = Math.round(Date.now()/1000 - data.now)
|
||||
if (diff >= confHead.maxLate) {
|
||||
throw `WWMeta.json is late by ${diff}s (>= ${confHead.maxLate})`
|
||||
return UrlWatcherResult.ko(`WWMeta.json is late by ${diff}s (>= ${confHead.maxLate})`)
|
||||
}
|
||||
return UrlWatcherResult.ok()
|
||||
}
|
||||
|
||||
export function jsonWatcher(conf: Conf) {
|
||||
@@ -15,12 +16,15 @@ export function jsonWatcher(conf: Conf) {
|
||||
return async (confWWMeta: ConfWWMeta) => {
|
||||
|
||||
return urlWatcher(conf, async (data) => {
|
||||
handleLateness(confWWMeta, data)
|
||||
return handleLateness(confWWMeta, data)
|
||||
})({
|
||||
name: `WWMeta.json watcher ${confWWMeta.address}`,
|
||||
address: confWWMeta.address + URL_PATH,
|
||||
frequency: confWWMeta.frequency
|
||||
})
|
||||
},
|
||||
() => `[OK] WWMeta.json is up-to-date`,
|
||||
() => `[FAILURE] WWMeta.json`,
|
||||
() => `[RECOVERED] WWMeta.json`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,6 @@ export function ws2pWatcher(conf: Conf) {
|
||||
},
|
||||
|
||||
mail.onRestartSuccess(conf, target),
|
||||
|
||||
mail.onError(conf, target)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user