Skip to content

Commit b53ce80

Browse files
ivolivol
authored andcommitted
Clarify behaviour of gating for failure fetches
1 parent ea1ef4b commit b53ce80

1 file changed

Lines changed: 13 additions & 9 deletions

File tree

approov-service/src/main/java/io/approov/service/retrofit/ApproovService.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ public class ApproovService {
121121
private static long cachedFailureTimeMs = 0;
122122
private static long failureCacheTtlMs = 500; // 0.5 seconds default
123123

124-
// Gate lock for the SDK fetch call. When the failure cache is empty, only ONE thread
125-
// enters the SDK; all others wait on this lock and then re-check the cache.
124+
// Gate lock for the SDK fetch call. When the service-layer failure cache is empty,
125+
// only ONE thread enters the SDK; all others wait on this lock and then re-check
126+
// the failure cache. This collapses concurrent failure storms that the SDK does
127+
// not cache, while successful fetches use the SDK's own cache/fast path.
126128
// This is separate from failureCacheLock to avoid holding the cache lock during
127129
// the potentially long (~1-3s) SDK network call.
128130
private static final Object fetchGateLock = new Object();
@@ -256,7 +258,8 @@ public static void setFailureCacheTtlMs(long ttlMs) {
256258
}
257259

258260
/**
259-
* Caches a failure result. Only failure statuses are cached; success is never cached.
261+
* Caches a failure result. Only failure statuses are cached by this service layer;
262+
* success caching is handled by the SDK.
260263
*/
261264
static void cacheFailureIfNeeded(Approov.TokenFetchResult result) {
262265
switch (result.getStatus()) {
@@ -271,7 +274,7 @@ static void cacheFailureIfNeeded(Approov.TokenFetchResult result) {
271274
}
272275
break;
273276
default:
274-
// Success and other statuses are never cached
277+
// Success and other statuses are not cached by this service layer.
275278
break;
276279
}
277280
}
@@ -284,8 +287,9 @@ static void cacheFailureIfNeeded(Approov.TokenFetchResult result) {
284287
* wait, then re-check the cache. This collapses N concurrent SDK calls into 1 when
285288
* the platform is in a failure state (MITM, no network, etc.).
286289
* <p>
287-
* On the happy path (SDK returns a valid token), no caching occurs and the gate
288-
* is released immediately — subsequent threads each get their own unique token.
290+
* On the happy path (SDK returns a valid token), this service layer does not
291+
* cache the result. Subsequent threads still pass through the gate, but the SDK
292+
* is expected to serve successful follow-up fetches from its own cache/fast path.
289293
*
290294
* @param url the URL to fetch the token for
291295
* @return the token fetch result (from cache or fresh SDK call)
@@ -297,7 +301,7 @@ static Approov.TokenFetchResult fetchApproovTokenWithGate(String url) {
297301
return cached;
298302
}
299303

300-
// 2. Slow path — gate ensures only one thread calls the SDK
304+
// 2. Slow path — gate ensures only one thread refreshes the failure state
301305
synchronized (fetchGateLock) {
302306
// Double-check: another thread may have populated the cache while we waited
303307
cached = getCachedFailure();
@@ -310,7 +314,7 @@ static Approov.TokenFetchResult fetchApproovTokenWithGate(String url) {
310314
Log.d(TAG, "gate: fetching token for " + url);
311315
Approov.TokenFetchResult result = Approov.fetchApproovTokenAndWait(url);
312316

313-
// Cache only failures; success tokens are unique per-request
317+
// Cache only failures here; success caching is handled inside the SDK.
314318
cacheFailureIfNeeded(result);
315319
return result;
316320
}
@@ -1203,7 +1207,7 @@ public Response intercept(Chain chain) throws IOException {
12031207

12041208
// Fetch token using double-checked locking on the failure cache.
12051209
// Fast path: cached failure returned immediately (no lock).
1206-
// Slow path: gate ensures only one thread calls the SDK; others wait and re-check.
1210+
// Slow path: gate ensures only one thread refreshes failure state; others wait and re-check.
12071211
Approov.TokenFetchResult approovResults = ApproovService.fetchApproovTokenWithGate(url.toString());
12081212

12091213
// provide information about the obtained token or error (note "approov token -check" can

0 commit comments

Comments
 (0)