[enh] Watch ww and ww2 diff
This commit is contained in:
5
app.yml
5
app.yml
@@ -54,6 +54,11 @@ dprobeHeartbeats:
|
|||||||
frequency: 60000 # 1'
|
frequency: 60000 # 1'
|
||||||
lastBeat: 300000 # 5'
|
lastBeat: 300000 # 5'
|
||||||
|
|
||||||
|
webDiffServers:
|
||||||
|
- file1: https://wotwizard.cgeek.fr/WWMeta.json
|
||||||
|
file2: https://wotwizard2.cgeek.fr/WWMeta.json
|
||||||
|
frequency: 60000
|
||||||
|
|
||||||
mail:
|
mail:
|
||||||
enabled: false
|
enabled: false
|
||||||
host: smtp.sparkpostmail.com
|
host: smtp.sparkpostmail.com
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
"author": "cgeek <cem.moreau@gmail.com>",
|
"author": "cgeek <cem.moreau@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/diff": "^4.0.2",
|
||||||
"@types/minimist": "^1.2.0",
|
"@types/minimist": "^1.2.0",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
|
"diff": "^4.0.1",
|
||||||
"duniter": "^1.8.0",
|
"duniter": "^1.8.0",
|
||||||
"js-yaml": "^3.12.1",
|
"js-yaml": "^3.12.1",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.0",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import * as fs from 'fs';
|
|||||||
import {ws2pWatcher} from "./watchers/ws2p/ws2p-watcher";
|
import {ws2pWatcher} from "./watchers/ws2p/ws2p-watcher";
|
||||||
import {bmaWatcher} from "./watchers/bma/bma-watcher";
|
import {bmaWatcher} from "./watchers/bma/bma-watcher";
|
||||||
import {dprobeHeartbeat} from './watchers/dprobe/dprobe-heartbeat-watcher'
|
import {dprobeHeartbeat} from './watchers/dprobe/dprobe-heartbeat-watcher'
|
||||||
|
import {webDiffWatcher} from "./watchers/webdiff/webdiff-watcher";
|
||||||
|
|
||||||
export async function dwatch(confFile: string) {
|
export async function dwatch(confFile: string) {
|
||||||
|
|
||||||
@@ -13,4 +14,5 @@ export async function dwatch(confFile: string) {
|
|||||||
await Promise.all((conf.ws2pServers || []).map(ws2pWatcher(conf)))
|
await Promise.all((conf.ws2pServers || []).map(ws2pWatcher(conf)))
|
||||||
await Promise.all((conf.bmaServers || []).map(bmaWatcher(conf)))
|
await Promise.all((conf.bmaServers || []).map(bmaWatcher(conf)))
|
||||||
await Promise.all((conf.dprobeHeartbeats || []).map(dprobeHeartbeat(conf)))
|
await Promise.all((conf.dprobeHeartbeats || []).map(dprobeHeartbeat(conf)))
|
||||||
|
await Promise.all((conf.webDiffServers || []).map(webDiffWatcher(conf)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,40 +31,40 @@ export async function sendMail(conf: ConfMail, subject: string, html: string) {
|
|||||||
|
|
||||||
export const mail = {
|
export const mail = {
|
||||||
|
|
||||||
onEstablished: (conf: Conf, target: string) => {
|
onEstablished: (conf: Conf, target: string, message = `Connection established for ${target}`, getHtml: () => string = () => `
|
||||||
return async () => {
|
|
||||||
console.log('Connection established for %s', target)
|
|
||||||
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] Connection established`, `
|
|
||||||
<p>
|
<p>
|
||||||
Connection from [${os.hostname}] to ${target} established on ${moment().format('DD-MM-YYYY HH:mm:ss')}.
|
Connection from [${os.hostname}] to ${target} established on ${moment().format('DD-MM-YYYY HH:mm:ss')}.
|
||||||
</p>
|
</p>
|
||||||
`)
|
`) => {
|
||||||
|
return async () => {
|
||||||
|
console.log(`${message}`)
|
||||||
|
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] ${message}`, getHtml())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDisconnect: (conf: Conf, target: string) => {
|
onDisconnect: (conf: Conf, target: string, message = `Connection closed for ${target}`, getHtml: (waitingDelay: number) => string = (waitingDelay: number) => `
|
||||||
return async (waitingDelay: number) => {
|
|
||||||
console.log('Connection closed for %s', target)
|
|
||||||
console.log('Waiting %s seconds...', (waitingDelay / 1000).toFixed(0))
|
|
||||||
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] Connection closed`, `
|
|
||||||
<p>
|
<p>
|
||||||
Connection from [${os.hostname}] to ${target} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
|
Connection from [${os.hostname}] to ${target} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Waiting ${(waitingDelay / 1000).toFixed(0)} seconds before trying to reconnect.
|
Waiting ${(waitingDelay / 1000).toFixed(0)} seconds before trying to reconnect.
|
||||||
</p>
|
</p>
|
||||||
`)
|
`) => {
|
||||||
|
return async (waitingDelay: number) => {
|
||||||
|
console.log(`${message}`)
|
||||||
|
console.log('Waiting %s seconds...', (waitingDelay / 1000).toFixed(0))
|
||||||
|
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] ${message}`, getHtml(waitingDelay))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onRestartSuccess: (conf: Conf, target: string) => {
|
onRestartSuccess: (conf: Conf, target: string, message = `Connection recovered for ${target}`, getHtml: () => string = () => `
|
||||||
return async () => {
|
|
||||||
console.log('Connection recovered for %s', target)
|
|
||||||
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] Connection recovered`, `
|
|
||||||
<p>
|
<p>
|
||||||
Connection from [${os.hostname}] to ${target} was recovered on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
|
Connection from [${os.hostname}] to ${target} was recovered on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
|
||||||
</p>
|
</p>
|
||||||
`)
|
`) => {
|
||||||
|
return async () => {
|
||||||
|
console.log(`${message}`)
|
||||||
|
await sendMail(conf.mail, `[dwatcher] [${os.hostname}] ${message}`, getHtml())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface Conf {
|
|||||||
ws2pServers: ConfWS2P[]
|
ws2pServers: ConfWS2P[]
|
||||||
bmaServers: ConfBMA[]
|
bmaServers: ConfBMA[]
|
||||||
dprobeHeartbeats: ConfDprobeHeartbeat[]
|
dprobeHeartbeats: ConfDprobeHeartbeat[]
|
||||||
|
webDiffServers: ConfWebDiff[]
|
||||||
mail: ConfMail
|
mail: ConfMail
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,6 +21,12 @@ export interface ConfURL {
|
|||||||
frequency: number
|
frequency: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConfWebDiff {
|
||||||
|
file1: string
|
||||||
|
file2: string
|
||||||
|
frequency: number
|
||||||
|
}
|
||||||
|
|
||||||
export interface ConfBMA extends ConfURL {
|
export interface ConfBMA extends ConfURL {
|
||||||
maxLate?: number
|
maxLate?: number
|
||||||
}
|
}
|
||||||
|
|||||||
90
src/lib/watchers/webdiff/webdiff-watcher.ts
Normal file
90
src/lib/watchers/webdiff/webdiff-watcher.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import {watcherLoop} from "../../watcherLoop";
|
||||||
|
import {Conf, ConfBMA, ConfWebDiff} from "../../types/conf";
|
||||||
|
import Axios from "axios";
|
||||||
|
import {mail} from "../../mail";
|
||||||
|
import {diffChars} from "diff";
|
||||||
|
import * as fs from "fs";
|
||||||
|
import * as path from "path";
|
||||||
|
import {moment} from "duniter/app/lib/common-libs/moment";
|
||||||
|
|
||||||
|
export function webDiffWatcher(conf: Conf) {
|
||||||
|
|
||||||
|
return async (webDiffConf: ConfWebDiff) => {
|
||||||
|
|
||||||
|
const target = `${webDiffConf.file1} <-> ${webDiffConf.file2}`
|
||||||
|
let nodeDownRes: () => void
|
||||||
|
let nodeDownPromise: Promise<void> = new Promise(res => nodeDownRes = res)
|
||||||
|
let htmlDiff = ''
|
||||||
|
|
||||||
|
function handleData(data1: { data: any }, data2: { data: any }) {
|
||||||
|
const json1 = JSON.stringify(data1.data, null, ' ')
|
||||||
|
const json2 = JSON.stringify(data2.data, null, ' ')
|
||||||
|
if (json1 !== json2) {
|
||||||
|
const diff = diffChars(json1, json2)
|
||||||
|
|
||||||
|
htmlDiff = ''
|
||||||
|
diff.forEach(function (part) {
|
||||||
|
// green for additions, red for deletions
|
||||||
|
// grey for common parts
|
||||||
|
const htmlStripped = part.value
|
||||||
|
.replace(/\n/g, '<br/>')
|
||||||
|
.replace(/ /g, ' ')
|
||||||
|
const color = part.added ? 'green' :
|
||||||
|
part.removed ? 'red' : 'grey';
|
||||||
|
|
||||||
|
htmlDiff += `<span style="color: ${color};">${htmlStripped}</span>`
|
||||||
|
});
|
||||||
|
|
||||||
|
if (htmlDiff) {
|
||||||
|
fs.writeFileSync(path.join(__dirname, 'diff.html'), htmlDiff, 'utf8')
|
||||||
|
}
|
||||||
|
console.log('Diff done')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await watcherLoop(
|
||||||
|
async () => {
|
||||||
|
const data1 = await Axios.get(webDiffConf.file1)
|
||||||
|
const data2 = await Axios.get(webDiffConf.file2)
|
||||||
|
handleData(data1, data2)
|
||||||
|
let interval = setInterval(async () => {
|
||||||
|
try {
|
||||||
|
const data1 = await Axios.get(webDiffConf.file1)
|
||||||
|
const data2 = await Axios.get(webDiffConf.file2)
|
||||||
|
handleData(data1, data2)
|
||||||
|
} catch (e) {
|
||||||
|
clearInterval(interval)
|
||||||
|
nodeDownRes()
|
||||||
|
// Re-create down promise for future connection trial
|
||||||
|
nodeDownPromise = new Promise(res => nodeDownRes = res)
|
||||||
|
}
|
||||||
|
}, webDiffConf.frequency)
|
||||||
|
},
|
||||||
|
|
||||||
|
() => nodeDownPromise,
|
||||||
|
|
||||||
|
conf.reconnectionDelays,
|
||||||
|
|
||||||
|
mail.onEstablished(conf, target, 'webdiff successfully started'),
|
||||||
|
|
||||||
|
// When a disconnection is detected
|
||||||
|
mail.onDisconnect(conf, target, 'Diff detected', (waitingDelay: number) => `
|
||||||
|
${htmlDiff}
|
||||||
|
<p>
|
||||||
|
Waiting ${(waitingDelay / 1000).toFixed(0)} seconds before trying to reconnect.
|
||||||
|
</p>
|
||||||
|
`),
|
||||||
|
|
||||||
|
async () => {
|
||||||
|
console.log('Trying to connect to %s', target)
|
||||||
|
},
|
||||||
|
|
||||||
|
mail.onRestartSuccess(conf, target),
|
||||||
|
|
||||||
|
async (e) => {
|
||||||
|
console.error(e.message)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
axios "*"
|
axios "*"
|
||||||
|
|
||||||
|
"@types/diff@^4.0.2":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c"
|
||||||
|
|
||||||
"@types/events@*":
|
"@types/events@*":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
||||||
@@ -706,6 +710,10 @@ dicer@0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
streamsearch "0.1.2"
|
streamsearch "0.1.2"
|
||||||
|
|
||||||
|
diff@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
|
||||||
|
|
||||||
duniter@^1.8.0:
|
duniter@^1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/duniter/-/duniter-1.8.0.tgz#bf9a25f671e9d4244a9e26aae3fdf576a8b2f583"
|
resolved "https://registry.yarnpkg.com/duniter/-/duniter-1.8.0.tgz#bf9a25f671e9d4244a9e26aae3fdf576a8b2f583"
|
||||||
|
|||||||
Reference in New Issue
Block a user