Skip to content
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

Implement Thread Safe Credential Manager #542

Merged
merged 9 commits into from
Feb 25, 2022
Merged

Conversation

poovamraj
Copy link
Contributor

Changes

Please describe both what is changing and why this is important. Include:

  • Added an Executor to BaseCredentialsManager
  • This executor is provided with a single-threaded ExecutorService
  • getCredentials methods are run over this executor
  • saveCredentials method in SecureCredentialsManager is made @Synchronized to avoid race conditions

References

#540, #330, #359

Testing

The existing Unit Tests are provided with proper mocks and fixed to accommodate current changes. Apart from that, manual testing is done where multiple threads try to access the above methods with RTR enabled

@poovamraj poovamraj requested a review from a team as a code owner February 16, 2022 10:12
Copy link
Contributor

@stevehobbsdev stevehobbsdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's doing the right things but needs a review from a more Kotlin/Android person as well. Reviewed the non-Code content though and left some comments 👍🏻

@stevehobbsdev stevehobbsdev requested a review from a team February 18, 2022 10:52
poovamraj and others added 2 commits February 18, 2022 16:26
…ecureCredentialsManager.kt

Co-authored-by: Steve Hobbs <steve.hobbs@auth0.com>
@adamjmcgrath
Copy link
Contributor

adamjmcgrath commented Feb 18, 2022

lgtm (from what I can understand about ExecutorService)

Apart from that, manual testing is done where multiple threads try to access the above methods with RTR enabled

Can you not create a test like this one on Android?

@poovamraj
Copy link
Contributor Author

@adamjmcgrath I checked to solve this for some time and looks like there is not a straightforward way currently to unit test a multi-threaded code in JUnit.

Although I have used Reflections (metadata information) to unit test if the saveCredentials is marked as synchronized so as to avoid accidentally removing it. I couldn't find a straightforward way for getCredentials method

@poovamraj
Copy link
Contributor Author

@lbalmaceda One thing I would like to bring to notice is the addition of a new Executor parameter to the BaseCredentialsManager's constructor. This should be considered a breaking change, but we are planning to release this in a minor version. Would like to know if this could affect the library users much?

Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@poovamraj I see with these changes now the developer is required to pass the executor instance. I wonder if customizing that instance the "most typical use case" or if this can be set internally and so avoid having to change the constructor signatures.

*/
public abstract class BaseCredentialsManager internal constructor(
protected val authenticationClient: AuthenticationAPIClient,
protected val storage: Storage,
private val jwtDecoder: JWTDecoder
private val jwtDecoder: JWTDecoder,
protected val serialExecutor: Executor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this breaking change can be avoided if a new/secondary constructor is defined instead keeping the old signature. For that, you'd need to have a "default executor" instance to use when one is not set by the dev.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lbalmaceda Instead of making it a secondary constructor I have implemented it as a setter similar to _clock member. This way the user can modify it for testing purposes.

* [SecureCredentialsManager] are executed synchronously to avoid racing conditions. Current usage
* is only around the [getCredentials] method but it can be used in future for others.
*/
public fun setExecutor(executor: Executor) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments on this. This base abstract class is supposed to work as an interface for implementations to follow. I wouldn't add mentions to those implementations in the javadoc, as this base class "doesn't know them".

I noticed that this class is keeping the executor instance but doesn't use it at all -- It only allows to set or get the instance. To me, seems like this instance belongs somewhere else. Perhaps on the classes that implement this one, even if that's repeating that small setter piece of code (because the getter will not be required).

Also, if this is meant to be used by devs for testing purposes only, why not make this function use the "internal" modifier instead? Less chances that someone would override it on production by mistake.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @lbalmaceda, I agree with you on this and exposed the executor through an internal constructor and made it private.

@poovamraj poovamraj merged commit 3ea50a3 into main Feb 25, 2022
@poovamraj poovamraj added this to the 2.7.0 milestone Feb 25, 2022
@poovamraj poovamraj mentioned this pull request Feb 25, 2022
@poovamraj poovamraj deleted the thread-safe-cred-manager branch July 18, 2023 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants