uci-socket/src/socket.mjs

83 lines
2.2 KiB
JavaScript

import { Server } from 'net'
import { unlink as fileDelete } from 'fs'
import btc from 'better-try-catch'
import Logger from 'simple-node-logger'
import ON_DEATH from 'death' //this is intentionally ugly
let logger = {
logFilePath:'logfile.log',
timestampFormat:'YYYY-MM-DD HH:mm:ss.SSS'
}
export default class Socket extends Server {
constructor (path, opts={}) {
super()
this.path = path
this.logger = Logger.createSimpleLogger(opts.logger ? opts.logger: logger)
} // end constructor
async create ( app ) {
this.on('error', async (err) => {
// recover from socket file that was not removed
if (err.code === 'EADDRINUSE') {
console.log(`socket path ${this.path} already exists...deleting`)
await fileDelete(this.path)
await this.listen(this.path)
return Promise.resolve(err.code)
}
// otherwise fatally exit
console.log('error creating socket: ',err.code)
return Promise.reject(err.code)
})
//
this.on('listening', async () => {
console.log(`socket created at ${this.path}`)
// this gets called for each client connection and is unique to each
this.on('connection', (socket) => {
console.log('new consumer connected')
socket.on('data', async (buf) => {
let [err, packet] = btc(JSON.parse)(buf.toString())
if (!err) {
this.logger.info(`data packet received to socket \n ${packet}`)
socket.write(JSON.stringify(await app.processPacket.bind(app)(packet)))
}
else { console.log(`bad packet JSON syntax \n ${buf.toString()}`)}
}) // end incoming data listerner
}) // end connected consumer
}) // end socket listening listener
// start it
await this.listen(this.path)
// if socket is terminated then shutdown gracefully
ON_DEATH( async () => {
await this.destroy()
})
process.once('SIGUSR2', async () => {
await this.destroy
process.kill(process.pid, 'SIGUSR2')
})
} // end create
async destroy () {
console.log('\nclosing down socket')
await this.close()
console.log('\n all connections closed....exiting')
process.exit()
} // end destroy
} // end class