UNPKG

@egeria/egeria

Version:

Egeria bestows wisdom and knowledge

229 lines (197 loc) 7.41 kB
/* .--. .-'. .--. .--. .--. .--. .`-. .--. :::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\ ' `--' `.-' `--' `--' `--' `-.' `--' ` Egeria - She bestows Knowledge and Wisdom Copyright (C) 2016-2019 MySidesTheyAreGone <mysidestheyaregone@protonmail.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. .--. .-'. .--. .--. .--. .--. .`-. .--. :::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\::::::::.\ ' `--' `.-' `--' `--' `--' `-.' `--' ` */ module.exports = async function (userconf) { process.once('unhandledException', (e) => { console.log('UNHANDLED EXCEPTION - CRASHING') console.log(e.stack) process.exit(1) }) process.once('unhandledRejection', (e) => { console.log('UNHANDLED REJECTION - CRASHING') console.log(e.stack) shutdown() }) const path = require('path') const R = require('ramda') const Baobab = require('baobab') const T = require('@egeria/tools') const Logger = require('@egeria/logger') const FS = require('@egeria/fslib') const Queue = require('@egeria/queue') const Auth = require('@egeria/auth') const Storage = require('@egeria/storage') const Cache = require('@egeria/cache') const PluginManager = require('@egeria/plugin-manager') const Job = require('@egeria/job') const _baobabCfg = { immutable: false, persistent: false, autoCommit: true, asynchronous: false } const userHomeDir = require('os').homedir() const _defaultAppstate = { prefix: 'EGERIA |', system: { port: 54321, logLevels: { silly: false, debug: false, info: true, warning: true, error: true }, logFile: path.resolve(userHomeDir, '.egeria', 'egeria.log'), masterPassword: '1234567812345678', directories: { base: path.resolve(userHomeDir, '.egeria') } }, jobs: [] } function interval (delay) { return new Promise((resolve) => { setTimeout(resolve, delay) }) } // [INIT] let cfg = R.clone(_defaultAppstate) cfg.system = R.merge(_defaultAppstate.system, userconf.system) cfg.jobs = R.merge(_defaultAppstate.jobs, userconf.jobs) let state = new Baobab(cfg, _baobabCfg) let systemcfg = state.select('system') // setup logging let logger = Logger('YYYY-MM-DD HH:mm:ss', { logLevels: cfg.system.logLevels }) state.set('outbox', { push: logger.log }) const logError = (message, origin, data) => T.log(state, 'error', message, origin, data) const logInfo = (message, origin, data) => T.log(state, 'info', message, origin, data) const logDebug = (message, origin, data) => T.log(state, 'debug', message, origin, data) const logSilly = (message, origin, data) => T.log(state, 'silly', message, origin, data) let baseDir = systemcfg.get('directories', 'base') let idBaseDir = systemcfg.get('directories', 'identities') let storageBaseDir = systemcfg.get('directories', 'memory') if (R.isNil(idBaseDir)) { idBaseDir = path.resolve(baseDir, 'identities') } if (R.isNil(storageBaseDir)) { storageBaseDir = path.resolve(baseDir, 'memory') } try { await FS.mkdir(baseDir) await FS.mkdir(idBaseDir) await FS.mkdir(storageBaseDir) } catch (e) { console.log('FATAL ERROR') console.log(e.stack) process.exit(1) } logInfo('Diverting main power to secondary subsystems...') // setup queue state state.select('subsystem', 'queue').set({ outbox: { push: logger.log } }) let queue = Queue(state.select('subsystem', 'queue')) logInfo('Action queue: ONLINE') // setup identity manager state.select('subsystem', 'auth').set({ masterPassword: systemcfg.get('masterPassword'), directory: idBaseDir, outbox: { push: logger.log } }) let auth = Auth(queue, state.select('subsystem', 'auth')) logInfo('Identity manager: ONLINE') // setup memory cache let cache = Cache() logInfo('Cache: ONLINE') // setup storage manager state.select('subsystem', 'storageManager').set({ configuration: { keyField: 'key', ttlField: 'system:ttl', storage: state.get('system', 'storage'), storageDirectory: storageBaseDir }, outbox: { push: logger.log } }) let storage = Storage(state.select('subsystem', 'storageManager')) logInfo('Storage manager: ONLINE') // setup plugin manager const plugins = require('../data/plugins.json') state.select('subsystem', 'pluginManager').set({ plugins: plugins, moduleBaseDir: baseDir, outbox: { push: logger.log } }) let pluginManager = PluginManager(state.select('subsystem', 'pluginManager')) logInfo('Plugin manager: ONLINE') logInfo('Assembling jobs...') let jobcfg = state.select('jobs', 0) while (!R.isNil(jobcfg) && !R.isNil(jobcfg.get())) { jobcfg.set('outbox', { push: logger.log }) let jobName = jobcfg.get('name') let action = 'While assembling job ' + jobName try { let job = Job(queue, pluginManager, auth, storage, cache, jobcfg) jobcfg.set('instance', job) await job.construct() job.start() } catch (e) { logError(action, e) process.exit(1) } logInfo('Job "' + jobName + '": ONLINE') jobcfg = jobcfg.right() } logInfo('All systems nominal.') async function shutdown () { logInfo('KILL SIGNAL RECEIVED - INITIATING SELF-DESTRUCT SEQUENCE') let job = state.select('jobs', 0) while (!R.isNil(job) && !R.isNil(job.get())) { let jobName = job.get('name') job.get('instance').stop() logDebug('Job "' + jobName + '": stopped') job = job.right() } queue.shutdown() await interval(1) logInfo('Queue manager: OFFLINE') job = state.select('jobs', 0) while (!R.isNil(job) && !R.isNil(job.get())) { let jobName = job.get('name') let action = 'While destroying job ' + jobName logSilly('Destroying job "' + jobName + '"...') try { await job.get('instance').destruct() } catch (e) { logError(action, e) } logInfo('Job "' + jobName + '": OFFLINE') job = job.right() } logInfo('All systems OFFLINE. Shutting down...') try { let gby = require('../data/goodbye.json') logInfo(gby[Math.floor(Math.random() * gby.length)] + ' \n\n') process.exit(0) } catch (e) { process.exit(1) } } return { shutdown } }