I have an app that authenticates using OAuth2 and fetches data from a RESTful service using Retrofit. Now, I have the token retrieval and refreshing up and running. The token is refreshed like so (schedulers omitted):
// Each Retrofit call observable is "wrapper" using this method
protected <T> Observable<T> wrap(@NonNull final Observable<T> page) {
return authenticate()
.concatMap(token -> page)
.onErrorResumeNext(throwable -> {
Log.w(TAG, "wrap: ErrorResumeNext", throwable);
return refreshAccessToken()
.flatMap(accessToken -> page);
}));
}
// Retrieves the access token if necessary
Observable<AccessToken> authenticate() {
// Already have token
if(accessToken != null) return Observable.just(accessToken);
// No token yet, fetch it
return api.getAccessToken(...);
}
// Refreshes the token
Observable<AccessToken> refreshAccessToken() {
return api.refreshToken(...);
}
This works, but in some cases, multiple requests are sent at once and they both invoke the refreshing process - basically my app ends up refreshing the token as many times as there were requests at the moment.
So, the question is: How do I ensure that when the token needs to be refreshed, it is done only once, no matter how many ongoing requests require the token to be refreshed? Can I somehow make the other requests "wait" until the first request sucessfully invoked and retrieved the new token?