fix(YouTube - ReturnYouTubeDislike): Do not retry API call if same fetch recently failed (#493)

This commit is contained in:
LisoUseInAIKyrios 2023-10-07 23:06:10 +04:00 committed by GitHub
parent 78b5fe2128
commit 486c894257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 18 deletions

View File

@ -25,6 +25,17 @@ import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislik
/**
* Handles all interaction of UI patch components.
*
* Known limitation:
* Litho based Shorts player can experience temporarily frozen video playback if the RYD fetch takes too long.
*
* Temporary work around:
* Enable app spoofing to version 18.20.39 or older, as that uses a non litho Shorts player.
*
* Permanent fix (yet to be implemented), either of:
* - Modify patch to hook onto the Shorts Litho TextView, and update the dislikes asynchronously.
* - Find a way to force Litho to rebuild it's component tree
* (and use that hook to force the shorts dislikes to update after the fetch is completed).
*/
public class ReturnYouTubeDislikePatch {
@ -435,10 +446,10 @@ public class ReturnYouTubeDislikePatch {
lastLithoShortsVideoData = videoData;
lithoShortsShouldUseCurrentData = false;
} else {
// All other playback (including non-litho Shorts).
if (videoIdIsSame(currentVideoData, videoId)) {
return;
}
// All other playback (including litho Shorts).
currentVideoData = ReturnYouTubeDislike.getFetchForVideoId(videoId);
}

View File

@ -69,12 +69,18 @@ public class ReturnYouTubeDislike {
* Must be less than 5 seconds, as per:
* https://developer.android.com/topic/performance/vitals/anr
*/
private static final long MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH = 4000;
private static final long MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH = 4500;
/**
* How long to retain cached RYD fetches.
* How long to retain successful RYD fetches.
*/
private static final long CACHE_TIMEOUT_MILLISECONDS = 5 * 60 * 1000; // 5 Minutes
private static final long CACHE_TIMEOUT_SUCCESS_MILLISECONDS = 5 * 60 * 1000; // 5 Minutes
/**
* How long to retain unsuccessful RYD fetches,
* and also the minimum time before retrying again.
*/
private static final long CACHE_TIMEOUT_FAILURE_MILLISECONDS = 60 * 1000; // 1 Minute
/**
* Unique placeholder character, used to detect if a segmented span already has dislikes added to it.
@ -348,7 +354,7 @@ public class ReturnYouTubeDislike {
}
ReturnYouTubeDislike fetch = fetchCache.get(videoId);
if (fetch == null || !fetch.futureInProgressOrFinishedSuccessfully()) {
if (fetch == null) {
fetch = new ReturnYouTubeDislike(videoId);
fetchCache.put(videoId, fetch);
}
@ -374,7 +380,15 @@ public class ReturnYouTubeDislike {
}
private boolean isExpired(long now) {
return timeFetched != 0 && (now - timeFetched) > CACHE_TIMEOUT_MILLISECONDS;
final long timeSinceCreation = now - timeFetched;
if (timeSinceCreation < CACHE_TIMEOUT_FAILURE_MILLISECONDS) {
return false; // Not expired, even if the API call failed.
}
if (timeSinceCreation > CACHE_TIMEOUT_SUCCESS_MILLISECONDS) {
return true; // Always expired.
}
// Only expired if the fetch failed (API null response).
return (!fetchCompleted() || getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH) == null);
}
@Nullable
@ -389,8 +403,11 @@ public class ReturnYouTubeDislike {
return null;
}
private boolean futureInProgressOrFinishedSuccessfully() {
return !future.isDone() || getFetchData(MAX_MILLISECONDS_TO_BLOCK_UI_WAITING_FOR_FETCH) != null;
/**
* @return if the RYD fetch call has completed.
*/
public boolean fetchCompleted() {
return future.isDone();
}
private synchronized void clearUICache() {
@ -493,13 +510,6 @@ public class ReturnYouTubeDislike {
return original;
}
/**
* @return if the RYD fetch call has completed.
*/
public boolean fetchCompleted() {
return future.isDone();
}
public void sendVote(@NonNull Vote vote) {
ReVancedUtils.verifyOnMainThread();
Objects.requireNonNull(vote);

View File

@ -35,10 +35,10 @@ public class ReturnYouTubeDislikeApi {
private static final int API_GET_VOTES_TCP_TIMEOUT_MILLISECONDS = 2000;
/**
* {@link #fetchVotes(String)} HTTP read timeout
* To locally debug and force timeouts, change this to a very small number (ie: 100)
* {@link #fetchVotes(String)} HTTP read timeout.
* To locally debug and force timeouts, change this to a very small number (ie: 100)
*/
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 4000;
private static final int API_GET_VOTES_HTTP_TIMEOUT_MILLISECONDS = 5000;
/**
* Default connection and response timeout for voting and registration.