commit
15dde154f5
3 changed files with 66 additions and 19 deletions
|
|
@ -177,7 +177,7 @@ def _get_cached_connector(
|
||||||
oldest_key = _connector_cache_order.pop(0)
|
oldest_key = _connector_cache_order.pop(0)
|
||||||
if oldest_key in _connector_cache:
|
if oldest_key in _connector_cache:
|
||||||
try:
|
try:
|
||||||
_connector_cache[oldest_key].close()
|
_connector_cache[oldest_key].close(forceClose=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Error closing evicted connector: {e}")
|
logger.warning(f"Error closing evicted connector: {e}")
|
||||||
del _connector_cache[oldest_key]
|
del _connector_cache[oldest_key]
|
||||||
|
|
@ -189,6 +189,7 @@ def _get_cached_connector(
|
||||||
dbPort=dbPort,
|
dbPort=dbPort,
|
||||||
userId=userId,
|
userId=userId,
|
||||||
)
|
)
|
||||||
|
_connector_cache[key]._isCachedShared = True
|
||||||
_connector_cache_order.append(key)
|
_connector_cache_order.append(key)
|
||||||
conn = _connector_cache[key]
|
conn = _connector_cache[key]
|
||||||
# Set request-scoped userId via contextvar (avoids mutating shared connector)
|
# Set request-scoped userId via contextvar (avoids mutating shared connector)
|
||||||
|
|
@ -225,6 +226,7 @@ class DatabaseConnector:
|
||||||
|
|
||||||
# Initialize database system first (creates database if needed)
|
# Initialize database system first (creates database if needed)
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
self._isCachedShared = False
|
||||||
self.initDbSystem()
|
self.initDbSystem()
|
||||||
|
|
||||||
# No caching needed with proper database - PostgreSQL handles performance
|
# No caching needed with proper database - PostgreSQL handles performance
|
||||||
|
|
@ -1159,8 +1161,15 @@ class DatabaseConnector:
|
||||||
logger.error(f"Error in semantic search on {table}: {e}")
|
logger.error(f"Error in semantic search on {table}: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def close(self):
|
def close(self, forceClose: bool = False):
|
||||||
"""Close the database connection."""
|
"""Close the database connection.
|
||||||
|
|
||||||
|
Shared cached connectors are intentionally kept open unless forceClose=True.
|
||||||
|
This prevents accidental shutdown from interface __del__ methods while
|
||||||
|
other requests are still using the same cached connector instance.
|
||||||
|
"""
|
||||||
|
if self._isCachedShared and not forceClose:
|
||||||
|
return
|
||||||
if (
|
if (
|
||||||
hasattr(self, "connection")
|
hasattr(self, "connection")
|
||||||
and self.connection
|
and self.connection
|
||||||
|
|
|
||||||
|
|
@ -1743,11 +1743,15 @@ class ComponentObjects:
|
||||||
logger.error("No user ID provided for voice settings")
|
logger.error("No user ID provided for voice settings")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Get voice settings for the user, filtered by RBAC
|
recordFilter: Dict[str, Any] = {"userId": targetUserId}
|
||||||
|
if self.featureInstanceId:
|
||||||
|
recordFilter["featureInstanceId"] = self.featureInstanceId
|
||||||
|
|
||||||
|
# Get voice settings for the user (scoped to current feature instance if available), filtered by RBAC
|
||||||
filteredSettings = getRecordsetWithRBAC(self.db,
|
filteredSettings = getRecordsetWithRBAC(self.db,
|
||||||
VoiceSettings,
|
VoiceSettings,
|
||||||
self.currentUser,
|
self.currentUser,
|
||||||
recordFilter={"userId": targetUserId},
|
recordFilter=recordFilter,
|
||||||
mandateId=self.mandateId
|
mandateId=self.mandateId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2239,19 +2239,53 @@ def _registerCoreTools(registry: ToolRegistry, services):
|
||||||
|
|
||||||
if not voiceName:
|
if not voiceName:
|
||||||
try:
|
try:
|
||||||
|
from modules.interfaces import interfaceDbManagement
|
||||||
featureInstanceId = context.get("featureInstanceId", "")
|
featureInstanceId = context.get("featureInstanceId", "")
|
||||||
userId = context.get("userId", "")
|
userId = context.get("userId", "")
|
||||||
if featureInstanceId and userId:
|
if userId:
|
||||||
dbMgmt = services.chat.interfaceDbApp if hasattr(services.chat, "interfaceDbApp") else None
|
dbMgmt = interfaceDbManagement.getInterface(
|
||||||
if dbMgmt and hasattr(dbMgmt, "getVoiceSettings"):
|
services.user,
|
||||||
vs = dbMgmt.getVoiceSettings(userId)
|
mandateId=mandateId or None,
|
||||||
|
featureInstanceId=featureInstanceId or None,
|
||||||
|
)
|
||||||
|
vs = dbMgmt.getVoiceSettings(userId) if dbMgmt and hasattr(dbMgmt, "getVoiceSettings") else None
|
||||||
if vs:
|
if vs:
|
||||||
voiceMap = {}
|
voiceMap = {}
|
||||||
if hasattr(vs, "ttsVoiceMap") and vs.ttsVoiceMap:
|
if hasattr(vs, "ttsVoiceMap") and vs.ttsVoiceMap:
|
||||||
voiceMap = vs.ttsVoiceMap if isinstance(vs.ttsVoiceMap, dict) else {}
|
voiceMap = vs.ttsVoiceMap if isinstance(vs.ttsVoiceMap, dict) else {}
|
||||||
if language in voiceMap:
|
|
||||||
voiceName = voiceMap[language].get("voiceName") if isinstance(voiceMap[language], dict) else voiceMap[language]
|
selectedKey = None
|
||||||
logger.info(f"textToSpeech: using configured voice '{voiceName}' for {language}")
|
selectedVoiceEntry = None
|
||||||
|
baseLanguage = language.split("-")[0].lower() if isinstance(language, str) and language else ""
|
||||||
|
|
||||||
|
# 1) Exact match first (e.g. de-DE)
|
||||||
|
if isinstance(language, str) and language in voiceMap:
|
||||||
|
selectedKey = language
|
||||||
|
selectedVoiceEntry = voiceMap[language]
|
||||||
|
|
||||||
|
# 2) Match short language key (e.g. de)
|
||||||
|
if selectedVoiceEntry is None and baseLanguage and baseLanguage in voiceMap:
|
||||||
|
selectedKey = baseLanguage
|
||||||
|
selectedVoiceEntry = voiceMap[baseLanguage]
|
||||||
|
|
||||||
|
# 3) Match by same language family (e.g. de-CH -> de-DE mapping)
|
||||||
|
if selectedVoiceEntry is None and baseLanguage:
|
||||||
|
for mapKey, mapValue in voiceMap.items():
|
||||||
|
mapKeyNorm = str(mapKey).lower()
|
||||||
|
if mapKeyNorm == baseLanguage or mapKeyNorm.startswith(f"{baseLanguage}-"):
|
||||||
|
selectedKey = str(mapKey)
|
||||||
|
selectedVoiceEntry = mapValue
|
||||||
|
break
|
||||||
|
|
||||||
|
if selectedVoiceEntry is not None:
|
||||||
|
voiceName = (
|
||||||
|
selectedVoiceEntry.get("voiceName")
|
||||||
|
if isinstance(selectedVoiceEntry, dict)
|
||||||
|
else selectedVoiceEntry
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"textToSpeech: using configured voice '{voiceName}' for requested language '{language}' (matched key '{selectedKey}')"
|
||||||
|
)
|
||||||
elif hasattr(vs, "ttsVoice") and vs.ttsVoice and hasattr(vs, "ttsLanguage") and vs.ttsLanguage == language:
|
elif hasattr(vs, "ttsVoice") and vs.ttsVoice and hasattr(vs, "ttsLanguage") and vs.ttsLanguage == language:
|
||||||
voiceName = vs.ttsVoice
|
voiceName = vs.ttsVoice
|
||||||
except Exception as prefErr:
|
except Exception as prefErr:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue