Compare commits
1 Commits
14
...
dev-20261005-1700
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e3d1e347c |
@@ -276,27 +276,34 @@ private suspend fun handleChat(
|
||||
setBody(forwarded.toString())
|
||||
}.execute { resp ->
|
||||
upstreamStatus = resp.status.value
|
||||
if (upstreamStatus in 400..599) {
|
||||
// 4xx/5xx — upstream не смог обработать запрос: 5xx/429/402 — сбой
|
||||
// провайдера (учёт в backoff); 400/401/404/etc. — ошибка либо
|
||||
// запроса, либо состояния апстрима (например, "Model is unavailable"),
|
||||
// но в обоих случаях следующий upstream в пуле может сработать, и
|
||||
// пробуем его. Тело ошибки логируем, но клиенту не возвращаем —
|
||||
// иначе пользователь увидит 400 от самого слабого звена пула,
|
||||
// хотя другие upstream'ы могли бы ответить.
|
||||
val errorBody = runCatching { resp.body<String>() }.getOrDefault("")
|
||||
if (upstreamStatus >= 500 || upstreamStatus == 429 || upstreamStatus == 402) {
|
||||
val rest = backoff.recordFailure(up)
|
||||
metrics.record(modelName, up, statusClass(upstreamStatus))
|
||||
log.warn {
|
||||
"[llm-proxy] model=$modelName upstream=${up.id} вернул $upstreamStatus → фейловер" +
|
||||
"[llm-proxy] model=$modelName upstream=${up.id} вернул $upstreamStatus " +
|
||||
"errorBody=${errorBody.take(500)} → фейловер" +
|
||||
(rest?.let { " (backoff: отдых ${it.toIsoString()})" } ?: "")
|
||||
}
|
||||
} else {
|
||||
metrics.record(modelName, up, statusClass(upstreamStatus))
|
||||
log.warn {
|
||||
"[llm-proxy] model=$modelName upstream=${up.id} вернул $upstreamStatus " +
|
||||
"errorBody=${errorBody.take(500)} → фейловер"
|
||||
}
|
||||
}
|
||||
failed.add(up.id)
|
||||
failover = true
|
||||
return@execute
|
||||
}
|
||||
if (upstreamStatus in 400..499) {
|
||||
// 4xx — JSON-тело, не стрим: читаем безопасно и отдаём клиенту как есть.
|
||||
val errorBody = runCatching { resp.body<String>() }.getOrDefault("")
|
||||
log.warn { "[llm-proxy] chat model=$modelName upstream=${up.id} вернул $upstreamStatus errorBody=${errorBody.take(500)}" }
|
||||
metrics.record(modelName, up, statusClass(upstreamStatus))
|
||||
val ct = resp.headers["Content-Type"] ?: "application/json"
|
||||
call.respondText(errorBody, ContentType.parse(ct), HttpStatusCode.fromValue(upstreamStatus))
|
||||
responded = true
|
||||
return@execute
|
||||
}
|
||||
responded = true
|
||||
backoff.recordSuccess(up)
|
||||
if (clientWantsStream) {
|
||||
|
||||
Reference in New Issue
Block a user