import yargs from 'yargs/yargs' import { hideBin } from 'yargs/helpers' import 'node:process' import {RedisConnexion} from './redisConnexion.js' import {configHelper} from '../configHelper.js' import {gpsServer} from './gpsServer.js' ///////////////////////////// Little improvement on console.xxx ///////////////////////////////////// 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('GPS', 'Global positions and collision system 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.1').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 return redis.map(cfg => new RedisConnexion({ debug, config: { ...cfg, ...meshConfig, gps: rootConfig.gps }, redisId: cfg.redisId, meshName, }) ) } async function startAllRedis(rootConfig, cfgh) { if (debug) console.log('Starting all Redis instances...') //1. instantiate all & login all const redisConns = [ ...meshRedisConns(rootConfig.systemMesh, 'system', debug, rootConfig), ...meshRedisConns(rootConfig.arenaMesh, 'arena', debug, rootConfig), ] const srv = new gpsServer(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 }) ) //2. make sure all connected before going any further 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(`chansStart 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') // --- Phase 2: start channels for all (since all succeeded) 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'}`) await startAllRedis(rootConfig, cfgh) })