possible fixes for the blocking heartbeat problem
This commit is contained in:
parent
f8eb00e04e
commit
cb011c903b
6 changed files with 32 additions and 45 deletions
|
@ -4,8 +4,7 @@ const Message = require('./Message');
|
||||||
|
|
||||||
class Audiostream {
|
class Audiostream {
|
||||||
|
|
||||||
constructor(eventParser) {
|
constructor() {
|
||||||
this.eventParser = eventParser;
|
|
||||||
this.#handleEvents();
|
this.#handleEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,23 +32,23 @@ class Audiostream {
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleEvents() {
|
#handleEvents() {
|
||||||
this.eventParser.on('audio:initialize', (data) => {
|
eventparser.on('audio:initialize', (data) => {
|
||||||
logger.debug('handling event \'audio:initialize\'...');
|
logger.debug('handling event \'audio:initialize\'...');
|
||||||
this.#initialize(data);
|
this.#initialize(data);
|
||||||
});
|
});
|
||||||
this.eventParser.on(constants.AUDIO_PLAY, () => {
|
eventparser.on(constants.AUDIO_PLAY, () => {
|
||||||
logger.debug('handling event \'' + constants.AUDIO_PLAY + '\'...');
|
logger.debug('handling event \'' + constants.AUDIO_PLAY + '\'...');
|
||||||
global.player.play();
|
global.player.play();
|
||||||
});
|
});
|
||||||
this.eventParser.on(constants.AUDIO_RESUME, () => {
|
eventparser.on(constants.AUDIO_RESUME, () => {
|
||||||
logger.debug('handling event \'' + constants.AUDIO_RESUME + '\'...');
|
logger.debug('handling event \'' + constants.AUDIO_RESUME + '\'...');
|
||||||
global.player.resume();
|
global.player.resume();
|
||||||
});
|
});
|
||||||
this.eventParser.on(constants.AUDIO_PAUSE, () => {
|
eventparser.on(constants.AUDIO_PAUSE, () => {
|
||||||
logger.debug('handling event \'' + constants.AUDIO_PAUSE + '\'...');
|
logger.debug('handling event \'' + constants.AUDIO_PAUSE + '\'...');
|
||||||
global.player.pause();
|
global.player.pause();
|
||||||
});
|
});
|
||||||
this.eventParser.on(constants.AUDIO_STOP, () => {
|
eventparser.on(constants.AUDIO_STOP, () => {
|
||||||
logger.debug('handling event \'' + constants.AUDIO_STOP + '\'...');
|
logger.debug('handling event \'' + constants.AUDIO_STOP + '\'...');
|
||||||
global.player.stop();
|
global.player.stop();
|
||||||
});
|
});
|
||||||
|
@ -71,9 +70,6 @@ class Audiostream {
|
||||||
socket.on('error', (error) => {
|
socket.on('error', (error) => {
|
||||||
logger.error('error connecting to audio server \'' + this.getTag() + '\': ' + error);
|
logger.error('error connecting to audio server \'' + this.getTag() + '\': ' + error);
|
||||||
});
|
});
|
||||||
socket.on('close', () => {
|
|
||||||
logger.info('connection to audio server \'' + this.getTag() + '\' closed');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
|
|
@ -2,7 +2,6 @@ const util = require('../libs/util.js');
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
|
|
||||||
const Heartbeat = require('./Heartbeat.js');
|
const Heartbeat = require('./Heartbeat.js');
|
||||||
const EventParser = require('./EventParser.js');
|
|
||||||
const Audiostream = require('./Audiostream.js');
|
const Audiostream = require('./Audiostream.js');
|
||||||
|
|
||||||
class Connection {
|
class Connection {
|
||||||
|
@ -16,8 +15,7 @@ class Connection {
|
||||||
}
|
}
|
||||||
this.host = config?.server?.host || "127.0.0.1";
|
this.host = config?.server?.host || "127.0.0.1";
|
||||||
this.port = config?.server?.port || "3000";
|
this.port = config?.server?.port || "3000";
|
||||||
this.eventParser = new EventParser();
|
this.audiostream = new Audiostream();
|
||||||
this.audiostream = new Audiostream(this.eventParser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getHost() {
|
getHost() {
|
||||||
|
@ -53,7 +51,7 @@ class Connection {
|
||||||
#handleEventConnect(resolve, socket) {
|
#handleEventConnect(resolve, socket) {
|
||||||
logger.info('connected to communication server \'' + this.getTag() + '\'...');
|
logger.info('connected to communication server \'' + this.getTag() + '\'...');
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.heartbeat = new Heartbeat(this.eventParser);
|
this.heartbeat = new Heartbeat();
|
||||||
this.#handleHeartbeat();
|
this.#handleHeartbeat();
|
||||||
socket.on('timeout', () => {
|
socket.on('timeout', () => {
|
||||||
this.#handleEventTimeout();
|
this.#handleEventTimeout();
|
||||||
|
@ -67,7 +65,7 @@ class Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
async #handleEventData(data) {
|
async #handleEventData(data) {
|
||||||
this.eventParser.parse(data);
|
eventparser.parse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#handleEventTimeout() {
|
#handleEventTimeout() {
|
||||||
|
@ -93,16 +91,12 @@ class Connection {
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.heartbeat !== undefined) {
|
if (this.heartbeat !== undefined) {
|
||||||
|
this.heartbeat.removeAllListeners();
|
||||||
this.heartbeat.destroy();
|
this.heartbeat.destroy();
|
||||||
this.heartbeat.removeAllListeners('timeout');
|
|
||||||
this.heartbeat = undefined;
|
this.heartbeat = undefined;
|
||||||
}
|
}
|
||||||
if (this.socket !== undefined) {
|
if (this.socket !== undefined) {
|
||||||
this.socket.removeAllListeners('connect');
|
this.socket.removeAllListeners();
|
||||||
this.socket.removeAllListeners('error');
|
|
||||||
this.socket.removeAllListeners('timeout');
|
|
||||||
this.socket.removeAllListeners('close');
|
|
||||||
this.socket.removeAllListeners('data');
|
|
||||||
this.socket.end();
|
this.socket.end();
|
||||||
this.socket.destroy();
|
this.socket.destroy();
|
||||||
this.socket = undefined;
|
this.socket = undefined;
|
||||||
|
|
|
@ -1,52 +1,47 @@
|
||||||
|
const { sleep } = require('../libs/util.js');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const Message = require('./Message.js');
|
const Message = require('./Message.js');
|
||||||
|
|
||||||
class Heartbeat extends EventEmitter {
|
class Heartbeat extends EventEmitter {
|
||||||
|
|
||||||
constructor(eventParser) {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.interval = config?.server?.heartbeat || 10000;
|
this.interval = config?.server?.heartbeat || 10000;
|
||||||
this.eventParser = eventParser;
|
|
||||||
this.#listenForPingPong();
|
this.#listenForPingPong();
|
||||||
this.#sendPing();
|
this.#sendPing();
|
||||||
}
|
}
|
||||||
|
|
||||||
async #sendPing() {
|
async #sendPing() {
|
||||||
if (this.timeout !== undefined) {
|
if (this.destroyed === true) {
|
||||||
clearTimeout(this.timeout);
|
return;
|
||||||
}
|
}
|
||||||
if (this.alive === false) {
|
if (this.alive === false) {
|
||||||
this.emit('timeout');
|
this.emit('timeout');
|
||||||
return;
|
}
|
||||||
} else if (this.alive === undefined) {
|
if (this.alive === undefined) {
|
||||||
await new Promise((resolve, reject) => {
|
await sleep(this.interval);
|
||||||
setTimeout(resolve, this.interval);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
this.alive = false;
|
this.alive = false;
|
||||||
await new Message('ping').send();
|
await new Message('ping').send();
|
||||||
this.timeout = setTimeout(() => {
|
await sleep(this.interval);
|
||||||
this.#sendPing();
|
this.#sendPing();
|
||||||
}, this.interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async #listenForPingPong() {
|
async #listenForPingPong() {
|
||||||
this.eventParser.on('ping', () => {
|
eventparser.on('ping', () => {
|
||||||
logger.debug('handling event \'ping\', responding with \'pong\'...');
|
logger.debug('handling event \'ping\', responding with \'pong\'...');
|
||||||
new Message('pong').send();
|
new Message('pong').send();
|
||||||
});
|
});
|
||||||
this.eventParser.on('pong', () => {
|
eventparser.on('pong', () => {
|
||||||
logger.debug('handling event \'pong\'...');
|
logger.debug('handling event \'pong\'...');
|
||||||
this.alive = true;
|
this.alive = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.timeout !== undefined) {
|
this.destroyed = true;
|
||||||
clearTimeout(this.timeout);
|
eventparser.removeAllListeners('ping');
|
||||||
}
|
eventparser.removeAllListeners('pong');
|
||||||
this.eventParser.removeAllListeners('ping');
|
|
||||||
this.eventParser.removeAllListeners('pong');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Message {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = this.toString();
|
const data = this.toString();
|
||||||
logger.debug('sending data to \'' + socket.remoteAddress + ':' + socket.remotePort + '\': ' + data);
|
// logger.debug('sending data to \'' + socket.remoteAddress + ':' + socket.remotePort + '\': ' + data);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
socket.write(data + constants.EVENT_DELIMITER, resolve);
|
socket.write(data + constants.EVENT_DELIMITER, resolve);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
const packageJSON = require('./package.json');
|
const packageJSON = require('./package.json');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const Connection = require('./classes/Connection.js');
|
|
||||||
const Logger = require('./classes/Logger.js');
|
const Logger = require('./classes/Logger.js');
|
||||||
|
const EventParser = require('./classes/EventParser.js');
|
||||||
const Player = require('./classes/Player.js');
|
const Player = require('./classes/Player.js');
|
||||||
|
const Connection = require('./classes/Connection.js');
|
||||||
|
|
||||||
const INTERRUPTS = ['beforeExit', 'SIGINT', 'SIGTERM'];
|
const INTERRUPTS = ['beforeExit', 'SIGINT', 'SIGTERM'];
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ async function main() {
|
||||||
handleExit();
|
handleExit();
|
||||||
global.constants = require('./libs/constants.js');
|
global.constants = require('./libs/constants.js');
|
||||||
global.logger.info("launching " + packageJSON.name + " " + packageJSON.version + "...");
|
global.logger.info("launching " + packageJSON.name + " " + packageJSON.version + "...");
|
||||||
|
global.eventparser = new EventParser();
|
||||||
global.player = new Player();
|
global.player = new Player();
|
||||||
global.connection = new Connection();
|
global.connection = new Connection();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
Loading…
Reference in a new issue