@remote.it/core
Version:
Core remote.it JavasScript/TypeScript library
124 lines (108 loc) • 3.55 kB
text/typescript
import { ConfigFile } from './ConfigFile'
import { FileWatcher } from './FileWatcher'
import { ProcessManagerMessage } from './ProcessManager'
import { ServiceProcessManager } from './ServiceProcessManager'
import { SChannelListener } from './SChannelListener'
import { TargetProcessManager } from './TargetProcessManager'
import { UDPEventBroadcaster } from './UDPEventBroadcaster'
import { Logger } from './Logger'
const SERVICE_EVENTS: ProcessManagerMessage[] = [
'adding',
'added',
'starting',
'started',
'restarting',
'restarted',
'stopping',
'stopped',
]
const TARGET_EVENTS: ProcessManagerMessage[] = [
'adding',
'added',
'starting',
'started',
'restarting',
'restarted',
'stopping',
'stopped',
]
export class ProcessSupervisor {
config: ConfigFile
target: TargetProcessManager
services: ServiceProcessManager
broadcaster: UDPEventBroadcaster
constructor(public configPath: string, public broadcastPort: number = 55000) {
this.broadcaster = this.configureUDPEventBroadcaster()
Logger.info('watching file:', { configPath })
this.config = new ConfigFile(configPath)
this.target = this.manageTargetProcess()
this.services = this.manageServiceProcesses()
this.watchConfigFile()
this.listenToSChannel()
Logger.info('process supervisor started')
}
private configureUDPEventBroadcaster() {
const broadcaster = new UDPEventBroadcaster(this.broadcastPort)
broadcaster.broadcast('started:' + this.broadcastPort)
return broadcaster
}
private manageTargetProcess() {
const target = new TargetProcessManager()
TARGET_EVENTS.map(e =>
target.on(e, uid => this.broadcaster.broadcast(`target/${e}/${uid}`))
)
target.update(this.config.target)
return target
}
private manageServiceProcesses() {
const services = new ServiceProcessManager()
SERVICE_EVENTS.map(e =>
services.on(e, uid => this.broadcaster.broadcast(`service/${e}/${uid}`))
)
services.update(this.config.services)
return services
}
private watchConfigFile() {
const watcher = new FileWatcher(this.configPath)
watcher.on('ready', path => Logger.info('watcher ready', { path }))
watcher.on('created', path => Logger.info('file created', { path }))
watcher.on('updated', () => {
this.services.update(this.config.services)
this.target.update(this.config.target)
// initiators.update(config.initiators)
})
watcher.on('removed', path => Logger.info('file removed', { path }))
watcher.on('error', error => Logger.error('watcher error', { error }))
}
private listenToSChannel() {
const schannel = new SChannelListener()
schannel.on('ready', () => {
Logger.info('schannel listener ready')
this.broadcastStatus()
})
schannel.on('error', error =>
Logger.info('schannel listener error:', { error })
)
schannel.on('message', message => {
Logger.info('schannel listener message:', { message })
if (message === 'status') this.broadcastStatus()
})
schannel.on('closed', () => Logger.info('schannel listener closed'))
schannel.listen()
}
private broadcastStatus() {
this.broadcaster.broadcast(
'status:' +
JSON.stringify({
target: this.target.processes.map(p => ({
pid: p.process.pid,
uid: p.config.uid,
})),
services: this.services.processes.map(p => ({
pid: p.process.pid,
uid: p.config.uid,
})),
})
)
}
}