From ef7873c1b31570fb67bec30a1346b4f136b49a7c Mon Sep 17 00:00:00 2001 From: Matthew Meacham Date: Mon, 30 Aug 2021 12:12:31 -0400 Subject: [PATCH] Fix bug that can prevent fast-polling clients from ever getting data again --- .../main/java/org/opensky/api/OpenSkyApi.java | 11 ++++++-- java/src/test/java/TestOpenSkyApi.java | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/java/src/main/java/org/opensky/api/OpenSkyApi.java b/java/src/main/java/org/opensky/api/OpenSkyApi.java index 27fc909..97db652 100644 --- a/java/src/main/java/org/opensky/api/OpenSkyApi.java +++ b/java/src/main/java/org/opensky/api/OpenSkyApi.java @@ -136,8 +136,15 @@ private OpenSkyStates getResponse(String baseUri, Collection timeDiffAuth) || (!authenticated && now - t > timeDiffNoAuth)); + boolean mayIssueRequest = t == null + || (authenticated && now - t > timeDiffAuth) + || (!authenticated && now - t > timeDiffNoAuth); + if (mayIssueRequest) { + // Optimistically update the last request time if the client can actually issue a request. If the request + // fails, we don't want to immediately retry anyway + lastRequestTime.put(type, now); + } + return mayIssueRequest; } /** diff --git a/java/src/test/java/TestOpenSkyApi.java b/java/src/test/java/TestOpenSkyApi.java index ef4ae86..0b7ba4d 100644 --- a/java/src/test/java/TestOpenSkyApi.java +++ b/java/src/test/java/TestOpenSkyApi.java @@ -153,4 +153,31 @@ public void testAuthGetMyStates() throws IOException { } } + @Test + public void testClientSideRateLimitingDoesNotLockClient() throws IOException, InterruptedException { + // If the client is requesting too fast, ensure it doesn't prevent requests from occurring after the + // rate limiting expires + OpenSkyApi api = new OpenSkyApi(); + OpenSkyStates os = api.getStates(0, null); + assertTrue("More than 1 state vector", os.getStates().size() > 1); + int initialTime = os.getTime(); + + // Simulate frequently-requesting client + long startTime = System.currentTimeMillis(); + while (startTime + 8000L > System.currentTimeMillis()) { + OpenSkyStates states = api.getStates(0, null); + assertNull("Client-side rate limited, should not receive data", states); + Thread.sleep(100L); + } + + // Wait a few more seconds (but less than anon rate limit frequency) + Thread.sleep(5000L); + + // It's been ~13s since our initial request, we should be able to request again as an anonymous caller + os = api.getStates(0, null); + assertNotNull(os); + assertTrue("More than 1 state vector for second valid request", os.getStates().size() > 1); + assertNotEquals("Second request should be different", initialTime, os.getTime()); + } + }