-
Notifications
You must be signed in to change notification settings - Fork 627
Enable request limiter for CreateInstallation, GenerateAuthToken request calls. #2003
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Binary Size ReportAffected SDKs
Test Logs
NotesHead commit (2c8d6f45) is created by Prow via merging commits: 1443ac5 91ca982. |
Coverage ReportAffected SDKs
Test Logs
NotesHTML coverage reports can be produced locally with Head commit (2c8d6f45) is created by Prow via merging commits: 1443ac5 91ca982. |
@@ -132,7 +132,7 @@ public Thread newThread(Runnable r) { | |||
new FirebaseInstallationServiceClient( | |||
firebaseApp.getApplicationContext(), publisher, heartbeatInfo), | |||
new PersistedInstallation(firebaseApp), | |||
new Utils(), | |||
Utils.getInstance(), | |||
new IidStore(firebaseApp), | |||
new RandomFidGenerator()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does RandomFidGenerator needs to be instantiated?
Usually I would assume, because a RandomNumberGenerator has to be injected, but that does not seem to be the case.
Thus, can we use the methods of this class statically?
As a more general note:
For general code design it would be better if there was a FIS model class that would represent FIDs and also carry methods like generating a random FID.
No action item! I just wanted to leave this comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(fyi: this was not addressed or acknowledged)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acknowledged. I will address this in a following PR.
firebase-installations/src/main/java/com/google/firebase/installations/Utils.java
Outdated
Show resolved
Hide resolved
firebase-installations/src/main/java/com/google/firebase/installations/Utils.java
Show resolved
Hide resolved
@@ -112,6 +115,7 @@ public FirebaseInstallationServiceClient( | |||
this.context = context; | |||
this.userAgentPublisher = publisher; | |||
this.heartbeatInfo = heartbeatInfo; | |||
this.requestLimiter = new RequestLimiter(Utils.getInstance()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to pass the Utils parameter?
Since there is only one Utils instance, RequestLimiter should be able to access that instance itself and does not need to be passed a Utils instance.
Maybe the Utils parameter can be optional?
Not saying that it's better! Just thinking out loud! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional not supported due to minSDK version.
This is for testing this class easily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "optional" I mean that you have 2 constructors, one with Utils
parameter, one without.
The constructor without Utils
parameter just calls Utils.getInstance()
, so we don't need this implementation detail here.
@@ -143,7 +147,7 @@ public InstallationResponse createFirebaseInstallation( | |||
String resourceName = String.format(CREATE_REQUEST_RESOURCE_NAME_FORMAT, projectID); | |||
int retryCount = 0; | |||
URL url = getFullyQualifiedRequestUri(resourceName); | |||
while (retryCount <= MAX_RETRIES) { | |||
while (requestLimiter.isRequestAllowed() || shouldServerErrorRetry) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
When we should not send requests to the server, we throw a FirebaseInstallationsException
with message "Firebase Installations Service is unavailable."? Is that correct and desired behavior?
If yes, why not throw this exception before the while loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Changed it to throw the exception before the loop.
Now about the desired behavior: We should throw an exception. But I am unclear if it should state "Firebase Installations Service is unavailable". WDYT?
...rc/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
Show resolved
Hide resolved
retryCount++; | ||
shouldServerErrorRetry = retryCount <= MAX_RETRIES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I like this code!
There is several things wrong with this I think:
a) When I read the While loop condition above, it is unclear to me what shouldServerErrorRetry
is and I have to search the code to find where the variable is set.
b) If avoidable (which is almost always the case) local variables should not change in value, because it makes code hard to read - this is actually a great example why. If you have to do it at all costs, you should mark the local variable as @Var
.
c) I just realize it's not a local variable, but an instance variable. Why is that? That is even more confusing to me. Are you saying that other parallel processes can change the value of the variable and affect this while loop? (c.1) I doubt that this is the case. (c.2) And if it's the case, I doubt that it's a good idea!
d) I also liked using a variable named retryCount
in the while loop condition better than a variable called shouldServerErrorRetry
... With the retryCount
it is immediately obvious, that we will retry sending the same request for some times... shouldServerErrorRetry
does not really give that much information.
I recommend:
Leave the retryCount <= MAX_RETRIES
in the while loop.
Even better, get rid of the while loop and replace it with a for (int retryCount = 0; retryCount <= MAX_RETRIES; retryCount++)
.
That explains so much better what is happening here than a local variable that is changed somewhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed it . PTAL.
...rc/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
Show resolved
Hide resolved
...rc/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java
Outdated
Show resolved
Hide resolved
...ase-installations/src/main/java/com/google/firebase/installations/remote/RequestLimiter.java
Outdated
Show resolved
Hide resolved
/test smoke-tests |
/test device-check-changed |
…o enableRequestLimiter
/test smoke-tests |
/test device-check-changed |
@@ -132,7 +132,7 @@ public Thread newThread(Runnable r) { | |||
new FirebaseInstallationServiceClient( | |||
firebaseApp.getApplicationContext(), publisher, heartbeatInfo), | |||
new PersistedInstallation(firebaseApp), | |||
new Utils(), | |||
Utils.getInstance(), | |||
new IidStore(firebaseApp), | |||
new RandomFidGenerator()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(fyi: this was not addressed or acknowledged)
firebase-installations/src/main/java/com/google/firebase/installations/Utils.java
Outdated
Show resolved
Hide resolved
firebase-installations/src/main/java/com/google/firebase/installations/Utils.java
Outdated
Show resolved
Hide resolved
@@ -112,6 +115,7 @@ public FirebaseInstallationServiceClient( | |||
this.context = context; | |||
this.userAgentPublisher = publisher; | |||
this.heartbeatInfo = heartbeatInfo; | |||
this.requestLimiter = new RequestLimiter(Utils.getInstance()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "optional" I mean that you have 2 constructors, one with Utils
parameter, one without.
The constructor without Utils
parameter just calls Utils.getInstance()
, so we don't need this implementation detail here.
…o enableRequestLimiter
…o enableRequestLimiter
@ankitaj224: The following test failed, say
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
Preventing erroneous requests.