add support for autoscaling SBC SIP servers; bugfix: synthAudio calls must past stats obj

This commit is contained in:
Dave Horton
2021-10-02 12:40:56 -04:00
parent a779ead79f
commit a9e789f466
7 changed files with 39 additions and 23 deletions

View File

@@ -210,6 +210,7 @@ class Dialogflow extends Task {
/* if we are using tts and a message was provided, play it out */ /* if we are using tts and a message was provided, play it out */
if (this.vendor && intent.fulfillmentText && intent.fulfillmentText.length > 0) { if (this.vendor && intent.fulfillmentText && intent.fulfillmentText.length > 0) {
const {srf} = cs; const {srf} = cs;
const {stats} = srf.locals;
const {synthAudio} = srf.locals.dbHelpers; const {synthAudio} = srf.locals.dbHelpers;
this.waitingForPlayStart = false; this.waitingForPlayStart = false;
@@ -229,7 +230,7 @@ class Dialogflow extends Task {
credentials: this.ttsCredentials credentials: this.ttsCredentials
}; };
this.logger.debug({obj}, 'Dialogflow:_onIntent - playing message via tts'); this.logger.debug({obj}, 'Dialogflow:_onIntent - playing message via tts');
const {filePath, servedFromCache} = await synthAudio(obj); const {filePath, servedFromCache} = await synthAudio(stats, obj);
if (filePath) cs.trackTmpFile(filePath); if (filePath) cs.trackTmpFile(filePath);
if (!this.ttsCredentials && !servedFromCache) cs.billForTts(intent.fulfillmentText.length); if (!this.ttsCredentials && !servedFromCache) cs.billForTts(intent.fulfillmentText.length);

View File

@@ -182,12 +182,13 @@ class Lex extends Task {
const type = messages[0].type; const type = messages[0].type;
if (['PlainText', 'SSML'].includes(type) && msg) { if (['PlainText', 'SSML'].includes(type) && msg) {
const {srf} = cs; const {srf} = cs;
const {stats} = srf.locals;
const {synthAudio} = srf.locals.dbHelpers; const {synthAudio} = srf.locals.dbHelpers;
try { try {
this.logger.debug(`tts with ${this.vendor} ${this.voice}`); this.logger.debug(`tts with ${this.vendor} ${this.voice}`);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const {filePath, servedFromCache} = await synthAudio({ const {filePath, servedFromCache} = await synthAudio(stats, {
text: msg, text: msg,
vendor: this.vendor, vendor: this.vendor,
language: this.language, language: this.language,

View File

@@ -19,7 +19,7 @@ class TaskSay extends Task {
const {srf} = cs; const {srf} = cs;
const {updateSpeechCredentialLastUsed} = require('../utils/db-utils')(this.logger, srf); const {updateSpeechCredentialLastUsed} = require('../utils/db-utils')(this.logger, srf);
const {writeAlerts, AlertType} = srf.locals; const {writeAlerts, AlertType, stats} = srf.locals;
const {synthAudio} = srf.locals.dbHelpers; const {synthAudio} = srf.locals.dbHelpers;
const vendor = this.synthesizer.vendor || cs.speechSynthesisVendor; const vendor = this.synthesizer.vendor || cs.speechSynthesisVendor;
const language = this.synthesizer.language || cs.speechSynthesisLanguage; const language = this.synthesizer.language || cs.speechSynthesisLanguage;
@@ -27,6 +27,7 @@ class TaskSay extends Task {
const salt = cs.callSid; const salt = cs.callSid;
const credentials = cs.getSpeechCredentials(vendor, 'tts'); const credentials = cs.getSpeechCredentials(vendor, 'tts');
this.logger.info({vendor, credentials}, 'Task:say - using vendor');
this.ep = ep; this.ep = ep;
try { try {
if (!credentials) { if (!credentials) {
@@ -40,7 +41,7 @@ class TaskSay extends Task {
// synthesize all of the text elements // synthesize all of the text elements
let lastUpdated = false; let lastUpdated = false;
const filepath = (await Promise.all(this.text.map(async(text) => { const filepath = (await Promise.all(this.text.map(async(text) => {
const {filePath, servedFromCache} = await synthAudio({ const {filePath, servedFromCache} = await synthAudio(stats, {
text, text,
vendor, vendor,
language, language,

View File

@@ -135,6 +135,7 @@ function installSrfLocals(srf, logger) {
retrieveSet, retrieveSet,
addToSet, addToSet,
removeFromSet, removeFromSet,
monitorSet,
pushBack, pushBack,
popFront, popFront,
removeFromList, removeFromList,
@@ -178,6 +179,7 @@ function installSrfLocals(srf, logger) {
retrieveSet, retrieveSet,
addToSet, addToSet,
removeFromSet, removeFromSet,
monitorSet,
pushBack, pushBack,
popFront, popFront,
removeFromList, removeFromList,

View File

@@ -7,13 +7,15 @@ const debug = require('debug')('jambonz:feature-server');
module.exports = (logger) => { module.exports = (logger) => {
logger = logger || noopLogger; logger = logger || noopLogger;
let idxSbc = 0; let idxSbc = 0;
let sbcs = [];
assert.ok(process.env.JAMBONES_SBCS, 'missing JAMBONES_SBCS env var'); if (process.env.JAMBONES_SBCS) {
const sbcs = process.env.JAMBONES_SBCS sbcs = process.env.JAMBONES_SBCS
.split(',') .split(',')
.map((sbc) => sbc.trim()); .map((sbc) => sbc.trim());
assert.ok(sbcs.length, 'JAMBONES_SBCS env var is empty or misconfigured'); assert.ok(sbcs.length, 'JAMBONES_SBCS env var is empty or misconfigured');
logger.info({sbcs}, 'SBC inventory'); logger.info({sbcs}, 'SBC inventory');
}
// listen for SNS lifecycle changes // listen for SNS lifecycle changes
let lifecycleEmitter = new Emitter(); let lifecycleEmitter = new Emitter();
@@ -96,8 +98,19 @@ module.exports = (logger) => {
}, 20000); }, 20000);
// initial ping once we are up // initial ping once we are up
setTimeout(() => { setTimeout(async() => {
const {srf} = require('../..'); const {srf} = require('../..');
// if SBCs are auto-scaling, monitor them as they come and go
if (!process.env.JAMBONES_SBCS) {
const {monitorSet} = srf.locals.dbHelpers;
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-sip`;
await monitorSet(setName, 10, (members) => {
sbcs = members;
logger.info(`sbc-pinger: SBC roster has changed, list of active SBCs is now ${sbcs}`);
});
}
pingProxies(srf); pingProxies(srf);
}, 1000); }, 1000);

20
package-lock.json generated
View File

@@ -1,16 +1,16 @@
{ {
"name": "jambonz-feature-server", "name": "jambonz-feature-server",
"version": "0.3.1", "version": "0.6.6",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"version": "0.3.1", "version": "0.6.6",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jambonz/db-helpers": "^0.6.13", "@jambonz/db-helpers": "^0.6.13",
"@jambonz/mw-registrar": "^0.2.1", "@jambonz/mw-registrar": "^0.2.1",
"@jambonz/realtimedb-helpers": "^0.4.1", "@jambonz/realtimedb-helpers": "^0.4.7",
"@jambonz/stats-collector": "^0.1.5", "@jambonz/stats-collector": "^0.1.5",
"@jambonz/time-series": "^0.1.5", "@jambonz/time-series": "^0.1.5",
"aws-sdk": "^2.846.0", "aws-sdk": "^2.846.0",
@@ -405,13 +405,12 @@
} }
}, },
"node_modules/@jambonz/realtimedb-helpers": { "node_modules/@jambonz/realtimedb-helpers": {
"version": "0.4.1", "version": "0.4.7",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.7.tgz",
"integrity": "sha512-GDZ+VkVkSatAh6rYxapzi3r0k/Lj45mh1LAV6aB8U1kTcm3cD9u8QDBB04JL+seBg9mZmEB5aEiCdE9icOnJew==", "integrity": "sha512-pJ8nhR0t0K5Z9jBxOvQY8/9o3XG497hkeYdgrRm/83igfqOnp2hMrslcSevJPNaZFzlEZZCNpC7g2LcZtXOxhQ==",
"dependencies": { "dependencies": {
"@google-cloud/text-to-speech": "^3.1.3", "@google-cloud/text-to-speech": "^3.1.3",
"@jambonz/promisify-redis": "0.0.6", "@jambonz/promisify-redis": "0.0.6",
"@jambonz/stats-collector": "^0.1.5",
"aws-sdk": "^2.840.0", "aws-sdk": "^2.840.0",
"debug": "^4.3.1", "debug": "^4.3.1",
"redis": "^3.0.0" "redis": "^3.0.0"
@@ -5075,13 +5074,12 @@
} }
}, },
"@jambonz/realtimedb-helpers": { "@jambonz/realtimedb-helpers": {
"version": "0.4.1", "version": "0.4.7",
"resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@jambonz/realtimedb-helpers/-/realtimedb-helpers-0.4.7.tgz",
"integrity": "sha512-GDZ+VkVkSatAh6rYxapzi3r0k/Lj45mh1LAV6aB8U1kTcm3cD9u8QDBB04JL+seBg9mZmEB5aEiCdE9icOnJew==", "integrity": "sha512-pJ8nhR0t0K5Z9jBxOvQY8/9o3XG497hkeYdgrRm/83igfqOnp2hMrslcSevJPNaZFzlEZZCNpC7g2LcZtXOxhQ==",
"requires": { "requires": {
"@google-cloud/text-to-speech": "^3.1.3", "@google-cloud/text-to-speech": "^3.1.3",
"@jambonz/promisify-redis": "0.0.6", "@jambonz/promisify-redis": "0.0.6",
"@jambonz/stats-collector": "^0.1.5",
"aws-sdk": "^2.840.0", "aws-sdk": "^2.840.0",
"debug": "^4.3.1", "debug": "^4.3.1",
"redis": "^3.0.0" "redis": "^3.0.0"

View File

@@ -28,7 +28,7 @@
"dependencies": { "dependencies": {
"@jambonz/db-helpers": "^0.6.13", "@jambonz/db-helpers": "^0.6.13",
"@jambonz/mw-registrar": "^0.2.1", "@jambonz/mw-registrar": "^0.2.1",
"@jambonz/realtimedb-helpers": "^0.4.1", "@jambonz/realtimedb-helpers": "^0.4.7",
"@jambonz/stats-collector": "^0.1.5", "@jambonz/stats-collector": "^0.1.5",
"@jambonz/time-series": "^0.1.5", "@jambonz/time-series": "^0.1.5",
"aws-sdk": "^2.846.0", "aws-sdk": "^2.846.0",