From 3b7a1b7b9ae9ec1f29bf5a6fa421f57d910870f2 Mon Sep 17 00:00:00 2001 From: Cliff Casey Date: Mon, 6 Jul 2026 12:56:37 -0400 Subject: [PATCH 1/2] fixes an issue where errors caused no consumption of responses, which held conns and blocked the pool --- .../xapi/client/StatementClient.java | 3 ++ .../xapi/client/StatementClientTest.java | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/main/java/com/yetanalytics/xapi/client/StatementClient.java b/src/main/java/com/yetanalytics/xapi/client/StatementClient.java index 758b1c7..d0f13c3 100644 --- a/src/main/java/com/yetanalytics/xapi/client/StatementClient.java +++ b/src/main/java/com/yetanalytics/xapi/client/StatementClient.java @@ -76,6 +76,7 @@ private List doPost(List statements, URI endpoint) responseBody, new TypeReference>(){}); } else { + EntityUtils.consumeQuietly(response.getEntity()); throw new StatementClientException(String.format( "Error, Non-200 Status. Received: %s", response.getStatusLine().getStatusCode())); @@ -119,6 +120,7 @@ private StatementResult doGetStatementResult(URI endpoint) String responseBody = EntityUtils.toString(response.getEntity()); return Mapper.getMapper().readValue(responseBody, StatementResult.class); } else { + EntityUtils.consumeQuietly(response.getEntity()); throw new StatementClientException(String.format( "Error, Non-200 Status. Received: %s", response.getStatusLine().getStatusCode())); @@ -134,6 +136,7 @@ private Statement doGetStatement(URI endpoint) String responseBody = EntityUtils.toString(response.getEntity()); return Mapper.getMapper().readValue(responseBody, Statement.class); } else { + EntityUtils.consumeQuietly(response.getEntity()); throw new StatementClientException(String.format( "Error, Non-200 Status. Received: %s", response.getStatusLine().getStatusCode())); diff --git a/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java b/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java index 2158ecd..deee7eb 100644 --- a/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java +++ b/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.core.exc.StreamReadException; import com.fasterxml.jackson.databind.DatabindException; import com.yetanalytics.xapi.client.filters.StatementFilters; +import com.yetanalytics.xapi.exception.StatementClientException; import com.yetanalytics.xapi.model.Agent; import com.yetanalytics.xapi.model.Statement; import com.yetanalytics.xapi.util.Mapper; @@ -216,5 +217,39 @@ public void testDateFilters() throws StreamReadException, DatabindException, IOE List result = client.getStatements(filters); assertNotNull(result); + } + + @Test + public void testConnectionPoolOnError() throws StreamReadException, DatabindException, IOException { + LRS lrs = new LRS(getMappedHost(), KEY, SECRET); + StatementClient client = new StatementClient(lrs); + + Statement statement = new Statement(); + statement.setId(UUID.randomUUID()); + + // Try 1, handled, no issue + try { + client.postStatement(statement); + } catch (StatementClientException e) { + assertTrue(e.getMessage().contains("Error, Non-200 Status. Received: 400")); + } + + // Try 2, handled, no issue + try { + client.postStatement(statement); + } catch (StatementClientException e) { + assertTrue(e.getMessage().contains("Error, Non-200 Status. Received: 400")); + } + + // Try 3, will await indefinitely if connection pool is not cleaned up properly + // Test will finish successfully if client is handling conns right + try { + client.postStatement(statement); + } catch (StatementClientException e) { + assertTrue(e.getMessage().contains("Error, Non-200 Status. Received: 400")); + } + + + } } From 1034fddce8ca9a3416d5814452235c3d5fb9cfe6 Mon Sep 17 00:00:00 2001 From: Cliff Casey Date: Mon, 6 Jul 2026 13:10:27 -0400 Subject: [PATCH 2/2] add timeout --- pom.xml | 2 +- .../com/yetanalytics/xapi/client/StatementClientTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0013af0..4f927ee 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ org.junit.jupiter junit-jupiter-engine - 5.2.0 + 5.10.5 test diff --git a/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java b/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java index deee7eb..3ed1e6d 100644 --- a/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java +++ b/src/test/java/com/yetanalytics/xapi/client/StatementClientTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; import org.testcontainers.containers.GenericContainer; @@ -220,6 +221,7 @@ public void testDateFilters() throws StreamReadException, DatabindException, IOE } @Test + @Timeout(value = 30, unit = TimeUnit.SECONDS) public void testConnectionPoolOnError() throws StreamReadException, DatabindException, IOException { LRS lrs = new LRS(getMappedHost(), KEY, SECRET); StatementClient client = new StatementClient(lrs); @@ -241,7 +243,7 @@ public void testConnectionPoolOnError() throws StreamReadException, DatabindExce assertTrue(e.getMessage().contains("Error, Non-200 Status. Received: 400")); } - // Try 3, will await indefinitely if connection pool is not cleaned up properly + // Try 3, will await indefinitely if connection pool is not cleaned up properly (timeout will trigger) // Test will finish successfully if client is handling conns right try { client.postStatement(statement);