-
Notifications
You must be signed in to change notification settings - Fork 659
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
Fix issues with CustomerSession listeners #856
Conversation
87f4a6c
to
0902651
Compare
0902651
to
401c90b
Compare
**Motivation** The previous implementation of `CustomerSession` listeners had a reference to a single `CustomerRetrievalListener` and `SourceRetrievalListener`. After a listener is called, it would be nulled out. This logic was buggy because it resulted in possible race conditions in which two calls are both in flight, and the first call that completes nulls out the listener for the second. **Summary** The solution to this issue is to associate an `operationId` (i.e. UUID) with each listener. This avoids the race condition and ambiguity about which listener is being referenced. Additionally, the listeners were being held with a strong reference, which could lead to memory leaks if the listener held a reference to an Activity. **Testing** Manually verified with samplestore and example apps.
401c90b
to
4107a3e
Compare
@@ -327,19 +354,23 @@ long getCustomerCacheTime() { | |||
private void addCustomerSource( | |||
@NonNull final Context context, | |||
@NonNull final CustomerEphemeralKey key, | |||
@Nullable final String operationId, |
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 to me to stick this argument on the end to match the API of the other functions
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.
Done
@@ -81,8 +84,10 @@ | |||
@Nullable private Customer mCustomer; | |||
private long mCustomerCacheTime; | |||
@Nullable private Context mContext; | |||
@Nullable private CustomerRetrievalListener mCustomerRetrievalListener; | |||
@Nullable private SourceRetrievalListener mSourceRetrievalListener; | |||
@NonNull private final Map<String, WeakReference<CustomerRetrievalListener>> |
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 there really a need for weakreferences here? I'm concerned it would bring back that issue of listeners getting garbage collected, and I don't see these leaking any contexts
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.
These listeners can have references to Activity contexts (see PaymentMethodsActivity
), so they should be WeakReferences to avoid memory leaks. We'll monitor new reports of GC issues.
Motivation
The previous implementation of
CustomerSession
listenershad a reference to a single
CustomerRetrievalListener
andSourceRetrievalListener
. After a listener is called, itwould be nulled out.
This logic was buggy because it resulted in possible race
conditions in which two calls are both in flight, and the
first call that completes nulls out the listener for the
second.
Summary
The solution to this issue is to associate an
operationId
(i.e. UUID) with each listener. This avoids the race condition
and ambiguity about which listener is being referenced.
Additionally, the listeners were being held with a strong
reference, which could lead to memory leaks if the listener
held a reference to an Activity.
Testing
Manually verified with samplestore and example apps.