Skip to content

Commit

Permalink
Deduplicate status and cleared calls in ErrorRequestCoordinator
Browse files Browse the repository at this point in the history
Previously we'd let both the the primary and the error request notify when the status of a request changes (ie cleared -> running). That would lead to duplicate running calls, once for the primary request, then when it failed, again for the error request.

This change also relaxes the requirements for canSetImage to be either request because we only ever run one at a time. It also simplifies canNotifyCleared to just the primary. For notifyCleared we just need one or the other request to do it, it doesn't particularly matter which one. There's no defined agreement over whether the primary's placehodler will be used, or the error if both have placeholders. Using the primary's always seems more coherent.
  • Loading branch information
sjudd committed Aug 16, 2022
1 parent f714343 commit 5c232dd
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ public boolean isEquivalentTo(Request o) {
@Override
public boolean canSetImage(Request request) {
synchronized (requestLock) {
return parentCanSetImage() && isValidRequest(request);
// Only one of primary or error runs at a time, so if we've reached this point and nothing
// else is broken, we should have nothing else to enforce.
return parentCanSetImage();
}
}

Expand All @@ -114,14 +116,14 @@ private boolean parentCanSetImage() {
@Override
public boolean canNotifyStatusChanged(Request request) {
synchronized (requestLock) {
return parentCanNotifyStatusChanged() && isValidRequest(request);
return parentCanNotifyStatusChanged() && isValidRequestForStatusChanged(request);
}
}

@Override
public boolean canNotifyCleared(Request request) {
synchronized (requestLock) {
return parentCanNotifyCleared() && isValidRequest(request);
return parentCanNotifyCleared() && request.equals(primary);
}
}

Expand All @@ -136,9 +138,17 @@ private boolean parentCanNotifyStatusChanged() {
}

@GuardedBy("requestLock")
private boolean isValidRequest(Request request) {
return request.equals(primary)
|| (primaryState == RequestState.FAILED && request.equals(error));
private boolean isValidRequestForStatusChanged(Request request) {
if (primaryState != RequestState.FAILED) {
return request.equals(primary);
} else {
return request.equals(error)
// We don't want to call onLoadStarted once for the primary request and then again
// if it fails and the error request starts. It's already running, so we might as well
// avoid the duplicate notification by only notifying about the error state when it's
// final.
&& (errorState == RequestState.SUCCESS || errorState == RequestState.FAILED);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,6 @@ public void canSetImage_withNotFailedPrimary_andNullParent_returnsTrue() {
assertThat(coordinator.canSetImage(primary)).isTrue();
}

@Test
public void canSetImage_withError_andNullParent_andNotFailedPrimary_returnsFalse() {
assertThat(coordinator.canSetImage(error)).isFalse();
}

@Test
public void canSetImage_withNotFailedPrimary_parentCanSetImage_returnsTrue() {
coordinator = newCoordinator(parent);
Expand Down Expand Up @@ -309,9 +304,17 @@ public void canNotifyStatusChanged_withError_notFailedPrimary_nullParent_returns
}

@Test
public void canNotifyStatusChanged_withError_failedPrimary_nullParent_returnsTrue() {
public void canNotifyStatusChanged_withErrorRequest_failedPrimary_nullParent_errorIsNotFailed_returnsFalse() {
coordinator.onRequestFailed(primary);

assertThat(coordinator.canNotifyStatusChanged(error)).isFalse();
}

@Test
public void canNotifyStatusChanged_withErrorRequest_failedPrimary_nullParent_failedError_returnsTrue() {
coordinator.onRequestFailed(primary);
coordinator.onRequestFailed(error);

assertThat(coordinator.canNotifyStatusChanged(error)).isTrue();
}

Expand All @@ -325,15 +328,27 @@ public void canNotifyStatusChanged_withError_failedPrimary_nonNullParentCantNoti
}

@Test
public void canNotifyStatusChanged_withError_failedPrimary_nonNullParentCanNotify_returnsTrue() {
public void canNotifyStatusChanged_withError_failedPrimary_notFailedError_nonNullParentCanNotify_returnsFalse() {
coordinator = newCoordinator(parent);
coordinator.setRequests(primary, error);
coordinator.onRequestFailed(primary);
when(parent.canNotifyStatusChanged(coordinator)).thenReturn(true);

assertThat(coordinator.canNotifyStatusChanged(primary)).isTrue();
assertThat(coordinator.canNotifyStatusChanged(error)).isFalse();
}

@Test
public void canNotifyStatusChanged_withError_failedPrimary_failedError_nonNullParentCanNotify_returnsTrue() {
coordinator = newCoordinator(parent);
coordinator.setRequests(primary, error);
coordinator.onRequestFailed(primary);
when(parent.canNotifyStatusChanged(coordinator)).thenReturn(true);
coordinator.onRequestFailed(error);

assertThat(coordinator.canNotifyStatusChanged(error)).isTrue();
}


@Test
public void isAnyResourceSet_primaryNotSet_nullParent_returnsFalse() {
assertThat(coordinator.isAnyResourceSet()).isFalse();
Expand Down Expand Up @@ -532,9 +547,19 @@ public void canNotifyCleared_errorRequest_nullParent_returnsFalse() {
}

@Test
public void canNotifyCleared_errorRequest_primaryFailed_nullParent_returnsTrue() {
public void canNotifyCleared_errorRequest_primaryFailed_nullParent_returnsFalse() {
coordinator.onRequestFailed(primary);
assertThat(coordinator.canNotifyCleared(error)).isTrue();
assertThat(coordinator.canNotifyCleared(error)).isFalse();
}

@Test
public void canNotifyCleared_primaryRequest_primaryFailed_nonNullParentCanNotNotify_returnsFalse() {
coordinator = newCoordinator(parent);
coordinator.setRequests(primary, error);
when(parent.canNotifyCleared(coordinator)).thenReturn(false);
coordinator.onRequestFailed(primary);

assertThat(coordinator.canNotifyCleared(primary)).isFalse();
}

@Test
Expand All @@ -548,13 +573,23 @@ public void canNotifyCleared_errorRequest_primaryFailed_nonNullParentCanNotNotif
}

@Test
public void canNotifyCleared_errorRequest_primaryFailed_nonNullParentCanNotify_returnsTrue() {
public void canNotifyCleared_errorRequest_primaryFailed_nonNullParentCanNotify_returnsFalse() {
coordinator = newCoordinator(parent);
coordinator.setRequests(primary, error);
when(parent.canNotifyCleared(coordinator)).thenReturn(true);
coordinator.onRequestFailed(primary);

assertThat(coordinator.canNotifyCleared(error)).isTrue();
assertThat(coordinator.canNotifyCleared(error)).isFalse();
}

@Test
public void canNotifyCleared_primaryRequest_primaryFailed_nonNullParentCanNotify_returnsTrue() {
coordinator = newCoordinator(parent);
coordinator.setRequests(primary, error);
when(parent.canNotifyCleared(coordinator)).thenReturn(true);
coordinator.onRequestFailed(primary);

assertThat(coordinator.canNotifyCleared(primary)).isTrue();
}

private static ErrorRequestCoordinator newCoordinator() {
Expand Down

0 comments on commit 5c232dd

Please sign in to comment.