From 54117ba2515337e365b429efd35917d4c6f9189c Mon Sep 17 00:00:00 2001 From: Quan HL Date: Thu, 9 Mar 2023 21:42:10 +0700 Subject: [PATCH 1/2] feat: add account_sid to tts hash key and confiurable TTL for cached file --- lib/purge-tts-cache.js | 10 ++++++++-- lib/synth-audio.js | 5 +++-- lib/utils.js | 4 ++-- test/synth.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lib/purge-tts-cache.js b/lib/purge-tts-cache.js index ce17794..f0ab7a1 100644 --- a/lib/purge-tts-cache.js +++ b/lib/purge-tts-cache.js @@ -11,7 +11,8 @@ const debug = require('debug')('jambonz:realtimedb-helpers'); * @param {string} opts.text - text or ssml to synthesize * @returns {object} result - {error, purgedCount} */ -async function purgeTtsCache(client, logger, {all, vendor, language, voice, deploymentId, engine, text} = {all: true}) { +async function purgeTtsCache(client, logger, {all, account_sid, vendor, + language, voice, deploymentId, engine, text} = {all: true}) { logger = logger || noopLogger; let purgedCount = 0, error; @@ -21,8 +22,13 @@ async function purgeTtsCache(client, logger, {all, vendor, language, voice, depl const keys = await client.keysAsync('tts:*'); purgedCount = await client.delAsync(keys); - } else { + } else if (account_sid && !vendor && !language && !voice && !engine && !text) { + const keys = await client.keysAsync(`tts:${account_sid}:*`); + purgedCount = await client.delAsync(keys); + } + else { const key = makeSynthKey({ + account_sid, vendor, language: language || '', voice: voice || deploymentId, diff --git a/lib/synth-audio.js b/lib/synth-audio.js index b5a0c5e..26c7774 100644 --- a/lib/synth-audio.js +++ b/lib/synth-audio.js @@ -32,7 +32,7 @@ const { const {SynthesizeSpeechRequest} = require('../stubs/riva/proto/riva_tts_pb'); const {AudioEncoding} = require('../stubs/riva/proto/riva_audio_pb'); const debug = require('debug')('jambonz:realtimedb-helpers'); -const EXPIRES = 3600 * 24; // cache tts for 24 hours +const EXPIRES = process.env.JAMBONES_TTS_CACHE_DURATION_MINS || 3600 * 24; // cache tts for 24 hours const TMP_FOLDER = '/tmp'; /** @@ -95,8 +95,9 @@ async function synthAudio(client, logger, stats, { } else if (vendor.startsWith('custom')) { assert.ok(credentials.custom_tts_url, `synthAudio requires custom_tts_url in credentials when ${vendor} is used`); } - + const account_sid = credentials.account_sid; const key = makeSynthKey({ + account_sid, vendor, language: language || '', voice: voice || deploymentId, diff --git a/lib/utils.js b/lib/utils.js index f8debdc..7fced9f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -16,10 +16,10 @@ const debug = require('debug')('jambonz:realtimedb-helpers'); */ //const nuanceClientMap = new Map(); -function makeSynthKey({vendor, language, voice, engine = '', text}) { +function makeSynthKey({account_sid = '', vendor, language, voice, engine = '', text}) { const hash = crypto.createHash('sha1'); hash.update(`${language}:${vendor}:${voice}:${engine}:${text}`); - return `tts:${hash.digest('hex')}`; + return `tts${account_sid ? (':' + account_sid) : ''}:${hash.digest('hex')}`; } const noopLogger = { diff --git a/test/synth.js b/test/synth.js index 23ce039..8058171 100644 --- a/test/synth.js +++ b/test/synth.js @@ -427,5 +427,35 @@ test('TTS Cache tests', async(t) => { t.end(err); } + try { + // clear cache + await purgeTtsCache(); + // save some random tts keys to cache + const minRecords = 8; + const account_sid = "12412512_cabc_5aff" + const account_sid2 = "22412512_cabc_5aff" + for (const i in Array(minRecords).fill(0)) { + await client.setAsync(makeSynthKey({account_sid, vendor: i, language: i, voice: i, engine: i, text: i}), i); + } + for (const i in Array(minRecords).fill(0)) { + await client.setAsync(makeSynthKey({account_sid: account_sid2, vendor: i, language: i, voice: i, engine: i, text: i}), i); + } + const {purgedCount} = await purgeTtsCache({account_sid}); + t.equal(purgedCount, minRecords, `successfully purged at least ${minRecords} tts records from cache for account_sid:${account_sid}`); + + let cached = (await client.keysAsync('tts:*')).length; + t.equal(cached, minRecords, `successfully purged all tts records from cache for account_sid:${account_sid}`); + + const {purgedCount: purgedCount2} = await purgeTtsCache({account_sid: account_sid2}); + t.equal(purgedCount2, minRecords, `successfully purged at least ${minRecords} tts records from cache for account_sid:${account_sid2}`); + + cached = (await client.keysAsync('tts:*')).length; + t.equal(cached, 0, `successfully purged all tts records from cache`); + + } catch (err) { + console.error(JSON.stringify(err)); + t.end(err); + } + client.quit(); }); From f7417acf58bc49d1dac2251d34ab0fe38613ddaa Mon Sep 17 00:00:00 2001 From: Quan HL Date: Thu, 9 Mar 2023 22:11:48 +0700 Subject: [PATCH 2/2] fix: review comments --- lib/synth-audio.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/synth-audio.js b/lib/synth-audio.js index 26c7774..7737874 100644 --- a/lib/synth-audio.js +++ b/lib/synth-audio.js @@ -52,7 +52,7 @@ const TMP_FOLDER = '/tmp'; * @returns object containing filepath to an mp3 file in the /tmp folder containing * the synthesized audio, and a variable indicating whether it was served from cache */ -async function synthAudio(client, logger, stats, { +async function synthAudio(client, logger, stats, { account_sid, vendor, language, voice, gender, text, engine, salt, model, credentials, deploymentId, disableTtsCache }) { let audioBuffer; @@ -95,7 +95,6 @@ async function synthAudio(client, logger, stats, { } else if (vendor.startsWith('custom')) { assert.ok(credentials.custom_tts_url, `synthAudio requires custom_tts_url in credentials when ${vendor} is used`); } - const account_sid = credentials.account_sid; const key = makeSynthKey({ account_sid, vendor,