Skip to content
This repository has been archived by the owner on Oct 26, 2024. It is now read-only.

Commit

Permalink
fix(YouTube - ReturnYouTubeDislike): Do not retry API call if same fe…
Browse files Browse the repository at this point in the history
…tch recently failed (#493)
  • Loading branch information
LisoUseInAIKyrios authored Oct 7, 2023
1 parent 78b5fe2 commit 486c894
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@

/**
* 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 {

Expand Down Expand Up @@ -435,10 +446,10 @@ public static void newVideoLoaded(@NonNull String videoId, boolean isShortsLitho
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,18 @@ public enum Vote {
* 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.
Expand Down Expand Up @@ -348,7 +354,7 @@ public static ReturnYouTubeDislike getFetchForVideoId(@Nullable String videoId)
}

ReturnYouTubeDislike fetch = fetchCache.get(videoId);
if (fetch == null || !fetch.futureInProgressOrFinishedSuccessfully()) {
if (fetch == null) {
fetch = new ReturnYouTubeDislike(videoId);
fetchCache.put(videoId, fetch);
}
Expand All @@ -374,7 +380,15 @@ private ReturnYouTubeDislike(@NonNull String videoId) {
}

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
Expand All @@ -389,8 +403,11 @@ public RYDVoteData getFetchData(long maxTimeToWait) {
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() {
Expand Down Expand Up @@ -493,13 +510,6 @@ private Spanned waitForFetchAndUpdateReplacementSpan(@NonNull Spanned original,
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 486c894

Please sign in to comment.