Skip to content

Commit 7c9d7ed

Browse files
smilesa-maurice
authored andcommitted
Added token fetch retry logic for Instance ID
PiperOrigin-RevId: 249115561
1 parent 53c2fff commit 7c9d7ed

File tree

2 files changed

+56
-20
lines changed

2 files changed

+56
-20
lines changed

app/instance_id/instance_id_desktop_impl.cc

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#include <assert.h>
1818

19+
#include <algorithm>
20+
1921
#include "app/instance_id/iid_data_generated.h"
2022
#include "app/rest/transport_curl.h"
2123
#include "app/rest/transport_interface.h"
@@ -104,10 +106,35 @@ static const char kTokenResetError[] = "RST";
104106
// Wildcard scope used to delete all tokens and the ID in a server registration.
105107
static const char kWildcardTokenScope[] = "*";
106108

109+
// Minimum retry time (in seconds) when a fetch token request fails.
110+
static const uint64_t kMinimumFetchTokenDelaySec = 30;
111+
// Maximum retry time (in seconds) when a fetch token request fails.
112+
static const uint64_t kMaximumFetchTokenDelaySec =
113+
8 * firebase::internal::kMinutesPerHour *
114+
firebase::internal::kSecondsPerMinute;
115+
107116
std::map<App*, InstanceIdDesktopImpl*>
108117
InstanceIdDesktopImpl::instance_id_by_app_; // NOLINT
109118
Mutex InstanceIdDesktopImpl::instance_id_by_app_mutex_; // NOLINT
110119

120+
void InstanceIdDesktopImpl::FetchServerTokenCallback::Run() {
121+
bool retry;
122+
bool fetched_token = iid_->FetchServerToken(scope_.c_str(), &retry);
123+
if (fetched_token) {
124+
iid_->ref_future()->CompleteWithResult(
125+
future_handle_, kErrorNone, "", iid_->FindCachedToken(scope_.c_str()));
126+
} else if (retry) {
127+
// Retry with an expodential backoff.
128+
retry_delay_time_ =
129+
std::min(std::max(retry_delay_time_ * 2, kMinimumFetchTokenDelaySec),
130+
kMaximumFetchTokenDelaySec);
131+
iid_->scheduler_.Schedule(this, retry_delay_time_);
132+
} else {
133+
iid_->ref_future()->Complete(future_handle_, kErrorUnknownError,
134+
"FetchToken failed");
135+
}
136+
}
137+
111138
InstanceIdDesktopImpl::InstanceIdDesktopImpl(App* app)
112139
: storage_semaphore_(0),
113140
app_(app),
@@ -267,22 +294,7 @@ Future<std::string> InstanceIdDesktopImpl::GetToken(const char* scope) {
267294
ref_future()->Complete(handle, kErrorShutdown,
268295
"Failed due to App shutdown in progress");
269296
} else {
270-
std::string scope_str(scope);
271-
auto callback = NewCallback(
272-
[](InstanceIdDesktopImpl* _this, std::string _scope_str,
273-
SafeFutureHandle<std::string> _handle) {
274-
if (_this->FetchServerToken(_scope_str.c_str())) {
275-
_this->ref_future()->CompleteWithResult(
276-
_handle, kErrorNone, "",
277-
_this->FindCachedToken(_scope_str.c_str()));
278-
} else {
279-
_this->ref_future()->Complete(_handle, kErrorUnknownError,
280-
"FetchToken failed");
281-
}
282-
},
283-
this, scope_str, handle);
284-
285-
scheduler_.Schedule(callback);
297+
scheduler_.Schedule(new FetchServerTokenCallback(this, scope, handle));
286298
}
287299

288300
return MakeFuture(ref_future(), handle);
@@ -666,7 +678,8 @@ void InstanceIdDesktopImpl::ServerTokenOperation(
666678
network_operation_complete_.Wait();
667679
}
668680

669-
bool InstanceIdDesktopImpl::FetchServerToken(const char* scope) {
681+
bool InstanceIdDesktopImpl::FetchServerToken(const char* scope, bool* retry) {
682+
*retry = false;
670683
if (terminating_ || !InitialOrRefreshCheckin()) return false;
671684

672685
// If we already have a token, don't refresh.
@@ -707,9 +720,9 @@ bool InstanceIdDesktopImpl::FetchServerToken(const char* scope) {
707720
std::string error_component =
708721
error.substr(component_start, component_end - component_start);
709722
if (error_component == kPhoneRegistrationError) {
710-
// TODO(smiles): Retry with expodential backoff.
711723
network_operation_.reset(nullptr);
712-
return true;
724+
*retry = true;
725+
return false;
713726
} else if (error_component == kTokenResetError) {
714727
// Server requests that the token is reset.
715728
DeleteServerToken(nullptr, true);

app/instance_id/instance_id_desktop_impl.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <string>
2121

2222
#include "app/memory/unique_ptr.h"
23+
#include "app/src/callback.h"
2324
#include "app/src/future_manager.h"
2425
#include "app/src/include/firebase/app.h"
2526
#include "app/src/include/firebase/future.h"
@@ -134,6 +135,26 @@ class InstanceIdDesktopImpl {
134135
uint64_t last_checkin_time_ms;
135136
};
136137

138+
// Fetches a token with expodential backoff using the scheduler.
139+
class FetchServerTokenCallback : public callback::Callback {
140+
public:
141+
FetchServerTokenCallback(InstanceIdDesktopImpl* iid,
142+
const std::string& scope,
143+
SafeFutureHandle<std::string> future_handle)
144+
: iid_(iid),
145+
scope_(scope),
146+
future_handle_(future_handle),
147+
retry_delay_time_(0) {}
148+
149+
void Run() override;
150+
151+
private:
152+
InstanceIdDesktopImpl* iid_;
153+
std::string scope_;
154+
SafeFutureHandle<std::string> future_handle_;
155+
uint64_t retry_delay_time_;
156+
};
157+
137158
explicit InstanceIdDesktopImpl(App* app);
138159

139160
// Get future manager of this object
@@ -184,7 +205,9 @@ class InstanceIdDesktopImpl {
184205

185206
// Fetch a token from the cache or retrieve a new token from the server.
186207
// The scope can be either "FCM" or "*" for remote config and other users.
187-
bool FetchServerToken(const char* scope);
208+
// retry is set to "true" if the server response requires a retry with
209+
// exponential back-off.
210+
bool FetchServerToken(const char* scope, bool* retry);
188211

189212
// Delete a server-side token for a scope and remove it from the cache.
190213
// If delete_id is true all tokens are deleted along with the server

0 commit comments

Comments
 (0)