|
|
|
@@ -9,9 +9,10 @@ from apiApp.database import get_db
|
|
|
|
|
from apiApp.database.Audio import Audio
|
|
|
|
|
from apiApp.database.AiConclusion import AiConclusion
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
import time
|
|
|
|
|
import logging
|
|
|
|
|
import requests
|
|
|
|
|
from apiApp.config import WEBHOOK_ENDPOINT, WEBHOOK_API_KEY
|
|
|
|
|
from apiApp.config import WEBHOOK_ENDPOINT, WEBHOOK_API_KEY, CALLS_WEB_CLIENT_URL
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
ai_conclusion_router = APIRouter()
|
|
|
|
@@ -168,39 +169,48 @@ async def save_ai_conclusion(request: AiConclusionRequest, db: Session = Depends
|
|
|
|
|
if (audio.sourse or "").lower() == "external" and request.callback_url:
|
|
|
|
|
_send_callback(request.callback_url, audio, conclusion_data)
|
|
|
|
|
|
|
|
|
|
# Отправляем webhook в Calls_WEB_Client_main для анализа
|
|
|
|
|
try:
|
|
|
|
|
if (audio.sourse or "").lower() != "external":
|
|
|
|
|
logger.info(f"📤 Отправка webhook в Calls_WEB_Client_main для {request.filename}")
|
|
|
|
|
# Отправляем webhook в Calls_WEB_Client_main для анализа (с retry при перезагрузке контейнера)
|
|
|
|
|
if (audio.sourse or "").lower() != "external":
|
|
|
|
|
logger.info(f"📤 Отправка webhook в Calls_WEB_Client_main для {request.filename}")
|
|
|
|
|
|
|
|
|
|
webhook_payload = {
|
|
|
|
|
"audio_id": str(audio.id),
|
|
|
|
|
"filename": request.filename,
|
|
|
|
|
"transcription": request.transcription,
|
|
|
|
|
"corrected_transcription": request.corrected_transcription,
|
|
|
|
|
"segments": request.segments,
|
|
|
|
|
"processing_time_seconds": request.processing_time_seconds
|
|
|
|
|
}
|
|
|
|
|
webhook_payload = {
|
|
|
|
|
"audio_id": str(audio.id),
|
|
|
|
|
"filename": request.filename,
|
|
|
|
|
"transcription": request.transcription,
|
|
|
|
|
"corrected_transcription": request.corrected_transcription,
|
|
|
|
|
"segments": request.segments,
|
|
|
|
|
"processing_time_seconds": request.processing_time_seconds
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
webhook_response = requests.post(
|
|
|
|
|
WEBHOOK_ENDPOINT,
|
|
|
|
|
json=webhook_payload,
|
|
|
|
|
headers={"X-Webhook-Key": WEBHOOK_API_KEY},
|
|
|
|
|
timeout=30
|
|
|
|
|
)
|
|
|
|
|
max_retries = 5
|
|
|
|
|
delays = [2, 4, 8, 15, 30]
|
|
|
|
|
delivered = False
|
|
|
|
|
|
|
|
|
|
if webhook_response.status_code == 200:
|
|
|
|
|
logger.info(f"✅ Webhook успешно отправлен для {request.filename}")
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(f"⚠️ Webhook вернул статус {webhook_response.status_code}")
|
|
|
|
|
logger.warning(f"Response: {webhook_response.text}")
|
|
|
|
|
for attempt in range(1, max_retries + 1):
|
|
|
|
|
try:
|
|
|
|
|
webhook_response = requests.post(
|
|
|
|
|
WEBHOOK_ENDPOINT,
|
|
|
|
|
json=webhook_payload,
|
|
|
|
|
headers={"X-Webhook-Key": WEBHOOK_API_KEY},
|
|
|
|
|
timeout=30
|
|
|
|
|
)
|
|
|
|
|
if webhook_response.status_code in (200, 201):
|
|
|
|
|
logger.info(f"✅ Webhook успешно отправлен для {request.filename} (попытка {attempt}/{max_retries})")
|
|
|
|
|
delivered = True
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(f"⚠️ Webhook вернул статус {webhook_response.status_code} (попытка {attempt}/{max_retries})")
|
|
|
|
|
logger.warning(f"Response: {webhook_response.text[:200]}")
|
|
|
|
|
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
|
|
|
|
|
logger.warning(f"⏳ Calls_WEB_Client_main временно недоступен ({type(e).__name__}), попытка {attempt}/{max_retries}...")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"❌ Непредвиденная ошибка при отправке webhook (попытка {attempt}): {e}")
|
|
|
|
|
|
|
|
|
|
except requests.exceptions.ConnectionError:
|
|
|
|
|
logger.error(f"❌ Не удалось подключиться к Calls_WEB_Client_main webhook: {WEBHOOK_ENDPOINT}")
|
|
|
|
|
except requests.exceptions.Timeout:
|
|
|
|
|
logger.warning(f"⚠️ Таймаут при отправке webhook для {request.filename}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"❌ Ошибка при отправке webhook: {e}")
|
|
|
|
|
if attempt < max_retries:
|
|
|
|
|
time.sleep(delays[attempt - 1])
|
|
|
|
|
|
|
|
|
|
if not delivered:
|
|
|
|
|
logger.error(f"❌ Не удалось доставить webhook для {request.filename} после {max_retries} попыток")
|
|
|
|
|
|
|
|
|
|
return AiConclusionResponse(
|
|
|
|
|
success=True,
|
|
|
|
|