[enh] Auto-restart

This commit is contained in:
2019-05-28 13:30:59 +02:00
parent fa85ddcc1d
commit 4b4c5807b5
4 changed files with 124 additions and 23 deletions

View File

@@ -2,7 +2,8 @@ export interface Conf {
currency: string
salt: string
passwd: string
connectionTimeout: 10000
connectionTimeout: number
reconnectionDelays: number[]
ws2pServers: ConfServers[]
mail: ConfMail
}

View File

@@ -7,6 +7,7 @@ import {Key} from 'duniter/app/lib/common-libs/crypto/keyring'
import {Scrypt} from 'duniter/app/modules/keypair/lib/scrypt'
import {sendMail} from './sendMail'
import {moment} from 'duniter/app/lib/common-libs/moment'
import {processHandler} from './processHandler'
export async function dwatch(confFile: string) {
@@ -17,36 +18,69 @@ export async function dwatch(confFile: string) {
await Promise.all(conf.ws2pServers.map(async wserver => {
const localAuth = new WS2PPubkeyLocalAuth(conf.currency, keypair, "", async () => true)
const remoteAuth = new WS2PPubkeyRemoteAuth(conf.currency, keypair, async () => true)
await processHandler(
() => {
const c = WS2PConnection.newConnectionToAddress(
1,
wserver.address,
new MessageHandler(),
localAuth,
remoteAuth,
undefined,
{
connectionTimeout: conf.connectionTimeout,
requestTimeout: 0 // No request anyway
const localAuth = new WS2PPubkeyLocalAuth(conf.currency, keypair, "", async () => true)
const remoteAuth = new WS2PPubkeyRemoteAuth(conf.currency, keypair, async () => true)
return WS2PConnection.newConnectionToAddress(
1,
wserver.address,
new MessageHandler(),
localAuth,
remoteAuth,
undefined,
{
connectionTimeout: conf.connectionTimeout,
requestTimeout: 0 // No request anyway
},
wserver.expectedKey
)
},
wserver.expectedKey
)
await c.connectAsInitiator()
conf.reconnectionDelays,
c.closed.then(async () => {
console.log('Connection closed')
await sendMail(conf.mail, '[dwatcher] Connection closed', `
async (c: WS2PConnection) => {
console.log('Connection established')
await sendMail(conf.mail, '[dwatcher] Connection established', `
<p>
Connection to ${c.pubkey} established on ${moment().format('DD-MM-YYYY HH:mm:ss')}.
</p>
`)
},
// When a disconnection is detected
async (c: WS2PConnection, waitingDelay) => {
console.log('Connection closed')
console.log('Waiting %s seconds...', waitingDelay)
await sendMail(conf.mail, '[dwatcher] Connection closed', `
<p>
Connection to ${c.pubkey} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
</p>
<p>
Waiting ${(waitingDelay / 1000).toFixed(0)} seconds before trying to reconnect.
</p>
`)
},
async (c: WS2PConnection) => {
console.log('Trying to connect to %s', c.pubkey)
},
async (c: WS2PConnection) => {
console.log('Connection recovered')
await sendMail(conf.mail, '[dwatcher] Connection recovered', `
<p>
Connection to ${c.pubkey} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
</p>
`)
})
},
await c.connected
async (e) => {
console.error(e)
}
)
console.log('Connected to %s', c.pubkey)
}))
}

52
src/lib/processHandler.ts Normal file
View File

@@ -0,0 +1,52 @@
import {WS2PConnection} from 'duniter/app/modules/ws2p/lib/WS2PConnection'
export async function processHandler(
getConnection: () => WS2PConnection,
reconnectionDelays: number[],
onStart: (c: WS2PConnection) => Promise<void>,
onDisconnection: (c: WS2PConnection, waitingDelay: number) => Promise<void>,
onRestart: (c: WS2PConnection) => Promise<void>,
onRestartSuccess: (c: WS2PConnection) => Promise<void>,
onError: (e: Error) => Promise<void>,
) {
let hasStarted = false
let connection = getConnection()
let connecting = connection.connectAsInitiator()
;(async () => {
let connected = false
let i = 0
while (!connected) {
try {
if (hasStarted) {
await onRestart(connection)
connection = getConnection()
connecting = connection.connectAsInitiator()
}
// Connection trial
await connecting
if (!hasStarted) {
hasStarted = true
await onStart(connection)
} else {
await onRestartSuccess(connection)
}
await connection.closed
} catch (e) {
await onError(e)
}
// Wait before reconnecting
const waitingDelay = reconnectionDelays[Math.min(reconnectionDelays.length - 1, i)]
await onDisconnection(connection, waitingDelay)
await new Promise(resolve => setTimeout(resolve, waitingDelay))
i++
}
})()
}