Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 49 additions & 135 deletions app/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,8 @@ const { Log } = require('@aliceo2/web-ui');
const config = require('./lib/config/configProvider.js');
const { buildPublicConfig } = require('./lib/config/publicConfigProvider.js');

// IO
const readline = require('readline');
const Utils = require('./lib/utils');
const { Console } = require('node:console');

// Services
const services = require('./lib/alimonitor-services');

const alimonitorServices = require('./lib/alimonitor-services');
// Database
const database = require('./lib/database');

Expand All @@ -34,6 +28,11 @@ const { webUiServer } = require('./lib/server');
const EP = config.public.endpoints;
Log.configure(config);

// IO
const readline = require('readline');
const Utils = require('./lib/utils');
const { Console } = require('node:console');

/**
* RunConditionTable application
*/
Expand All @@ -45,91 +44,14 @@ class RunConditionTableApplication {

this.webUiServer = webUiServer;
this.databaseService = database.databaseService;
this.services = services;
this.databaseService.healthcheckInsertData();
this.syncManager = alimonitorServices.syncManager;
this.defineEndpoints();

buildPublicConfig(config);
this.buildCli();
}

buildCli() {
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
prompt: '==> ',
});
this.rl.on('line', (line) => this.devCli(line));
this.con = new Console({ stdout: process.stdout, stderr: process.stderr });
}

devCli(line) {
try {
const cmdAndArgs = line.trim().split(/ +/).map((s) => s.trim());
const dbAdminExec = (args) => {
this.databaseService.adminClient
.query(args.join(' '))
.then(this.con.log)
.catch((e) => {
this.con.log(e);
});
};
const shExec = (args) => {
Utils.exec(args)
.then(this.con.log)
.catch((e) => {
this.con.log(e);
});
};
Utils.switchCase(cmdAndArgs[0], {
'': () => {},
hc: () => this.databaseService.healthcheck(),
users: () => {
this.con.log(this.databaseService.loggedUsers);
},
pool: () => {
this.con.log(this.databaseService.pool);
},
now: () => {
dbAdminExec(['select now();']);
},
psql: dbAdminExec,
sh: shExec,
bk: (args) => this.servCLI(this.services.bookkeepingService, args),
ml: (args) => this.servCLI(this.services.monalisaService, args),
mc: (args) => this.servCLI(this.services.monalisaServiceMC, args),
sync: () => this.syncAll(),
connServ: async () => {
await this.connectServices();
},
app: (args) => this.applicationCli(args),
}, this.incorrectCommand())(cmdAndArgs.slice(1));
this.rl.prompt();
} catch (error) {
this.con.error(error.message);
}
}

applicationCli(args) {
Utils.switchCase(args[0], {
stop: () => this.stop(),
run: () => this.run(),
}, this.incorrectCommand())();
}

servCLI(serv, args) {
Utils.switchCase(args[0], {
state: () => this.con.log(args[1] ? serv?.[args[1]] : serv),
stop: () => serv.clearSyncTask(),
start: () => serv.setSyncTask(),
logdepth: () => serv.setLogginLevel(args[1]),
}, this.incorrectCommand())();
}

incorrectCommand() {
return () => this.con.log('incorrect command');
}

defineEndpoints() {
const { httpServer } = this;
const { databaseService } = this;
Expand All @@ -139,22 +61,7 @@ class RunConditionTableApplication {
httpServer.get(EP.rctData, (req, res) => databaseService.pgExecFetchData(req, res));
httpServer.post(EP.insertData, (req, res) => databaseService.pgExecDataInsert(req, res));
httpServer.get(EP.date, (req, res) => databaseService.getDate(req, res));
httpServer.get(EP.sync, async (_req, _res) => this.syncAll());
}

async syncAll() {
await this.services.bookkeepingService.setSyncTask();
await this.services.monalisaService.setSyncTask();
await this.services.monalisaServiceMC.setSyncTask();
}

async setSyncAllTask() {
this.syncAll();
this.syncAllTask = setInterval(this.syncAll, 24 * 60 * 60 * 1000); // Ones per day
}

async clearSyncAllTask() {
clearInterval(this.setSyncAllTask);
httpServer.get(EP.sync, async (_req, _res) => this.syncManager.syncAll());
}

async restart() {
Expand All @@ -170,27 +77,9 @@ class RunConditionTableApplication {
this.logger.error(`Error while starting RCT app: ${error}`);
await this.stop();
}

await this.connectServices();
if (config.syncTaskAtStart) {
this.setSyncAllTask();
}
this.logger.info('RCT app started');
}

async connectServices() {
const errors = [];
await this.databaseService.setAdminConnection()
.catch((e) => errors.push(e));
await Promise.all(
Object.values(this.services)
.map((serv) => serv.dbConnect()),
).catch((e) => errors.push(e));
if (errors.length > 0) {
this.logger.error(`Error while starting services: ${errors.map((e) => e.message).join(', ')}`);
}
}

async stop() {
if (! this.isStopping) {
this.isStopping = true;
Expand All @@ -200,8 +89,7 @@ class RunConditionTableApplication {
} catch (error) {
this.logger.error(`Error while stopping RCT app: ${error}`);
}
await this.disconnectServices();
await this.clearSyncAllTask();
await this.syncManager.clearSyncAllTask();
this.rl.close();

this.logger.info('RCT app stopped');
Expand All @@ -210,19 +98,6 @@ class RunConditionTableApplication {
}
}

async disconnectServices() {
const errors = [];
await this.databaseService.disconnect()
.catch((e) => errors.push(e));
await Promise.all(
Object.values(this.services)
.map((serv) => serv.close()),
).catch((e) => errors.push(e));
if (errors.length > 0) {
this.logger.error(`Error while stopping services: ${errors.map((e) => e.message).join(', ')}`);
}
}

static isInTestMode() {
return process.env.ENV_MODE === 'test';
}
Expand All @@ -238,6 +113,45 @@ class RunConditionTableApplication {
get httpServer() {
return this.webUiServer.httpServer;
}

buildCli() {
this.rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
prompt: '==> ',
});
this.rl.on('line', (line) => this.devCli(line));
this.con = new Console({ stdout: process.stdout, stderr: process.stderr });
}

devCli(line) {
try {
const cmdAndArgs = line.trim().split(/ +/).map((s) => s.trim());
Utils.switchCase(cmdAndArgs[0], {
'': () => {},
users: () => {
this.con.log(this.databaseService.loggedUsers);
},
sync: () => this.syncManager.syncAll(),
app: (args) => this.applicationCli(args),
}, this.incorrectCommand())(cmdAndArgs.slice(1));
this.rl.prompt();
} catch (error) {
this.con.error(error.message);
}
}

applicationCli(args) {
Utils.switchCase(args[0], {
stop: () => this.stop(),
run: () => this.run(),
}, this.incorrectCommand())();
}

incorrectCommand() {
return () => this.con.log('incorrect command');
}
}

module.exports = new RunConditionTableApplication();
50 changes: 43 additions & 7 deletions app/config/rct-data/healthcheckQueries.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,59 @@ const detectors = require('./detectors.js').sort();
const flags = require('./flags.json');
const physicalParticlesData = require('./physicalParticlesData.js');

const healthcheckQueries = {
const checkStaticData = {
detectors: {
description: 'detectors dict insert',
description: 'Detectors dict insert',
query: detectors.map((d) => `INSERT INTO detectors_subsystems("id", "name") VALUES (DEFAULT, '${d}');`),
},
particle: {
description: 'particles dict insert',
description: 'Particles dict insert',
query: Object.entries(physicalParticlesData).map(([name, d]) => `INSERT INTO particle_phys_data("id", "name", "full_name", "A", "Z")
VALUES (DEFAULT, '${name}', '${d.full_name}', ${d.A}, ${d.Z});`),
VALUES (DEFAULT, '${name}', '${d.full_name}', ${d.A}, ${d.Z});`),
},
flags: {
description: 'flags types dict insert',
query: flags.map((f) => `INSERT INTO flags_types_dictionary("id", "name", "method", "bad", "obsolate")
VALUES (${f.id}, '${f.name}', '${f.method}', ${f.bad}::bool, ${f.obsolete}::bool);`),
description: 'Flag types dict insert',
query: flags.map((f) => `INSERT INTO flag_types_dictionary("id", "name", "method", "bad", "obsolate")
VALUES (${f.id}, '${f.name}', '${f.method}', ${f.bad}::bool, ${f.obsolete}::bool);`),
},
};

const metaObj = {
lastSync: {
name: 'last_sync',
},
};

const queryForName = (name) => `SELECT name, val, extract(epoch from "updatedAt") as "udatedAt" FROM meta WHERE name = '${name}'`;
const updateForName = (name, val) => `INSERT INTO meta (name, val, "updatedAt") values ('${name}', '${val}', now())
ON conflict (name) do update set val = EXCLUDED.val, "updatedAt" = now();`;

const meta = {
objects: metaObj,

readLastSync: {
description: 'Check time of last update',
query: queryForName(metaObj.lastSync.name),
},
setLastSyncInProgress: {
description: 'Store info in DB that sync is in progress',
query: updateForName(metaObj.lastSync.name, 'in_progress'),
},
setLastSyncOK: {
description: 'Store info in DB that sync is done',
query: updateForName(metaObj.lastSync.name, 'ok'),
},
setLastSyncFailed: {
description: 'Store info in DB that sync is done',
query: updateForName(metaObj.lastSync.name, 'failed'),
},
};

const healthcheckQueries = {
checkStaticData,
meta,
};

const suppressHealthcheckLogs = (process.env['RCT_SUPRESS_HEALTHCECK_LOGS']?.toLowerCase() || 'true') == 'true';

module.exports = {
Expand Down
Loading