Skip to content

Commit

Permalink
Parse the whole error object and store in the OpenAIException
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanBratanov committed Jan 11, 2024
1 parent 20e2eba commit 68d95d3
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 20 deletions.
21 changes: 9 additions & 12 deletions src/main/java/io/github/stefanbratanov/chatjpt/OpenAIClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ <T> CompletableFuture<HttpResponse<T>> sendHttpRequestAsync(
void validateHttpResponse(HttpResponse<?> httpResponse) {
int statusCode = httpResponse.statusCode();
if (statusCode < 200 || statusCode > 299) {
getErrorMessageFromHttpResponse(httpResponse)
getErrorFromHttpResponse(httpResponse)
.ifPresentOrElse(
errorMessage -> {
throw new OpenAIException(statusCode, errorMessage);
error -> {
throw new OpenAIException(statusCode, error);
},
() -> {
throw new OpenAIException(statusCode, null);
Expand Down Expand Up @@ -146,7 +146,7 @@ private String[] getAuthenticationHeaders(String apiKey, Optional<String> organi
return authHeaders.toArray(new String[] {});
}

private Optional<String> getErrorMessageFromHttpResponse(HttpResponse<?> httpResponse) {
private Optional<OpenAIException.Error> getErrorFromHttpResponse(HttpResponse<?> httpResponse) {
try {
byte[] body;
if (httpResponse.body() instanceof byte[]) {
Expand All @@ -158,14 +158,11 @@ private Optional<String> getErrorMessageFromHttpResponse(HttpResponse<?> httpRes
} else {
return Optional.empty();
}
return Optional.ofNullable(objectMapper.readTree(body).get("error"))
.flatMap(
errorNode ->
Optional.ofNullable(errorNode.get("message"))
.filter(node -> !node.asText().isBlank())
// fallback to "type" if no "message"
.or(() -> Optional.ofNullable(errorNode.get("type"))))
.map(JsonNode::asText);
JsonNode errorNode = objectMapper.readTree(body).get("error");
if (errorNode == null) {
return Optional.empty();
}
return Optional.of(objectMapper.treeToValue(errorNode, OpenAIException.Error.class));
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,31 @@
public final class OpenAIException extends RuntimeException {

private final int statusCode;
private final String errorMessage;
private final Error error;

OpenAIException(int statusCode, String errorMessage) {
super(String.format("%d - %s", statusCode, errorMessage));
OpenAIException(int statusCode, Error error) {
super(String.format("%d - %s", statusCode, error));
this.statusCode = statusCode;
this.errorMessage = errorMessage;
this.error = error;
}

public record Error(String message, String type, String param, String code) {
@Override
public String toString() {
return String.format(
"message: %s, type: %s, param: %s, code: %s", message, type, param, code);
}
}

public int statusCode() {
return statusCode;
}

public String errorMessage() {
return errorMessage;
return error.message();
}

public Error error() {
return error;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ protected void awaitCondition(
Supplier<Boolean> condition, Duration pollingInterval, Duration timeout) {
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

CountDownLatch conditionMetLatch = new CountDownLatch(1);
CountDownLatch conditionSatisfiedLatch = new CountDownLatch(1);
executor.scheduleAtFixedRate(
() -> {
if (condition.get()) {
conditionMetLatch.countDown();
conditionSatisfiedLatch.countDown();
}
},
0,
pollingInterval.toMillis(),
TimeUnit.MILLISECONDS);

try {
if (!conditionMetLatch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
if (!conditionSatisfiedLatch.await(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
Assertions.fail("The condition was not satisfied within the time limit.");
}
} catch (InterruptedException ex) {
Expand Down

0 comments on commit 68d95d3

Please sign in to comment.