Skip to content

Commit b81de9a

Browse files
authored
Fix batchCheck error handling (#183)
* Fix batchCheck latch handling on errors * Apply Spotless formatting
1 parent a48bc3a commit b81de9a

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

src/main/java/dev/openfga/sdk/api/client/OpenFgaClient.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.Map;
2727
import java.util.concurrent.*;
28+
import java.util.concurrent.atomic.AtomicReference;
2829
import java.util.function.Consumer;
2930
import java.util.stream.Collectors;
3031
import java.util.stream.IntStream;
@@ -715,6 +716,7 @@ public CompletableFuture<ClientBatchCheckResponse> batchCheck(
715716
var latch = new CountDownLatch(batchedChecks.size());
716717

717718
var responses = new ConcurrentLinkedQueue<ClientBatchCheckSingleResponse>();
719+
var failure = new AtomicReference<Throwable>();
718720

719721
var override = new ConfigurationOverride().addHeaders(options);
720722

@@ -735,26 +737,36 @@ public CompletableFuture<ClientBatchCheckResponse> batchCheck(
735737

736738
return api.batchCheck(configuration.getStoreId(), body, override);
737739
})
738-
.handleAsync((batchCheckResponseApiResponse, throwable) -> {
739-
Map<String, BatchCheckSingleResult> response =
740-
batchCheckResponseApiResponse.getData().getResult();
741-
742-
List<ClientBatchCheckSingleResponse> batchResults = new ArrayList<>();
743-
response.forEach((key, result) -> {
744-
boolean allowed = Boolean.TRUE.equals(result.getAllowed());
745-
ClientBatchCheckItem checkItem = correlationIdToCheck.get(key);
746-
var singleResponse =
747-
new ClientBatchCheckSingleResponse(allowed, checkItem, key, result.getError());
748-
batchResults.add(singleResponse);
749-
});
750-
return batchResults;
751-
})
752-
.thenAccept(responses::addAll)
753-
.thenRun(latch::countDown);
740+
.whenComplete((batchCheckResponseApiResponse, throwable) -> {
741+
try {
742+
if (throwable != null) {
743+
failure.compareAndSet(null, throwable);
744+
return;
745+
}
746+
747+
Map<String, BatchCheckSingleResult> response =
748+
batchCheckResponseApiResponse.getData().getResult();
749+
750+
List<ClientBatchCheckSingleResponse> batchResults = new ArrayList<>();
751+
response.forEach((key, result) -> {
752+
boolean allowed = Boolean.TRUE.equals(result.getAllowed());
753+
ClientBatchCheckItem checkItem = correlationIdToCheck.get(key);
754+
var singleResponse =
755+
new ClientBatchCheckSingleResponse(allowed, checkItem, key, result.getError());
756+
batchResults.add(singleResponse);
757+
});
758+
responses.addAll(batchResults);
759+
} finally {
760+
latch.countDown();
761+
}
762+
});
754763

755764
try {
756765
batchedChecks.forEach(batch -> executor.execute(() -> singleBatchCheckRequest.accept(batch)));
757766
latch.await();
767+
if (failure.get() != null) {
768+
return CompletableFuture.failedFuture(failure.get());
769+
}
758770
return CompletableFuture.completedFuture(new ClientBatchCheckResponse(new ArrayList<>(responses)));
759771
} catch (Exception e) {
760772
return CompletableFuture.failedFuture(e);

src/test/java/dev/openfga/sdk/api/client/OpenFgaClientTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,30 @@ public void batchCheck_withOptions() throws Exception {
20722072
assertTrue(response.getResult().isEmpty());
20732073
}
20742074

2075+
@Test
2076+
public void batchCheck_rateLimited() {
2077+
// Given
2078+
String postUrl = String.format("https://api.fga.example/stores/%s/batch-check", DEFAULT_STORE_ID);
2079+
mockHttpClient.onPost(postUrl).doReturn(429, "{\"code\":\"rate_limited\",\"message\":\"Too Many Requests\"}");
2080+
2081+
ClientBatchCheckItem item = new ClientBatchCheckItem()
2082+
.user(DEFAULT_USER)
2083+
.relation(DEFAULT_RELATION)
2084+
._object(DEFAULT_OBJECT)
2085+
.correlationId("cor-1");
2086+
ClientBatchCheckRequest request = new ClientBatchCheckRequest().checks(List.of(item));
2087+
2088+
// When
2089+
ExecutionException execException = assertThrows(
2090+
ExecutionException.class, () -> fga.batchCheck(request).get());
2091+
2092+
// Then
2093+
mockHttpClient.verify().post(postUrl).called(1 + DEFAULT_MAX_RETRIES);
2094+
var exception = assertInstanceOf(FgaApiRateLimitExceededError.class, execException.getCause());
2095+
assertEquals(429, exception.getStatusCode());
2096+
assertEquals("{\"code\":\"rate_limited\",\"message\":\"Too Many Requests\"}", exception.getResponseData());
2097+
}
2098+
20752099
/**
20762100
* Expand all relationships in userset tree format, and following userset rewrite rules. Useful to reason
20772101
* about and debug a certain relationship.

0 commit comments

Comments
 (0)