Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class ConfigAutoFetch {
private final ScheduledExecutorService scheduledExecutorService;
private final Random random;
private final Clock clock;
private final ConfigSharedPrefsClient sharedPrefsClient;
private boolean isInBackground;

public ConfigAutoFetch(
Expand All @@ -67,7 +68,8 @@ public ConfigAutoFetch(
ConfigCacheClient activatedCache,
Set<ConfigUpdateListener> eventListeners,
ConfigUpdateListener retryCallback,
ScheduledExecutorService scheduledExecutorService) {
ScheduledExecutorService scheduledExecutorService,
ConfigSharedPrefsClient sharedPrefsClient) {
this.httpURLConnection = httpURLConnection;
this.configFetchHandler = configFetchHandler;
this.activatedCache = activatedCache;
Expand All @@ -76,12 +78,12 @@ public ConfigAutoFetch(
this.scheduledExecutorService = scheduledExecutorService;
this.random = new Random();
this.isInBackground = false;
this.sharedPrefsClient = sharedPrefsClient;
clock = DefaultClock.getInstance();
}

// Increase the backoff duration with a new end time based on Retry Interval
private synchronized void updateBackoffMetadataWithRetryInterval(
int realtimeRetryInterval, ConfigSharedPrefsClient sharedPrefsClient) {
private synchronized void updateBackoffMetadataWithRetryInterval(int realtimeRetryInterval) {
Date currentTime = new Date(clock.currentTimeMillis());
long backoffDurationInMillis = realtimeRetryInterval * 1000L;
Date backoffEndTime = new Date(currentTime.getTime() + backoffDurationInMillis);
Expand Down Expand Up @@ -123,7 +125,7 @@ private String parseAndValidateConfigUpdateMessage(String message) {

// Check connection and establish InputStream
@VisibleForTesting
public void listenForNotifications(ConfigSharedPrefsClient sharedPrefsClient) {
public void listenForNotifications() {
if (httpURLConnection == null) {
return;
}
Expand All @@ -133,7 +135,7 @@ public void listenForNotifications(ConfigSharedPrefsClient sharedPrefsClient) {
InputStream inputStream = null;
try {
inputStream = httpURLConnection.getInputStream();
handleNotifications(inputStream, sharedPrefsClient);
handleNotifications(inputStream);
} catch (IOException ex) {
// If the real-time connection is at an unexpected lifecycle state when the app is
// backgrounded, it's expected closing the httpURLConnection will throw an exception.
Expand All @@ -155,8 +157,7 @@ public void listenForNotifications(ConfigSharedPrefsClient sharedPrefsClient) {
}

// Auto-fetch new config and execute callbacks on each new message
private void handleNotifications(
InputStream inputStream, ConfigSharedPrefsClient sharedPrefsClient) throws IOException {
private void handleNotifications(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader((new InputStreamReader(inputStream, "utf-8")));
String partialConfigUpdateMessage;
String currentConfigUpdateMessage = "";
Expand Down Expand Up @@ -209,9 +210,13 @@ private void handleNotifications(
}
}

// This field in the response indicates that the realtime request has exceeded the
// project's quota. It will retry after the specified interval to establish a long-lived
// connection. This interval extends the backoff duration without affecting the number of
// retries, so it will not enter an exponential backoff state.
if (jsonObject.has(REALTIME_RETRY_INTERVAL)) {
int realtimeRetryInterval = jsonObject.getInt(REALTIME_RETRY_INTERVAL);
updateBackoffMetadataWithRetryInterval(realtimeRetryInterval, sharedPrefsClient);
updateBackoffMetadataWithRetryInterval(realtimeRetryInterval);
}
} catch (JSONException ex) {
// Message was mangled up and so it was unable to be parsed. User is notified of this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,8 @@ public void onError(@NonNull FirebaseRemoteConfigException error) {
activatedCache,
listeners,
retryCallback,
scheduledExecutorService);
scheduledExecutorService,
sharedPrefsClient);
}

// HTTP status code that the Realtime client should retry on.
Expand Down Expand Up @@ -554,7 +555,7 @@ public void beginRealtimeHttpStream() {

// Start listening for realtime notifications.
configAutoFetch = startAutoFetch(httpURLConnection);
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();
}
} catch (IOException e) {
if (isInBackground) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ public void onError(@NonNull FirebaseRemoteConfigException error) {
mockActivatedCache,
listeners,
mockRetryListener,
scheduledExecutorService);
scheduledExecutorService,
sharedPrefsClient);
configAutoFetch.setIsInBackground(false);
realtimeSharedPrefsClient =
new ConfigSharedPrefsClient(
Expand Down Expand Up @@ -1286,7 +1287,7 @@ public void realtime_stream_listen_and_end_connection() throws Exception {
when(mockFetchHandler.fetchNowWithTypeAndAttemptNumber(
ConfigFetchHandler.FetchType.REALTIME, 1))
.thenReturn(Tasks.forResult(realtimeFetchedContainerResponse));
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(inputStreamSpy, times(2)).close();
}
Expand All @@ -1299,7 +1300,7 @@ public void realtime_fetchesWithoutChangedParams_doesNotCallOnUpdate() throws Ex
"{ \"latestTemplateVersionNumber\": 1 }".getBytes(StandardCharsets.UTF_8)));
when(mockFetchHandler.getTemplateVersionNumber()).thenReturn(1L);
when(mockFetchHandler.fetch(0)).thenReturn(Tasks.forResult(firstFetchedContainerResponse));
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verifyNoInteractions(mockOnUpdateListener);
}
Expand Down Expand Up @@ -1339,7 +1340,7 @@ public void realtime_okStatusCode_startAutofetchAndRetries() throws Exception {
configRealtimeHttpClientSpy.beginRealtimeHttpStream();
flushScheduledTasks();

verify(mockConfigAutoFetch).listenForNotifications(any());
verify(mockConfigAutoFetch).listenForNotifications();
verify(configRealtimeHttpClientSpy).retryHttpConnectionWhenBackoffEnds();
}

Expand Down Expand Up @@ -1490,7 +1491,7 @@ public void realtime_stream_listen_and_failsafe_enabled() throws Exception {
new ByteArrayInputStream(
"{ \"featureDisabled\": true }".getBytes(StandardCharsets.UTF_8)));
when(mockFetchHandler.getTemplateVersionNumber()).thenReturn(1L);
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(mockRetryListener).onError(any(FirebaseRemoteConfigServerException.class));
verify(mockFetchHandler, never()).fetch(0);
Expand All @@ -1508,7 +1509,7 @@ public void realtime_stream_listen_and_failsafe_disabled() throws Exception {
when(mockFetchHandler.fetchNowWithTypeAndAttemptNumber(
ConfigFetchHandler.FetchType.REALTIME, 1))
.thenReturn(Tasks.forResult(realtimeFetchedContainerResponse));
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(mockUnavailableEventListener, never())
.onError(any(FirebaseRemoteConfigServerException.class));
Expand Down Expand Up @@ -1546,7 +1547,7 @@ public void realtimeStreamListen_andUnableToParseMessage() throws Exception {
when(mockFetchHandler.fetchNowWithTypeAndAttemptNumber(
ConfigFetchHandler.FetchType.REALTIME, 1))
.thenReturn(Tasks.forResult(realtimeFetchedContainerResponse));
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(mockInvalidMessageEventListener).onError(any(FirebaseRemoteConfigClientException.class));
}
Expand All @@ -1564,7 +1565,7 @@ public void realtime_updatesBackoffMetadataWithProvidedRetryInterval() throws Ex
expectedRetryInterval)
.getBytes(StandardCharsets.UTF_8)));
when(mockFetchHandler.getTemplateVersionNumber()).thenReturn(1L);
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(sharedPrefsClient, times(1)).setRealtimeBackoffEndTime(any());
}
Expand All @@ -1579,7 +1580,7 @@ public void realtime_stream_listen_get_inputstream_fail() throws Exception {
when(mockFetchHandler.fetchNowWithTypeAndAttemptNumber(
ConfigFetchHandler.FetchType.REALTIME, 1))
.thenReturn(Tasks.forResult(realtimeFetchedContainerResponse));
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(inputStream).close();
}
Expand All @@ -1589,7 +1590,7 @@ public void realtime_stream_listen_get_inputstream_exception_handling() throws E
InputStream inputStream = mock(InputStream.class);
when(mockHttpURLConnection.getResponseCode()).thenReturn(200);
when(mockHttpURLConnection.getInputStream()).thenThrow(IOException.class);
configAutoFetch.listenForNotifications(sharedPrefsClient);
configAutoFetch.listenForNotifications();

verify(mockHttpURLConnection, times(1)).getInputStream();
verify(inputStream, never()).close();
Expand Down
Loading