[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

16
app.yml
View File

@@ -1,11 +1,25 @@
currency: g1-test # Ensure we connect to the correct currency
salt: test salt: test
passwd: test passwd: test
connectionTimeout: 10000
reconnectionDelays:
- 5000
- 10000
- 15000
- 30000
- 60000 # 1'
- 300000 # 5'
- 900000 # 15'
- 3600000 # 1h
- 7200000 # 2h
- 21600000 # 6h
- 43200000 # 12h
ws2pServers: ws2pServers:
- address: ws://g1-test.cgeek.fr:20900 - address: ws://g1-test.cgeek.fr:20900
expectedPubkey: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ expectedPubkey: 2ny7YAdmzReQxAayyJZsyVYwYhVyax2thKcGknmQy5nQ
mail: mail:
enabled: true enabled: false
host: smtp.sparkpostmail.com host: smtp.sparkpostmail.com
port: 587 port: 587
auth: LOGIN auth: LOGIN

View File

@@ -2,7 +2,8 @@ export interface Conf {
currency: string currency: string
salt: string salt: string
passwd: string passwd: string
connectionTimeout: 10000 connectionTimeout: number
reconnectionDelays: number[]
ws2pServers: ConfServers[] ws2pServers: ConfServers[]
mail: ConfMail 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 {Scrypt} from 'duniter/app/modules/keypair/lib/scrypt'
import {sendMail} from './sendMail' import {sendMail} from './sendMail'
import {moment} from 'duniter/app/lib/common-libs/moment' import {moment} from 'duniter/app/lib/common-libs/moment'
import {processHandler} from './processHandler'
export async function dwatch(confFile: string) { export async function dwatch(confFile: string) {
@@ -17,36 +18,69 @@ export async function dwatch(confFile: string) {
await Promise.all(conf.ws2pServers.map(async wserver => { await Promise.all(conf.ws2pServers.map(async wserver => {
const localAuth = new WS2PPubkeyLocalAuth(conf.currency, keypair, "", async () => true) await processHandler(
const remoteAuth = new WS2PPubkeyRemoteAuth(conf.currency, keypair, async () => true) () => {
const c = WS2PConnection.newConnectionToAddress( const localAuth = new WS2PPubkeyLocalAuth(conf.currency, keypair, "", async () => true)
1, const remoteAuth = new WS2PPubkeyRemoteAuth(conf.currency, keypair, async () => true)
wserver.address,
new MessageHandler(), return WS2PConnection.newConnectionToAddress(
localAuth, 1,
remoteAuth, wserver.address,
undefined, new MessageHandler(),
{ localAuth,
connectionTimeout: conf.connectionTimeout, remoteAuth,
requestTimeout: 0 // No request anyway undefined,
{
connectionTimeout: conf.connectionTimeout,
requestTimeout: 0 // No request anyway
},
wserver.expectedKey
)
}, },
wserver.expectedKey
)
await c.connectAsInitiator() conf.reconnectionDelays,
c.closed.then(async () => { async (c: WS2PConnection) => {
console.log('Connection closed') console.log('Connection established')
await sendMail(conf.mail, '[dwatcher] Connection closed', ` 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> <p>
Connection to ${c.pubkey} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}. Connection to ${c.pubkey} was lost on ${moment().format('dd-MM-YYYY HH:mm:ss')}.
</p> </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++
}
})()
}