-
Notifications
You must be signed in to change notification settings - Fork 295
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
Analytics - only fetch config before flushing events cache #1337
Conversation
We could add a unit test like below, but I don't think it brings that much value. I think we should make a ticket for a holistic integration test for analytics, the batch POST, & the config GET. Open to folks opinions though.
|
I think in some functions, we call sendAnalytics event before the fetch function. So if tokenize is called immediately after BTAPIClient instantiation, we would have prefetch call from BTAPIClient instantiation and possibly fetch call from analytics. Correct me if I am wrong. We definitely want to move the first sendAnalyticsEvent call in tokenize functions in the fetch call completion handler. I know that batched call would introduce a delay, but it's hard to predict timing of these events especially with cache expiration. |
I'm not following this. This PR is really just a small change/fix. We never actually needed to fetch the config as early as we were before this PR (on each call to sendAnalyticsEvent). We only need the config value when we construct the batch of events to send to FPTI. This PR now only retrieves the config (ideally it's cached by now) before we're ready to batch upload our queue of analytic events. This batch happens on a 20 second timer. |
http?.post("v1/tracking/batch/events", parameters: postParameters) { _, _, _ in } | ||
await BTAnalyticsService.events.removeAll() | ||
do { | ||
let configuration = try await apiClient.fetchConfiguration() |
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.
Would we also want to consider setting a property for this in the class and using an if let
to continue to reuse the config if not nil? That could let us reuse the config for the entire flow vs fetching it every 20 seconds.
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.
The concern there is if the config had expired, we would be using an expired config
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 it's stored as a singleton in the ConfigurationCache
couldn't we check that? Psudocode but something like:
if let configuration, configuration = try? ConfigurationCache.shared.getFromCache(authorization: self.authorization.bearer)
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.
But honestly, does that even matter? Let's say a merchant uses our SDK with multiple merchantIDs (ie refreshing their clientToken would possible use a new merchantID). They would have to re-create a BTAPIClient with that refreshed clientToken which would create a new instance of BTAnalyticsService anyways.
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, but in cases where merchants don't, which I believe is more common, it would avoid an additional hop to fetchConfiguration
which while minor could reduce some latency. It is a take it or leave it comment so if you don't agree we don't need to implement it, was just asking a question.
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.
Oh weird! My comment "But honestly, does that even matter?" was in response to questioning my previous comment here 😆 . I must not have refreshed to see your comment, my apologies!
Since it's stored as a singleton in the ConfigurationCache couldn't we check that? Psudocode but something like:
We could but I don't think we want to leak logic of checking the config cache into the analytics layer. I think @richherrera is working on moving to the ConfigurationLoader pattern, like Android, which we can call in here once that's ready.
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.
Rich and I are pairing on working on the ConfigurationLoader pattern like you had suggested.
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 could but I don't think we want to leak logic of checking the config cache into the analytics layer. I think @richherrera is working on moving to the ConfigurationLoader pattern, like Android, which we can call in here once that's ready.
That makes sense, we can punt on it until the ConfigurationLoader pattern is established!
Co-authored-by: Jax DesMarais-Leder <[email protected]>
Yes, I understand that. I was just trying to understand the timeline of whether we are trying to make these calls less frequent or injecting config value into BTAnalyticsService as we discussed as a possibility for scenario in this PR: |
Like Rich called out, there is a problem with injecting it, since it could be expired. This PR is a simple fix that could help things. It doesn't change any public APIs within the SDK. |
Background
"core:api-request-latency"
analytics for the/v1/configuration
endpoint in FPTI, compared to the number of occurrences for each attempted payment method flow (see data below)/v1/configuration
, while another is in-flight, resulting in duplicate/overlapping requests.This PR reduces the number of calls to
BTAPIClient.fetchConfiguration()
in our Analytics layer. I don't know if this will solve 100% of the issue, but it should help.Changes
BTAPIClient.fetchConfiguration()
call inBTAnalyticsService
sendAnalyticsEvent()
method callChecklist
Authors
@scannillo