Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JXVi2GMQ7bR5EmbUFdDj7N
49 lines
1.5 KiB
Java
49 lines
1.5 KiB
Java
package com.ankurm.gateway;
|
|
|
|
import java.io.IOException;
|
|
|
|
import com.anthropic.errors.AnthropicIoException;
|
|
import com.anthropic.errors.AnthropicServiceException;
|
|
import com.openai.errors.OpenAIIoException;
|
|
import com.openai.errors.OpenAIServiceException;
|
|
|
|
/**
|
|
* Decides whether a failed model call is worth sending to another provider. Same idea as the
|
|
* {@code providers} module: the vendor SDKs throw unrelated exception families, so walk the cause
|
|
* chain for an HTTP status.
|
|
*/
|
|
public final class Failures {
|
|
|
|
private Failures() {
|
|
}
|
|
|
|
public static int status(Throwable t) {
|
|
for (Throwable c = t; c != null; c = c.getCause()) {
|
|
if (c instanceof ProviderFailure e) {
|
|
return e.status();
|
|
}
|
|
if (c instanceof OpenAIServiceException e) {
|
|
return e.statusCode();
|
|
}
|
|
if (c instanceof AnthropicServiceException e) {
|
|
return e.statusCode();
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** True for overload, rate limit, 5xx and network failures. A 400 or 401 is the caller's problem. */
|
|
public static boolean isTransient(Throwable t) {
|
|
int status = status(t);
|
|
if (status != -1) {
|
|
return status == 408 || status == 429 || status >= 500;
|
|
}
|
|
for (Throwable c = t; c != null; c = c.getCause()) {
|
|
if (c instanceof OpenAIIoException || c instanceof AnthropicIoException || c instanceof IOException) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|