const { intervalToDuration, secondsToMilliseconds, formatDuration } = require('date-fns/fp') const _ = require('lodash/fp') const ticker = require('../ticker') const settingsLoader = require('./settings-loader') const db = require('../db') const machineLoader = require('../machine-loader') const CONSIDERED_UP_SECS = 30 function checkWasConfigured () { return settingsLoader.loadLatest() .then(() => true) .catch(() => false) } function machinesLastPing () { const sql = `select min(extract(epoch from (now() - created))) as age from machine_events group by device_id` return Promise.all([machineLoader.getMachineNames(), db.any(sql)]) .then(([machines, events]) => { if (machines.length === 0) return 'No paired machines' const addName = event => { const machine = _.find(['deviceId', event.deviceId], machines) if (!machine) return null return _.set('name', machine.name, event) } const mapper = _.flow(_.filter(row => row.age > CONSIDERED_UP_SECS), _.map(addName), _.compact) const downRows = mapper(events) if (downRows.length === 0) return 'All machines are up' if (downRows.length === 1) { const row = downRows[0] const age = intervalToDuration({ start: 0, end: secondsToMilliseconds(row.age) }) return `${row.name} down for ${formatDuration(age)}` } return 'Multiple machines down' }) } function status () { const sql = `select extract(epoch from (now() - created)) as age from server_events where event_type=$1 order by created desc limit 1` return Promise.all([checkWasConfigured(), db.oneOrNone(sql, ['ping']), machinesLastPing()]) .then(([wasConfigured, statusRow, machineStatus]) => { const age = statusRow && intervalToDuration({ start: 0, end: secondsToMilliseconds(statusRow.age) }) const up = statusRow ? statusRow.age < CONSIDERED_UP_SECS : false const lastPing = statusRow && formatDuration(age) return settingsLoader.loadLatest() .catch(() => null) .then(settings => { return getRates(settings) .then(rates => ({wasConfigured, up, lastPing, rates, machineStatus})) }) }) } function getRates (settings) { if (!settings) return Promise.resolve([]) return ticker.getRates(settings, 'USD', 'BTC') .then(ratesRec => { return [{ crypto: 'BTC', bid: parseFloat(ratesRec.rates.bid), ask: parseFloat(ratesRec.rates.ask) }] }) .catch(() => []) } module.exports = {status}