Add cache source tracking (L1/L2) for Telegram bot responses
Implements cache tier identification in Telegram bot to display data source: - "db" for database queries - "cached L1" for in-memory cache hits - "cached L2" for SQLite cache hits Backend changes: - Added cache metadata fields to TrendsResponse and DashboardSummary models (cache_hit, response_time_ms, cache_source) - Updated /api/dashboard/summary and /api/dashboard/trends endpoints to include cache metadata when X-Include-Cache-Metadata header is present - Cache metadata is extracted from request.state (set by @cached decorator) Telegram bot changes: - Updated API client to send X-Include-Cache-Metadata header - Modified helpers to extract cache_source from backend responses - Updated handlers to pass cache metadata to formatters - Performance footer now displays specific cache tier (L1 vs L2) Fixed Pydantic serialization issue: - Changed field names from _cache_hit to cache_hit (without underscore) - Pydantic excludes underscore-prefixed fields from JSON by default 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,7 @@ async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
if result:
|
||||
# Success!
|
||||
username = result['username']
|
||||
jwt_token = result['jwt_token']
|
||||
|
||||
# Show main menu with buttons for newly linked user
|
||||
session_manager = get_session_manager()
|
||||
@@ -77,8 +78,19 @@ async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
company_name = company['name'] if company else None
|
||||
company_cui = company.get('cui') if company else None
|
||||
|
||||
# Get cache status
|
||||
cache_enabled = None
|
||||
try:
|
||||
from app.api.client import get_backend_client
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
cache_stats = await client.get_cache_stats(jwt_token=jwt_token)
|
||||
cache_enabled = cache_stats.get('user_enabled', True)
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not get cache status in /start: {e}")
|
||||
|
||||
from app.bot.menus import create_main_menu, pad_message_for_wide_buttons
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated=True)
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated=True, cache_enabled=cache_enabled)
|
||||
|
||||
# Single welcome message with menu
|
||||
if company_name:
|
||||
@@ -209,6 +221,11 @@ Dupa conectarea contului, foloseste **butoanele interactive** pentru:
|
||||
/help - Acest mesaj de ajutor
|
||||
/unlink - Deconecteaza contul (securitate)
|
||||
|
||||
**Comenzi Cache (optimizare performanta):**
|
||||
/togglecache - Activeaza/Dezactiveaza cache pentru tine
|
||||
/clearcache - Sterge cache pentru compania activa
|
||||
/clearcache all - Sterge tot cache-ul
|
||||
|
||||
**Conectare cont:**
|
||||
1. Loghează-te în aplicația web ROA2WEB
|
||||
2. Accesează Setări → Telegram Linking
|
||||
@@ -263,6 +280,158 @@ async def clear_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
)
|
||||
|
||||
|
||||
async def clearcache_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""
|
||||
Handle /clearcache command.
|
||||
|
||||
Clears the cache for the current company or all companies.
|
||||
|
||||
Usage:
|
||||
- /clearcache - Clear cache for current company
|
||||
- /clearcache all - Clear entire cache (all companies)
|
||||
|
||||
Args:
|
||||
update: Telegram update object
|
||||
context: Telegram context
|
||||
"""
|
||||
try:
|
||||
telegram_user_id = update.effective_user.id
|
||||
logger.info(f"/clearcache command from user {telegram_user_id}")
|
||||
|
||||
# Check if user is linked
|
||||
is_linked = await check_user_linked(telegram_user_id)
|
||||
if not is_linked:
|
||||
await update.message.reply_text(
|
||||
"**Cont neconectat**\n\nFoloseste /start pentru a conecta contul.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
return
|
||||
|
||||
# Get auth data
|
||||
auth_data = await get_user_auth_data(telegram_user_id)
|
||||
jwt_token = auth_data['jwt_token']
|
||||
|
||||
# Check if user wants to clear all cache
|
||||
clear_all = len(context.args) > 0 and context.args[0].lower() == 'all'
|
||||
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
if clear_all:
|
||||
# Clear entire cache
|
||||
result = await client.client.post(
|
||||
"/api/cache/invalidate",
|
||||
json={},
|
||||
headers=client._get_auth_headers(jwt_token)
|
||||
)
|
||||
if result.status_code == 200:
|
||||
await update.message.reply_text(
|
||||
"✅ **Cache șters complet**\n\n"
|
||||
"Toate datele cached au fost șterse.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text("❌ Eroare la ștergerea cache-ului.")
|
||||
else:
|
||||
# Get active company
|
||||
session_manager = get_session_manager()
|
||||
from app.bot.helpers import get_active_company_or_prompt
|
||||
company = await get_active_company_or_prompt(update, session_manager, telegram_user_id)
|
||||
|
||||
if not company:
|
||||
return
|
||||
|
||||
# Clear cache for current company
|
||||
result = await client.client.post(
|
||||
"/api/cache/invalidate",
|
||||
json={"company_id": company['id']},
|
||||
headers=client._get_auth_headers(jwt_token)
|
||||
)
|
||||
|
||||
if result.status_code == 200:
|
||||
await update.message.reply_text(
|
||||
f"✅ **Cache șters pentru {company['name']}**\n\n"
|
||||
"Datele vor fi reîncărcate la următoarea interogare.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text("❌ Eroare la ștergerea cache-ului.")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in clearcache_command: {e}", exc_info=True)
|
||||
await update.message.reply_text("Eroare la ștergerea cache-ului.")
|
||||
|
||||
|
||||
async def togglecache_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""
|
||||
Handle /togglecache command.
|
||||
|
||||
Toggles cache on/off for the current user.
|
||||
|
||||
Args:
|
||||
update: Telegram update object
|
||||
context: Telegram context
|
||||
"""
|
||||
try:
|
||||
telegram_user_id = update.effective_user.id
|
||||
logger.info(f"/togglecache command from user {telegram_user_id}")
|
||||
|
||||
# Check if user is linked
|
||||
is_linked = await check_user_linked(telegram_user_id)
|
||||
if not is_linked:
|
||||
await update.message.reply_text(
|
||||
"**Cont neconectat**\n\nFoloseste /start pentru a conecta contul.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
return
|
||||
|
||||
# Get auth data
|
||||
auth_data = await get_user_auth_data(telegram_user_id)
|
||||
jwt_token = auth_data['jwt_token']
|
||||
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
# Get current cache stats to determine current state
|
||||
stats_response = await client.client.get(
|
||||
"/api/cache/stats",
|
||||
headers=client._get_auth_headers(jwt_token)
|
||||
)
|
||||
|
||||
if stats_response.status_code == 200:
|
||||
stats = stats_response.json()
|
||||
current_enabled = stats.get('user_cache_enabled', True)
|
||||
|
||||
# Toggle to opposite state
|
||||
new_state = not current_enabled
|
||||
|
||||
toggle_response = await client.client.post(
|
||||
"/api/cache/toggle-user",
|
||||
json={"enabled": new_state},
|
||||
headers=client._get_auth_headers(jwt_token)
|
||||
)
|
||||
|
||||
if toggle_response.status_code == 200:
|
||||
if new_state:
|
||||
await update.message.reply_text(
|
||||
"✅ **Cache activat**\n\n"
|
||||
"Interogările tale vor folosi cache-ul pentru răspunsuri mai rapide.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text(
|
||||
"⚠️ **Cache dezactivat**\n\n"
|
||||
"Interogările tale vor accesa direct baza de date Oracle.",
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text("❌ Eroare la comutarea cache-ului.")
|
||||
else:
|
||||
await update.message.reply_text("❌ Eroare la citirea stării cache-ului.")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in togglecache_command: {e}", exc_info=True)
|
||||
await update.message.reply_text("Eroare la comutarea cache-ului.")
|
||||
|
||||
|
||||
async def companies_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""
|
||||
Handle /companies command.
|
||||
@@ -574,6 +743,11 @@ async def trezorerie_command(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
||||
await update.message.reply_text("Eroare la incarcarea trezoreriei.")
|
||||
return
|
||||
|
||||
# Extract cache metadata
|
||||
cache_hit = treasury_data.get('cache_hit', False)
|
||||
response_time_ms = treasury_data.get('response_time_ms', 0)
|
||||
cache_source = treasury_data.get('cache_source', None)
|
||||
|
||||
# Format combined response (casa + banca) - rotunjit la leu (0 zecimale)
|
||||
casa_total = round(treasury_data['casa']['total'])
|
||||
banca_total = round(treasury_data['banca']['total'])
|
||||
@@ -589,6 +763,11 @@ async def trezorerie_command(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
||||
from app.bot.menus import format_response_with_company
|
||||
text = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer
|
||||
if response_time_ms > 0:
|
||||
from app.bot.formatters import add_performance_footer
|
||||
text = add_performance_footer(text, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
# Add buttons to view details
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
keyboard = InlineKeyboardMarkup([
|
||||
@@ -645,9 +824,20 @@ async def menu_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
company_name = company['name'] if company else None
|
||||
company_cui = company.get('cui') if company else None
|
||||
|
||||
# Get cache status for user
|
||||
cache_enabled = None
|
||||
try:
|
||||
from app.api.client import get_backend_client
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
cache_stats = await client.get_cache_stats(jwt_token=auth_data['jwt_token'])
|
||||
cache_enabled = cache_stats.get('user_enabled', True)
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not get cache status: {e}")
|
||||
|
||||
# Create main menu (user is authenticated if they passed the is_linked check)
|
||||
from app.bot.menus import create_main_menu, get_menu_message
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated=True)
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated=True, cache_enabled=cache_enabled)
|
||||
menu_text = get_menu_message(company_name, company_cui)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -708,11 +898,19 @@ async def trezorerie_casa_command(update: Update, context: ContextTypes.DEFAULT_
|
||||
return
|
||||
|
||||
# Format response
|
||||
from app.bot.formatters import format_treasury_casa_response
|
||||
from app.bot.formatters import format_treasury_casa_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_treasury_casa_response(treasury_data['casa'])
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
|
||||
cache_hit = treasury_data['cache_hit']
|
||||
response_time_ms = treasury_data['response_time_ms']
|
||||
cache_source = treasury_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("casa", show_export=True)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -773,11 +971,19 @@ async def trezorerie_banca_command(update: Update, context: ContextTypes.DEFAULT
|
||||
return
|
||||
|
||||
# Format response
|
||||
from app.bot.formatters import format_treasury_banca_response
|
||||
from app.bot.formatters import format_treasury_banca_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_treasury_banca_response(treasury_data['banca'])
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
|
||||
cache_hit = treasury_data['cache_hit']
|
||||
response_time_ms = treasury_data['response_time_ms']
|
||||
cache_source = treasury_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("banca", show_export=True)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -838,8 +1044,13 @@ async def clienti_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await update.message.reply_text("Eroare la incarcarea datelor clienti.")
|
||||
return
|
||||
|
||||
# Extract cache metadata
|
||||
cache_hit = clients_data.get('cache_hit', False)
|
||||
response_time_ms = clients_data.get('response_time_ms', 0)
|
||||
cache_source = clients_data.get('cache_source', None)
|
||||
|
||||
# Format response
|
||||
from app.bot.formatters import format_clients_balance_response
|
||||
from app.bot.formatters import format_clients_balance_response, add_performance_footer
|
||||
from app.bot.menus import create_client_list_keyboard, format_response_with_company
|
||||
|
||||
content = format_clients_balance_response(
|
||||
@@ -847,6 +1058,11 @@ async def clienti_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
clients_data['maturity']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer
|
||||
if response_time_ms > 0:
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_client_list_keyboard(clients_data['clients'], page=0)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -907,8 +1123,13 @@ async def furnizori_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await update.message.reply_text("Eroare la incarcarea datelor furnizori.")
|
||||
return
|
||||
|
||||
# Extract cache metadata
|
||||
cache_hit = suppliers_data.get('cache_hit', False)
|
||||
response_time_ms = suppliers_data.get('response_time_ms', 0)
|
||||
cache_source = suppliers_data.get('cache_source', None)
|
||||
|
||||
# Format response
|
||||
from app.bot.formatters import format_suppliers_balance_response
|
||||
from app.bot.formatters import format_suppliers_balance_response, add_performance_footer
|
||||
from app.bot.menus import create_supplier_list_keyboard, format_response_with_company
|
||||
|
||||
content = format_suppliers_balance_response(
|
||||
@@ -916,6 +1137,11 @@ async def furnizori_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
suppliers_data['maturity']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer
|
||||
if response_time_ms > 0:
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_supplier_list_keyboard(suppliers_data['suppliers'], page=0)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -976,7 +1202,7 @@ async def evolutie_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
return
|
||||
|
||||
# Format response
|
||||
from app.bot.formatters import format_cashflow_evolution_response
|
||||
from app.bot.formatters import format_cashflow_evolution_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_cashflow_evolution_response(
|
||||
@@ -984,6 +1210,14 @@ async def evolutie_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
evolution_data['monthly']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in evolution_data and 'response_time_ms' in evolution_data:
|
||||
cache_hit = evolution_data['cache_hit']
|
||||
response_time_ms = evolution_data['response_time_ms']
|
||||
cache_source = evolution_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("evolutie", show_export=False, show_refresh=False)
|
||||
|
||||
await update.message.reply_text(
|
||||
@@ -1205,11 +1439,19 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
from app.bot.helpers import get_treasury_breakdown_split
|
||||
treasury_data = await get_treasury_breakdown_split(company['id'], jwt_token)
|
||||
|
||||
from app.bot.formatters import format_treasury_casa_response
|
||||
from app.bot.formatters import format_treasury_casa_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_treasury_casa_response(treasury_data['casa'])
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
|
||||
cache_hit = treasury_data['cache_hit']
|
||||
response_time_ms = treasury_data['response_time_ms']
|
||||
cache_source = treasury_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("casa", show_export=False, show_refresh=False)
|
||||
|
||||
try:
|
||||
@@ -1228,11 +1470,19 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
from app.bot.helpers import get_treasury_breakdown_split
|
||||
treasury_data = await get_treasury_breakdown_split(company['id'], jwt_token)
|
||||
|
||||
from app.bot.formatters import format_treasury_banca_response
|
||||
from app.bot.formatters import format_treasury_banca_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_treasury_banca_response(treasury_data['banca'])
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in treasury_data and 'response_time_ms' in treasury_data:
|
||||
cache_hit = treasury_data['cache_hit']
|
||||
response_time_ms = treasury_data['response_time_ms']
|
||||
cache_source = treasury_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("banca", show_export=False, show_refresh=False)
|
||||
|
||||
try:
|
||||
@@ -1251,7 +1501,7 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
from app.bot.helpers import get_clients_with_maturity
|
||||
clients_data = await get_clients_with_maturity(company['id'], jwt_token)
|
||||
|
||||
from app.bot.formatters import format_clients_balance_response
|
||||
from app.bot.formatters import format_clients_balance_response, add_performance_footer
|
||||
from app.bot.menus import create_client_list_keyboard, format_response_with_company
|
||||
|
||||
content = format_clients_balance_response(
|
||||
@@ -1259,6 +1509,14 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
clients_data['maturity']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in clients_data and 'response_time_ms' in clients_data:
|
||||
cache_hit = clients_data['cache_hit']
|
||||
response_time_ms = clients_data['response_time_ms']
|
||||
cache_source = clients_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_client_list_keyboard(clients_data['clients'], page=0)
|
||||
|
||||
await query.edit_message_text(
|
||||
@@ -1272,7 +1530,7 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
from app.bot.helpers import get_suppliers_with_maturity
|
||||
suppliers_data = await get_suppliers_with_maturity(company['id'], jwt_token)
|
||||
|
||||
from app.bot.formatters import format_suppliers_balance_response
|
||||
from app.bot.formatters import format_suppliers_balance_response, add_performance_footer
|
||||
from app.bot.menus import create_supplier_list_keyboard, format_response_with_company
|
||||
|
||||
content = format_suppliers_balance_response(
|
||||
@@ -1280,6 +1538,14 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
suppliers_data['maturity']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in suppliers_data and 'response_time_ms' in suppliers_data:
|
||||
cache_hit = suppliers_data['cache_hit']
|
||||
response_time_ms = suppliers_data['response_time_ms']
|
||||
cache_source = suppliers_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_supplier_list_keyboard(suppliers_data['suppliers'], page=0)
|
||||
|
||||
await query.edit_message_text(
|
||||
@@ -1293,7 +1559,7 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
from app.bot.helpers import get_cashflow_evolution_data
|
||||
evolution_data = await get_cashflow_evolution_data(company['id'], jwt_token)
|
||||
|
||||
from app.bot.formatters import format_cashflow_evolution_response
|
||||
from app.bot.formatters import format_cashflow_evolution_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
content = format_cashflow_evolution_response(
|
||||
@@ -1301,6 +1567,14 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
evolution_data['monthly']
|
||||
)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer if cache metadata is available
|
||||
if 'cache_hit' in evolution_data and 'response_time_ms' in evolution_data:
|
||||
cache_hit = evolution_data['cache_hit']
|
||||
response_time_ms = evolution_data['response_time_ms']
|
||||
cache_source = evolution_data.get('cache_source', None)
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
|
||||
keyboard = create_action_buttons("evolutie", show_export=False, show_refresh=False)
|
||||
|
||||
await query.edit_message_text(
|
||||
@@ -1309,6 +1583,72 @@ async def handle_menu_callback(query, telegram_user_id: int, callback_data: str)
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
|
||||
elif action == "togglecache":
|
||||
# Toggle cache pentru user
|
||||
try:
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
cache_stats = await client.get_cache_stats(jwt_token=jwt_token)
|
||||
user_enabled = cache_stats.get('user_enabled', True)
|
||||
|
||||
# Create toggle buttons
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
keyboard = [
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
"✅ Activează" if not user_enabled else "❌ Dezactivează",
|
||||
callback_data=f"cache_toggle:{'on' if not user_enabled else 'off'}"
|
||||
)
|
||||
],
|
||||
[InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
|
||||
]
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
|
||||
status = "ACTIVAT" if user_enabled else "DEZACTIVAT"
|
||||
message = f"**Cache Status**\n\nCurent: {status}\n\n"
|
||||
|
||||
if user_enabled:
|
||||
message += "Vrei să dezactivezi cache-ul temporar?\nFolosește pentru teste de performanță."
|
||||
else:
|
||||
message += "Cache-ul este dezactivat.\nToate queries merg direct la Oracle."
|
||||
|
||||
await query.edit_message_text(
|
||||
message,
|
||||
reply_markup=reply_markup,
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Toggle cache menu error: {e}", exc_info=True)
|
||||
await query.answer("Eroare la obținerea status cache.", show_alert=True)
|
||||
|
||||
elif action == "clearcache":
|
||||
# Clear cache
|
||||
try:
|
||||
# Create inline keyboard
|
||||
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
|
||||
keyboard = [
|
||||
[
|
||||
InlineKeyboardButton("Toate companiile", callback_data="cache_clear:all"),
|
||||
InlineKeyboardButton("Doar compania mea", callback_data="cache_clear:current")
|
||||
],
|
||||
[InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
|
||||
]
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
|
||||
message = "**🔄 Invalidare Cache**\n\n"
|
||||
if company:
|
||||
message += f"Compania curentă: {company['name']}\n\n"
|
||||
message += "Alege scope:"
|
||||
|
||||
await query.edit_message_text(
|
||||
message,
|
||||
reply_markup=reply_markup,
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Clear cache menu error: {e}", exc_info=True)
|
||||
await query.answer("Eroare la afișarea opțiuni cache.", show_alert=True)
|
||||
|
||||
elif action == "select_company":
|
||||
# ✅ MODIFICARE: Folosim funcția comună
|
||||
await _handle_selectcompany_view(
|
||||
@@ -1346,10 +1686,22 @@ async def handle_action_callback(query, telegram_user_id: int, callback_data: st
|
||||
auth_data = await get_user_auth_data(telegram_user_id)
|
||||
is_authenticated = auth_data is not None
|
||||
|
||||
# Get cache status for user
|
||||
cache_enabled = None
|
||||
if is_authenticated:
|
||||
try:
|
||||
from app.api.client import get_backend_client
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
cache_stats = await client.get_cache_stats(jwt_token=auth_data['jwt_token'])
|
||||
cache_enabled = cache_stats.get('user_enabled', True)
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not get cache status: {e}")
|
||||
|
||||
from app.bot.menus import create_main_menu, get_menu_message
|
||||
company_name = company['name'] if company else None
|
||||
company_cui = company.get('cui') if company else None
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated)
|
||||
keyboard = create_main_menu(company_name, company_cui, is_authenticated, cache_enabled)
|
||||
menu_text = get_menu_message(company_name, company_cui)
|
||||
|
||||
await query.edit_message_text(
|
||||
@@ -1897,6 +2249,87 @@ async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
elif callback_data.startswith("nav:back:"):
|
||||
await handle_navigation_back(query, telegram_user_id, callback_data)
|
||||
|
||||
# ========== CACHE CALLBACKS (FAZA 6) ==========
|
||||
|
||||
elif callback_data.startswith("cache_toggle:"):
|
||||
# Handle cache toggle button
|
||||
action = callback_data.split(":")[1]
|
||||
enabled = action == "on"
|
||||
|
||||
auth_data = await get_user_auth_data(telegram_user_id)
|
||||
jwt_token = auth_data['jwt_token']
|
||||
|
||||
try:
|
||||
client = get_backend_client()
|
||||
async with client:
|
||||
await client.toggle_user_cache(jwt_token=jwt_token, enabled=enabled)
|
||||
|
||||
status = "activat" if enabled else "dezactivat"
|
||||
message = f"✅ **Cache {status}** pentru tine.\n\n"
|
||||
|
||||
if enabled:
|
||||
message += "Queries vor fi servite din cache când e posibil."
|
||||
else:
|
||||
message += "Toate queries vor merge direct la Oracle.\nFolosește /togglecache din nou pentru reactivare."
|
||||
|
||||
# Add back button
|
||||
keyboard = InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
|
||||
])
|
||||
|
||||
await query.edit_message_text(
|
||||
message,
|
||||
reply_markup=keyboard,
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Toggle cache callback error: {e}", exc_info=True)
|
||||
await query.answer("❌ Eroare la modificarea setării cache.", show_alert=True)
|
||||
|
||||
elif callback_data.startswith("cache_clear:"):
|
||||
# Handle clear cache button
|
||||
scope = callback_data.split(":")[1]
|
||||
|
||||
auth_data = await get_user_auth_data(telegram_user_id)
|
||||
jwt_token = auth_data['jwt_token']
|
||||
|
||||
try:
|
||||
client = get_backend_client()
|
||||
|
||||
if scope == "all":
|
||||
# Clear all cache
|
||||
async with client:
|
||||
await client.invalidate_cache(jwt_token=jwt_token, company_id=None)
|
||||
message = "✅ Cache invalidat pentru **toate companiile**.\n\nDatele vor fi refreshate la următoarea interogare."
|
||||
|
||||
elif scope == "current":
|
||||
# Clear only current company
|
||||
session_manager = get_session_manager()
|
||||
session = await session_manager.get_or_create_session(telegram_user_id)
|
||||
company = session.get_active_company()
|
||||
|
||||
if not company:
|
||||
await query.answer("Nu ai o companie selectată.", show_alert=True)
|
||||
return
|
||||
|
||||
async with client:
|
||||
await client.invalidate_cache(jwt_token=jwt_token, company_id=company['id'])
|
||||
message = f"✅ Cache invalidat pentru **{company['name']}**.\n\nDatele vor fi refreshate la următoarea interogare."
|
||||
|
||||
# Add back button
|
||||
keyboard = InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("« Înapoi la Meniu", callback_data="action:menu")]
|
||||
])
|
||||
|
||||
await query.edit_message_text(
|
||||
message,
|
||||
reply_markup=keyboard,
|
||||
parse_mode=ParseMode.MARKDOWN
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Clear cache callback error: {e}", exc_info=True)
|
||||
await query.answer("❌ Eroare la ștergerea cache-ului.", show_alert=True)
|
||||
|
||||
# ========== PAGINATION CALLBACKS ==========
|
||||
|
||||
elif callback_data.startswith("clients_page:"):
|
||||
@@ -2144,11 +2577,20 @@ async def _handle_sold_view(
|
||||
await query_or_update.message.reply_text(error_msg)
|
||||
return
|
||||
|
||||
from app.bot.formatters import format_dashboard_response
|
||||
from app.bot.formatters import format_dashboard_response, add_performance_footer
|
||||
from app.bot.menus import create_action_buttons, format_response_with_company
|
||||
|
||||
# Extract cache metadata
|
||||
cache_hit = data.get('cache_hit', False)
|
||||
response_time_ms = data.get('response_time_ms', 0)
|
||||
cache_source = data.get('cache_source', None)
|
||||
|
||||
content = format_dashboard_response(data)
|
||||
response = format_response_with_company(content, company['name'])
|
||||
|
||||
# Add performance footer
|
||||
if response_time_ms > 0:
|
||||
response = add_performance_footer(response, cache_hit, response_time_ms, cache_source)
|
||||
keyboard = create_action_buttons("sold", show_export=False, show_refresh=False)
|
||||
|
||||
if is_callback:
|
||||
|
||||
Reference in New Issue
Block a user