fix for #826 race condition in say (#827)

* fix for #826 race condition in say

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip
This commit is contained in:
Dave Horton
2024-07-24 12:56:03 -04:00
committed by GitHub
parent ee24041cba
commit edd8f20642
3 changed files with 98 additions and 78 deletions

View File

@@ -151,7 +151,7 @@ class TaskSay extends TtsTask {
preCache preCache
}); });
if (!filePath.startsWith('say:')) { if (!filePath.startsWith('say:')) {
this.logger.debug(`file ${filePath}, served from cache ${servedFromCache}`); this.logger.debug(`Say: file ${filePath}, served from cache ${servedFromCache}`);
if (filePath) cs.trackTmpFile(filePath); if (filePath) cs.trackTmpFile(filePath);
if (this.otelSpan) { if (this.otelSpan) {
this.otelSpan.setAttributes({'tts.cached': servedFromCache}); this.otelSpan.setAttributes({'tts.cached': servedFromCache});
@@ -173,7 +173,7 @@ class TaskSay extends TtsTask {
} }
} }
else { else {
this.logger.debug('a streaming tts api will be used'); this.logger.debug('Say: a streaming tts api will be used');
const modifiedPath = filePath.replace('say:{', `say:{session-uuid=${ep.uuid},`); const modifiedPath = filePath.replace('say:{', `say:{session-uuid=${ep.uuid},`);
return modifiedPath; return modifiedPath;
} }
@@ -280,40 +280,52 @@ class TaskSay extends TtsTask {
await this.playToConfMember(ep, memberId, confName, confUuid, filepath[segment]); await this.playToConfMember(ep, memberId, confName, confUuid, filepath[segment]);
} }
else { else {
let tts_cache_filename;
if (filepath[segment].startsWith('say:{')) { if (filepath[segment].startsWith('say:{')) {
const arr = /^say:\{.*\}\s*(.*)$/.exec(filepath[segment]); const arr = /^say:\{.*\}\s*(.*)$/.exec(filepath[segment]);
if (arr) this.logger.debug(`Say:exec sending streaming tts request: ${arr[1].substring(0, 64)}..`); if (arr) this.logger.debug(`Say:exec sending streaming tts request: ${arr[1].substring(0, 64)}..`);
} }
else this.logger.debug(`Say:exec sending ${filepath[segment].substring(0, 64)}`); else this.logger.debug(`Say:exec sending ${filepath[segment].substring(0, 64)}`);
ep.once('playback-start', (evt) => { ep.once('playback-start', (evt) => {
this.logger.debug({evt}, 'got playback-start'); this.logger.debug({evt}, 'Say got playback-start');
if (this.otelSpan) { if (this.otelSpan) {
this._addStreamingTtsAttributes(this.otelSpan, evt); this._addStreamingTtsAttributes(this.otelSpan, evt);
this.otelSpan.end(); this.otelSpan.end();
this.otelSpan = null; this.otelSpan = null;
if (evt.variable_tts_cache_filename) cs.trackTmpFile(evt.variable_tts_cache_filename); if (evt.variable_tts_cache_filename) {
tts_cache_filename = evt.variable_tts_cache_filename;
cs.trackTmpFile(evt.variable_tts_cache_filename);
}
else {
this.logger.info('No tts_cache_filename in playback-start event');
}
} }
}); });
ep.once('playback-stop', (evt) => { ep.once('playback-stop', (evt) => {
this.logger.debug({evt}, 'got playback-stop'); if (!tts_cache_filename || evt.variable_tts_cache_filename !== tts_cache_filename) {
if (evt.variable_tts_error) { this.logger.info({evt}, 'Say: discarding playback-stop from other say verb');
writeAlerts({
account_sid,
alert_type: AlertType.TTS_FAILURE,
vendor,
detail: evt.variable_tts_error
}).catch((err) => this.logger.info({err}, 'Error generating alert for no tts'));
} }
if (evt.variable_tts_cache_filename) { else {
const text = parseTextFromSayString(this.text[segment]); this.logger.debug({evt}, 'Say got playback-stop');
addFileToCache(evt.variable_tts_cache_filename, { if (evt.variable_tts_error) {
account_sid, writeAlerts({
vendor, account_sid,
language, alert_type: AlertType.TTS_FAILURE,
voice, vendor,
engine, detail: evt.variable_tts_error
text }).catch((err) => this.logger.info({err}, 'Error generating alert for no tts'));
}).catch((err) => this.logger.info({err}, 'Error adding file to cache')); }
if (evt.variable_tts_cache_filename && !this.killed) {
const text = parseTextFromSayString(this.text[segment]);
addFileToCache(evt.variable_tts_cache_filename, {
account_sid,
vendor,
language,
voice,
engine,
text
}).catch((err) => this.logger.info({err}, 'Error adding file to cache'));
}
} }
if (this._playResolve) { if (this._playResolve) {
evt.variable_tts_error ? this._playReject(new Error(evt.variable_tts_error)) : this._playResolve(); evt.variable_tts_error ? this._playReject(new Error(evt.variable_tts_error)) : this._playResolve();
@@ -324,7 +336,8 @@ class TaskSay extends TtsTask {
this._playResolve = resolve; this._playResolve = resolve;
this._playReject = reject; this._playReject = reject;
}); });
await ep.play(filepath[segment]); const r = await ep.play(filepath[segment]);
this.logger.debug({r}, 'Say:exec play result');
try { try {
// wait for playback-stop event received to confirm if the playback is successful // wait for playback-stop event received to confirm if the playback is successful
await this._playPromise; await this._playPromise;
@@ -369,7 +382,10 @@ class TaskSay extends TtsTask {
this.ep.removeAllListeners('playback-start'); this.ep.removeAllListeners('playback-start');
this.ep.removeAllListeners('playback-stop'); this.ep.removeAllListeners('playback-stop');
// if we are waiting for playback-stop event, resolve the promise // if we are waiting for playback-stop event, resolve the promise
if (this._playResolve) this._playResolve(); if (this._playResolve) {
this._playResolve();
this._playResolve = null;
}
} }
} }

110
package-lock.json generated
View File

@@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@aws-sdk/client-auto-scaling": "^3.549.0", "@aws-sdk/client-auto-scaling": "^3.549.0",
"@aws-sdk/client-sns": "^3.549.0", "@aws-sdk/client-sns": "^3.549.0",
"@jambonz/db-helpers": "^0.9.3", "@jambonz/db-helpers": "^0.9.6",
"@jambonz/http-health-check": "^0.0.1", "@jambonz/http-health-check": "^0.0.1",
"@jambonz/mw-registrar": "^0.2.7", "@jambonz/mw-registrar": "^0.2.7",
"@jambonz/realtimedb-helpers": "^0.8.8", "@jambonz/realtimedb-helpers": "^0.8.8",
@@ -2217,11 +2217,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/@grpc/proto-loader/node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.5.0", "version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
@@ -2282,13 +2277,13 @@
} }
}, },
"node_modules/@jambonz/db-helpers": { "node_modules/@jambonz/db-helpers": {
"version": "0.9.3", "version": "0.9.6",
"resolved": "https://registry.npmjs.org/@jambonz/db-helpers/-/db-helpers-0.9.3.tgz", "resolved": "https://registry.npmjs.org/@jambonz/db-helpers/-/db-helpers-0.9.6.tgz",
"integrity": "sha512-3XFs7NC7J7Q/eb1CwG1YJHa6N4elh8IP/4hMMDgoM9U5Loplx61XI4nZ58FIrY3C/F6gEF4UdjqKvbusEVw7cQ==", "integrity": "sha512-uvtkqdP6GP6KSaM7eo2jcU1k0R6Ymodhl0RH/XiNESgIhZ7sx7ZnMQtrZQVVmzrJ429H7q8dQqgcB2YhAyEK+A==",
"dependencies": { "dependencies": {
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"mysql2": "^2.3.3", "mysql2": "^3.10.3",
"node-object-hash": "^2.3.10", "node-object-hash": "^2.3.10",
"uuid": "^8.3.2" "uuid": "^8.3.2"
} }
@@ -3799,6 +3794,14 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/aws-ssl-profiles": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz",
"integrity": "sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==",
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/axios": { "node_modules/axios": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
@@ -7198,9 +7201,9 @@
"dev": true "dev": true
}, },
"node_modules/long": { "node_modules/long": {
"version": "4.0.0", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
}, },
"node_modules/lower-case": { "node_modules/lower-case": {
"version": "2.0.2", "version": "2.0.2",
@@ -7472,16 +7475,17 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/mysql2": { "node_modules/mysql2": {
"version": "2.3.3", "version": "3.10.3",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.10.3.tgz",
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", "integrity": "sha512-k43gmH9i79rZD4hGPdj7pDuT0UBiFjs4UzXEy1cJrV0QqcSABomoLwvejqdbcXN+Vd7gi999CVM6o9vCPKq29g==",
"dependencies": { "dependencies": {
"denque": "^2.0.1", "aws-ssl-profiles": "^1.1.1",
"denque": "^2.1.0",
"generate-function": "^2.3.1", "generate-function": "^2.3.1",
"iconv-lite": "^0.6.3", "iconv-lite": "^0.6.3",
"long": "^4.0.0", "long": "^5.2.1",
"lru-cache": "^6.0.0", "lru-cache": "^8.0.0",
"named-placeholders": "^1.1.2", "named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5", "seq-queue": "^0.0.5",
"sqlstring": "^2.3.2" "sqlstring": "^2.3.2"
}, },
@@ -7500,6 +7504,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/mysql2/node_modules/lru-cache": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
"engines": {
"node": ">=16.14"
}
},
"node_modules/named-placeholders": { "node_modules/named-placeholders": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
@@ -8270,11 +8282,6 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/protobufjs/node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"node_modules/protocols": { "node_modules/protocols": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz",
@@ -11860,13 +11867,6 @@
"long": "^5.0.0", "long": "^5.0.0",
"protobufjs": "^7.2.4", "protobufjs": "^7.2.4",
"yargs": "^17.7.2" "yargs": "^17.7.2"
},
"dependencies": {
"long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
}
} }
}, },
"@humanwhocodes/config-array": { "@humanwhocodes/config-array": {
@@ -11919,13 +11919,13 @@
"dev": true "dev": true
}, },
"@jambonz/db-helpers": { "@jambonz/db-helpers": {
"version": "0.9.3", "version": "0.9.6",
"resolved": "https://registry.npmjs.org/@jambonz/db-helpers/-/db-helpers-0.9.3.tgz", "resolved": "https://registry.npmjs.org/@jambonz/db-helpers/-/db-helpers-0.9.6.tgz",
"integrity": "sha512-3XFs7NC7J7Q/eb1CwG1YJHa6N4elh8IP/4hMMDgoM9U5Loplx61XI4nZ58FIrY3C/F6gEF4UdjqKvbusEVw7cQ==", "integrity": "sha512-uvtkqdP6GP6KSaM7eo2jcU1k0R6Ymodhl0RH/XiNESgIhZ7sx7ZnMQtrZQVVmzrJ429H7q8dQqgcB2YhAyEK+A==",
"requires": { "requires": {
"cidr-matcher": "^2.1.1", "cidr-matcher": "^2.1.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"mysql2": "^2.3.3", "mysql2": "^3.10.3",
"node-object-hash": "^2.3.10", "node-object-hash": "^2.3.10",
"uuid": "^8.3.2" "uuid": "^8.3.2"
} }
@@ -13125,6 +13125,11 @@
"possible-typed-array-names": "^1.0.0" "possible-typed-array-names": "^1.0.0"
} }
}, },
"aws-ssl-profiles": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz",
"integrity": "sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ=="
},
"axios": { "axios": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
@@ -15683,9 +15688,9 @@
"dev": true "dev": true
}, },
"long": { "long": {
"version": "4.0.0", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
}, },
"lower-case": { "lower-case": {
"version": "2.0.2", "version": "2.0.2",
@@ -15881,16 +15886,17 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"mysql2": { "mysql2": {
"version": "2.3.3", "version": "3.10.3",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.10.3.tgz",
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", "integrity": "sha512-k43gmH9i79rZD4hGPdj7pDuT0UBiFjs4UzXEy1cJrV0QqcSABomoLwvejqdbcXN+Vd7gi999CVM6o9vCPKq29g==",
"requires": { "requires": {
"denque": "^2.0.1", "aws-ssl-profiles": "^1.1.1",
"denque": "^2.1.0",
"generate-function": "^2.3.1", "generate-function": "^2.3.1",
"iconv-lite": "^0.6.3", "iconv-lite": "^0.6.3",
"long": "^4.0.0", "long": "^5.2.1",
"lru-cache": "^6.0.0", "lru-cache": "^8.0.0",
"named-placeholders": "^1.1.2", "named-placeholders": "^1.1.3",
"seq-queue": "^0.0.5", "seq-queue": "^0.0.5",
"sqlstring": "^2.3.2" "sqlstring": "^2.3.2"
}, },
@@ -15902,6 +15908,11 @@
"requires": { "requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0" "safer-buffer": ">= 2.1.2 < 3.0.0"
} }
},
"lru-cache": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA=="
} }
} }
}, },
@@ -16502,13 +16513,6 @@
"@protobufjs/utf8": "^1.1.0", "@protobufjs/utf8": "^1.1.0",
"@types/node": ">=13.7.0", "@types/node": ">=13.7.0",
"long": "^5.0.0" "long": "^5.0.0"
},
"dependencies": {
"long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
}
} }
}, },
"protocols": { "protocols": {

View File

@@ -27,7 +27,7 @@
"dependencies": { "dependencies": {
"@aws-sdk/client-auto-scaling": "^3.549.0", "@aws-sdk/client-auto-scaling": "^3.549.0",
"@aws-sdk/client-sns": "^3.549.0", "@aws-sdk/client-sns": "^3.549.0",
"@jambonz/db-helpers": "^0.9.3", "@jambonz/db-helpers": "^0.9.6",
"@jambonz/http-health-check": "^0.0.1", "@jambonz/http-health-check": "^0.0.1",
"@jambonz/mw-registrar": "^0.2.7", "@jambonz/mw-registrar": "^0.2.7",
"@jambonz/realtimedb-helpers": "^0.8.8", "@jambonz/realtimedb-helpers": "^0.8.8",