diff --git a/lib/middleware.js b/lib/middleware.js index 2ce46986..51b85122 100644 --- a/lib/middleware.js +++ b/lib/middleware.js @@ -192,8 +192,8 @@ module.exports = function(srf, logger) { if (0 === app.tasks.length) throw new Error('no application provided'); next(); } catch (err) { - logger.info({err}, `Error retrieving or parsing application: ${err.message}`); - res.send(480, {headers: {'X-Reason': err.message}}); + logger.info({err}, `Error retrieving or parsing application: ${err?.message}`); + res.send(480, {headers: {'X-Reason': err?.message || 'unknown'}}); } } diff --git a/lib/session/call-session.js b/lib/session/call-session.js index c62d32cb..584b1aac 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -8,6 +8,7 @@ const makeTask = require('../tasks/make_task'); const normalizeJambones = require('../utils/normalize-jambones'); const listTaskNames = require('../utils/summarize-tasks'); const HttpRequestor = require('../utils/http-requestor'); +const WsRequestor = require('../utils/ws-requestor'); const BADPRECONDITIONS = 'preconditions not met'; const CALLER_CANCELLED_ERR_MSG = 'Response not sent due to unknown transaction'; @@ -291,6 +292,7 @@ class CallSession extends Emitter { */ async exec() { this.logger.info({tasks: listTaskNames(this.tasks)}, `CallSession:exec starting ${this.tasks.length} tasks`); + while (this.tasks.length && !this.callGone) { const taskNum = ++this.taskIdx; const stackNum = this.stackIdx; @@ -304,13 +306,22 @@ class CallSession extends Emitter { this.logger.info(`CallSession:exec completed task #${stackNum}:${taskNum}: ${task.name}`); } catch (err) { this.currentTask = null; - if (err.message.includes(BADPRECONDITIONS)) { + if (err.message?.includes(BADPRECONDITIONS)) { this.logger.info(`CallSession:exec task #${stackNum}:${taskNum}: ${task.name}: ${err.message}`); } else { this.logger.error(err, `Error executing task #${stackNum}:${taskNum}: ${task.name}`); break; } + + if (0 === this.tasks.length && this.hasStableDialog && this.requestor instanceof WsRequestor) { + try { + await this._awaitCommandsOrHangup(); + } catch (err) { + this.logger.info(err, 'CallSession:exec - error waiting for new commands'); + break; + } + } } } @@ -370,6 +381,10 @@ class CallSession extends Emitter { this.currentTask.kill(this); this.currentTask = null; } + if (this.wakeupResolver) { + this.wakeupResolver(); + this.wakeupResolver = null; + } } /** @@ -620,7 +635,7 @@ class CallSession extends Emitter { } _onCommand({msgid, command, queueCommand, data}) { - this.logger.info({msgid, command, data}, 'CallSession:_onCommand - received command'); + this.logger.info({msgid, command, queueCommand, data}, 'CallSession:_onCommand - received command'); switch (command) { case 'redirect': if (Array.isArray(data)) { @@ -665,6 +680,10 @@ class CallSession extends Emitter { default: this.logger.info(`CallSession:_onCommand - invalid command ${command}`); } + if (this.wakeupResolver) { + this.wakeupResolver(); + this.wakeupResolver = null; + } } _evaluatePreconditions(task) { @@ -1008,6 +1027,10 @@ class CallSession extends Emitter { this.emit('callStatusChange', {callStatus: CallStatus.Completed, duration}); this.logger.debug('CallSession: call terminated by jambones'); origDestroy(); + if (this.wakeupResolver) { + this.wakeupResolver(); + this.wakeupResolver = null; + } } }; } @@ -1076,6 +1099,13 @@ class CallSession extends Emitter { this.updateCallStatus(Object.assign({}, this.callInfo.toJSON()), this.serviceUrl) .catch((err) => this.logger.error(err, 'redis error')); } + + _awaitCommandsOrHangup() { + assert(!this.wakeupResolver); + return new Promise((resolve, reject) => { + this.wakeupResolver = resolve; + }); + } } module.exports = CallSession;