Files
P42_godDaemons/Maestro/p42Maestro.js
T
2026-06-20 18:50:26 +00:00

141 lines
4.4 KiB
JavaScript

import yargs from 'yargs/yargs'
import { hideBin } from 'yargs/helpers'
import 'node:process'
import { RedisConnexion } from '../redisConnexion.js'
import { busReplyRoute } from '../bus/publishActionReply.js'
import { configHelper } from '../configHelper.js'
import { maestroServer } from './maestroServer.js'
import * as systemMesh from './actions/system/index.js'
import * as arenaMesh from './actions/arena/index.js'
const meshModules = {
system: systemMesh,
arena: arenaMesh,
}
const originalLog = console.log
const originalWarn = console.warn
const originalError = console.error
function logWithTimestamp(originalFn, level, ...args) {
const timestamp = new Date().toISOString()
originalFn(`[${timestamp}] [${level}]`, ...args)
}
console.log = (...args) => logWithTimestamp(originalLog, 'LOG', ...args)
console.warn = (...args) => logWithTimestamp(originalWarn, 'WARN', ...args)
console.error = (...args) => logWithTimestamp(originalError, 'ERROR', ...args)
const argv = yargs(hideBin(process.argv)).command('Maestro', 'Simulation orchestrator for P42', {})
.options({
'debug': {
description: 'shows debug info',
alias: 'd',
defaut: false,
type: 'boolean'
},
'config': {
description: 'Points to config file (default: ../config.json)',
alias: 'c',
default: '../config.json',
type: 'string'
},
}).help().version('1.0').argv
const debug = Boolean(process.env.DEBUG) || argv.debug
let cfgh = new configHelper({
localfile: argv.config,
})
function meshRedisConns(mesh, meshName, debug, rootConfig) {
const { redis, ...meshConfig } = mesh
const busRoute = busReplyRoute(rootConfig.maestro, meshName)
return redis.map(cfg =>
new RedisConnexion({
debug,
config: { ...cfg, ...meshConfig, maestro: rootConfig.maestro },
redisId: cfg.redisId,
meshName,
meshModule: meshModules[meshName],
senderId: busRoute?.senderId,
actionsReply: busRoute?.actionsReply,
})
)
}
async function startAllRedis(rootConfig, cfgh) {
if(debug) console.log('Starting all Redis instances...')
const redisConns = [
...meshRedisConns(rootConfig.systemMesh, 'system', debug, rootConfig),
...meshRedisConns(rootConfig.arenaMesh, 'arena', debug, rootConfig),
]
const srv = new maestroServer(cfgh, redisConns, debug)
for(const cnx of redisConns) {
if(cnx.meshName === 'system') srv.wireSystemConnexion(cnx)
else if(cnx.meshName === 'arena') srv.wireArenaConnexion(cnx)
}
const loginResults = await Promise.allSettled(
redisConns.map(async cnx => {
await cnx.redisLogin()
return(cnx.redisId)
})
)
const failedLogin = loginResults.filter(r => r.status !== 'fulfilled')
if(failedLogin.length > 0) {
console.error('Redis login failures:')
failedLogin.forEach((r, i) => {
const id = redisConns[i].redisId
console.error(`login failed for redis:[${id}] → ${r.reason}`)
})
throw new Error(
`Redis login failed for ${failedLogin.length}/${redisConns.length} instances`
)
}
if(debug) console.log('All Redis logins OK')
const chanResults = await Promise.allSettled(
redisConns.map(async cnx => {
await cnx.redisChansStart()
return(cnx.redisId)
})
)
const failedChans = chanResults.filter(r => r.status !== 'fulfilled')
if(failedChans.length > 0) {
console.error('Redis chansStart failures:')
failedChans.forEach((r, i) => {
const id = redisConns[i].redisId
console.error(`chansStart failed for redis:[${id}] → ${r.reason}`)
})
throw new Error(
`Redis chansStart failed for ${failedChans.length}/${redisConns.length} instances`
)
}
if(debug) console.log('All Redis chansStart OK')
return({ redisConns, srv })
}
cfgh.fetchConfig().then(async rootConfig => {
if(!rootConfig) {
console.error('Cannot get a valid configuration ! Aaarrghhh...')
process.exit()
}
console.log(`Debug mode : ${debug ? 'ON' : 'OFF'}`)
const { srv } = await startAllRedis(rootConfig, cfgh)
const dbOk = await srv.init()
if(!dbOk) {
console.error('Maestro MySQL init failed — exiting')
process.exit(1)
}
})