-
Notifications
You must be signed in to change notification settings - Fork 51
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 connection issue #791
fix connection issue #791
Conversation
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.
Could you explain the problem a bit more? I think I'm missing a bit of context here. Are we currently overwriting the ConnectionTokenCallback
instance when receiving more than one request? Is the ConnectionTokenCallback
implemented in native code (I couldn't find anything in the repo) or is it a react native component?
@@ -6,29 +6,43 @@ import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider | |||
import com.stripe.stripeterminal.external.models.ConnectionTokenException | |||
import com.stripeterminalreactnative.ReactExtensions.sendEvent | |||
import com.stripeterminalreactnative.ReactNativeConstants.FETCH_TOKEN_PROVIDER | |||
import java.util.UUID | |||
import kotlin.collections.HashMap | |||
|
|||
class TokenProvider(private val context: ReactApplicationContext) : ConnectionTokenProvider { | |||
private var connectionTokenCallback: ConnectionTokenCallback? = null |
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.
We should remove this instance property and make the callback a locally declared variable in setConnectionToken
below.
connectionTokenCallback = callback | ||
context.sendEvent(FETCH_TOKEN_PROVIDER.listenerName, null) | ||
val uuid = UUID.randomUUID().toString() | ||
callbackMap[uuid] = callback |
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 a bit worried that we add a ConnectionTokenCallback
instance to the map and never remove it. I imagine it's most likely the same instance over and over again but there's nothing that guarantees that. We could be causing a memory leak 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.
You are absolutely right. I didn't think enough about this situation. Do you think it's enough if I add a remove of the callback after calling once, since that every request of fectchConnectionToken
seems there must be a calling of setConnectionToken
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.
Yes, it will be fine if we remove it once we're done.
yes, user reported that the connecting the device on the first running of the app after installation would timeout, and connect successful after reopen the app. and we have some findings here https://docs.google.com/document/d/1PMfnDrshVFXo3H2WkPITNvGwMwkme0irJ482heOeq4w |
|
||
fun setConnectionToken(token: String?, error: String?) { | ||
fun setConnectionToken(token: String?, error: String?, callbackId: String?) { | ||
var connectionTokenCallback: ConnectionTokenCallback? = null |
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.
Nit: Maybe we can extract all the below duplicate call to init and remove here.
I understand the issue better now, thanks for the doc. If this code is being called from multiple threads it might be better to use a HashTable instead of a HashMap as the former is thread safe. I wonder if we could re-use the first token instead of fetching a new one by synchronizing the requests. In any case, this is good enough for now. Changes look good to me but I'll leave the final approval with @bric-stripe to double check the iOS side. |
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.
requesting changes to provide some logging if we can't map to a completion
ideally we wouldn't need the integration to deal with the callbackId. But I understand how things are now where setConnectionToken is a separate method so we need some way to connect the dots to call back in to the native SDK
ios/TokenProvider.swift
Outdated
let unwrappedToken = token ?? "" | ||
if (!unwrappedToken.isEmpty) { | ||
self.completionCallback?(token, nil) | ||
if let callbackId = callbackId { |
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.
since this function doesn't do anything if the callback id is nil or it doesn't have a matching completion, I suggest using a single check at the top that logs a message and early returns if things aren't as they should be:
guard let callbackId,
let completionCallback = self.callbackMap[callbackId] else {
print("⚠️ setConnectionToken requires the callbackId be set to the callbackId value provided to the tokenProviderHandler.")
return
}
otherwise it would fail silently which would likely be tricky for people to debug.
and something similar on the Android side
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.
ok, let me improve it.
Thanks, let me change to use a HashTable. |
Q: This might be off-topic and thread safe is definitely a good thing if we can't control the upstream, but I still like to clarify on the usage of HashTable. If the only purpose is thread safe, are we gonna consider to use ConcurrentHashMap instead? According to the HashTable javadoc, it should be a better option as far as I know. Ref: https://docs.oracle.com/javase/8/docs/api/java/util/Hashtable.html
|
Yeah, ConcurrentHashMap will work as well. We just need a data structure that can handle concurrency without issues. |
@nazli-stripe When can we expect the next release (v21) that will contain this fix? |
* fix connection issue on the first running. * fix lint and android unit-test issues. * optimize the codes. * optimize the codes. * optimize codes * fix android unit-test issue
Summary
fix connection issues with beta.20, improve the method of fetching and setting token.
Motivation
To fix the issues reported by users that connecting device would timeout on the first running after app installed.
Testing
Documentation
Select one: