UNPKG

asksuite-core

Version:
302 lines (259 loc) 9.16 kB
const promisesTranslateTree = {}; const thenPromisesTranslateTree = {}; const _ = require('lodash'); const PromiseBlue = require('bluebird'); const { AsksuiteTreeManagerGeneralUtils } = require('./asksuite.tree.manager.general.utils'); class AsksuiteTreeManagerGeneral { constructor({ configuration, CompanyMap, TreeMap, IntentsMap, AsksuiteUtil, AsksuiteService, InitMap, treesTestingCache, getLanguages, translator, treeCompiler, wait, LastAccessCompanyMap, }) { this.configuration = configuration; this.CompanyMap = CompanyMap; this.TreeMap = TreeMap; this.getLanguages = getLanguages; this.IntentsMap = IntentsMap; this.AsksuiteUtil = AsksuiteUtil; this.translator = translator; this.AsksuiteService = AsksuiteService; this.treesTestingCache = treesTestingCache; this.InitMap = InitMap; this.wait = wait; this.treeCompiler = treeCompiler; this.LastAccessCompanyMap = LastAccessCompanyMap; } getLanguagesByCompany(chatTreeId) { const company = this.CompanyMap.get(chatTreeId) || this.CompanyMap.get(chatTreeId.split('.')[1]); return AsksuiteTreeManagerGeneralUtils.getLanguagesByCompany(company); } resolveDefaultLanguage(languages, language) { return AsksuiteTreeManagerGeneralUtils.resolveDefaultLanguage(languages, language); } resolveLanguage(paramLanguage, companyId) { let languages = this.getLanguages(); companyId = companyId || ''; const company = this.CompanyMap.get(companyId) || this.CompanyMap.get(companyId.split('.')[1]); if (company && !_.isEmpty(company.languages)) { languages = _.filter(languages, (l) => _.includes(company.languages, l.formatIso)); } return this.AsksuiteUtil.resolveLanguage(paramLanguage, languages); } flushTreeMapKeys(keys) { const languages = this.getLanguages(); if (keys && Array.isArray(keys)) { languages.forEach(({ formatIso }) => { keys.forEach((key) => { const treeInstance = this.resolveTreeInstance(formatIso); if (treeInstance.has(key)) { treeInstance.delete(key); } }); }); } } resolveTreeInstance(language, companyId) { this.renewLastAccessCompany(companyId); language = this.resolveLanguage(language, companyId); if (!this.TreeMap.has(language)) { this.TreeMap.set(language, new Map()); } return this.TreeMap.get(language); } isTreeAlreadyRegistred(chatTreeId, paramLanguage) { const company = this.CompanyMap.get(chatTreeId) || this.CompanyMap.get(chatTreeId.split('.')[1]); if (!paramLanguage && company) { return this.resolveTreeInstance(company.defaultLanguage, chatTreeId).has(chatTreeId); } return this.resolveTreeInstance(paramLanguage, chatTreeId).has(chatTreeId); } async recursiveDialog(map, node) { if (node.children) { node.children.forEach(async (item) => { map.set(item.dialog, item); await this.recursiveDialog(map, item); }); } } async initTreeMap(map, tree) { map.set(tree.json.dialog, tree.json); await this.recursiveDialog(map, tree.json); } async initTreeByLanguage(language, languageFrom, tree, needTranslate, languages) { const treeInstance = this.resolveTreeInstance(language, tree.chatTreeId); return new Promise((resolve, reject) => { (async () => { if (needTranslate) { console.time(`${tree.chatTreeId}: ${languageFrom} -> ${language}`); const cached = await AsksuiteTreeManagerGeneralUtils.getCachedChatTree( this.configuration, tree.chatTreeId, language, ); if (cached) { tree = cached; console.log(`Cached tree ${tree.chatTreeId} -- ${language}`); } else { tree = await this.translator .translate(tree, language, languageFrom, languages) .catch(reject); } console.timeEnd(`${tree.chatTreeId}: ${languageFrom} -> ${language}`); } else { tree = await this.translator .translate(tree, language, languageFrom, languages) .catch(reject); } await this.initTreeMap(treeInstance, tree).catch(reject); resolve(); })(); }); } async initTreesByCompanyIDIfNeeded(idsTrees, paramLanguage) { return Promise.all( _.map(idsTrees, async (idTree) => { const language = this.resolveLanguage(paramLanguage, idTree); if (!this.isTreeAlreadyRegistred(idTree, language)) { await this.initTreeByCompanyID(idTree, language); } }), ); } async initTreeByCompanyID(idTree, paramLanguage) { const language = this.resolveLanguage(paramLanguage, idTree); let key = `${idTree}`; if (language) { key += `-${language}`; } if (!this.InitMap.get(idTree) && !(language && this.InitMap.get(key))) { this.InitMap.set(key, true); let tree; if (this.treesTestingCache && this.treesTestingCache.get(idTree)) { tree = this.treesTestingCache.get(idTree); } else { tree = await this.AsksuiteService.findTreeByCompanyId(idTree); const company = this.CompanyMap.get(idTree); const cached = await this.getCachedTree(tree, company); if (!cached && !this.configuration.USE_S3_CACHE_CHAT_TREES && this.treeCompiler) { tree = await this.treeCompiler.compile(tree, company).catch(() => tree); } tree = cached || tree; } const result = await this.initTree(tree, language).catch((e) => { return { error: true, e }; }); this.InitMap.delete(key); if (result && result.error) { throw result.e; } } else { await this.wait.until(function () { return !this.InitMap.get(idTree) && !(language && this.InitMap.get(key)); }); } } getCachedTree(tree, company) { if (!tree || !company) { return null; } const companyLanguages = AsksuiteTreeManagerGeneralUtils.getLanguagesByCompany(company); const defaultLanguage = AsksuiteTreeManagerGeneralUtils.resolveDefaultLanguage( companyLanguages, tree.defaultLanguage, ); return AsksuiteTreeManagerGeneralUtils.getCachedChatTree( this.configuration, tree.chatTreeId, defaultLanguage, ); } resolveThenInitTree(chatTreeId) { const { tree, language } = thenPromisesTranslateTree[chatTreeId]; console.log('--------------------------------------- resolveThenInitTree', { chatTreeId, language, }); delete thenPromisesTranslateTree[chatTreeId]; return this.initTree(tree, language); } async initTree(tree, language) { if (promisesTranslateTree[tree.chatTreeId]) { // next initTree const itemInQueue = thenPromisesTranslateTree[tree.chatTreeId]; const promise = promisesTranslateTree[tree.chatTreeId].catch((e) => console.log('error initTree', e), ); if (itemInQueue) { if (itemInQueue.language && itemInQueue.language !== language) { itemInQueue.language = null; } itemInQueue.tree = tree; } else { thenPromisesTranslateTree[tree.chatTreeId] = { tree, language }; return promise.then(() => this.resolveThenInitTree(tree.chatTreeId)); } return promise; } promisesTranslateTree[tree.chatTreeId] = new Promise((resolve) => { (async () => { console.log('init initTree', tree.chatTreeId); this.IntentsMap.set(tree.chatTreeId, tree.intents); let languages = this.getLanguagesByCompany(tree.chatTreeId); const defaultLanguage = this.resolveDefaultLanguage(languages, tree.defaultLanguage); if (language) { const lang = this.resolveDefaultLanguage(languages, language); languages = _.filter(languages, (l) => l === lang); if ( !this.isTreeAlreadyRegistred(tree.chatTreeId, defaultLanguage) && !_.includes(languages, defaultLanguage) ) { languages.push(defaultLanguage); } } const allLanguages = this.getLanguages(); try { await PromiseBlue.map( languages, (lang) => { return this.initTreeByLanguage( lang, defaultLanguage, tree, lang !== defaultLanguage, allLanguages, ); }, { concurrency: 1 }, ); } catch (e) { console.log('error on initTree', e); } finally { console.log('end initTree', tree.chatTreeId); resolve(); delete promisesTranslateTree[tree.chatTreeId]; } })(); }); return promisesTranslateTree[tree.chatTreeId]; } renewLastAccessCompany(companyId) { if (this.LastAccessCompanyMap && companyId) { this.LastAccessCompanyMap.set(companyId, companyId); } } } module.exports = { AsksuiteTreeManagerGeneral, };