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

Feature/6618 limit stats refresh #7411

Merged
merged 33 commits into from
Oct 6, 2022

Conversation

JorgeMucientes
Copy link
Contributor

@JorgeMucientes JorgeMucientes commented Sep 17, 2022

⚠️ Do not merge until FluxC changes are merged

Part of: #6618

Description

wc-analytics endpoint is one of the slowest endpoints we hit from the app, and is one that we hit a lot. We fetch site stats and top performers every time we open My Store tab and when we change between tabs. This translates into the "slow/endless loading" perception of the app. This PR alongside changes applied in this other PR in woocommerce-android aims to reduce that loading "slowness" for top performer products data and provide better offline support with the following changes:

  • Migrate top performers cache to Room to easily expose an observable
  • Simplify top performers cached model to avoid having to parse multiple JSON or query different sql tables to load top performers from cache.
  • Invalidate top performers cache when a new order is placed
  • Invalidate top performers cache after 1h. Maybe this is to often? please share your thoughts

Finally, I updated all broken unit tests, remove some that did not apply anymore, and added a couple more.

Testing instructions

Log into the app and check the following:

  • Top performers are loaded correctly for all stats granularities
  • Top performers are invalidated when a new order notification is received. Check for logcat messageInvalidating top performer products after receiving the notification
  • Check that after data is invalidated when changing stat granularity, the data is fetched from API and refeshed accordingly with new values.. See the log fetchLeaderboards is displayed in logcat as well as notice how the top performer list is refershed
  • Check that once all 4 tabs data is loaded at least once, switching between tabs doesn't trigger fetching data from API. Basically, check that fetchLeaderboards is never called
  • Check that after swipe to refresh is called, then switching between tabs will refresh data fro API
  • Check that when we try to refresh top performer data without connectivity, when connectivity is back (enable/disable airplane mode for example) the top performer list is refreshed with data from API.

…/woocommerce/woocommerce-android into feature/6618-limit-stats-refresh

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/mystore/MyStoreViewModel.kt
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/mystore/data/StatsRepository.kt
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/mystore/domain/GetTopPerformers.kt
@JorgeMucientes JorgeMucientes added the status: do not merge Dependent on another PR, ready for review but not ready for merge. label Sep 17, 2022
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Sep 17, 2022

You can test the changes on this Pull Request by downloading an installable build, or scanning this QR code:

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/mystore/data/StatsRepository.kt
#	build.gradle
@codecov-commenter
Copy link

codecov-commenter commented Sep 25, 2022

Codecov Report

Base: 44.10% // Head: 44.10% // Increases project coverage by +0.00% 🎉

Coverage data is based on head (f7f592a) compared to base (9ee1e74).
Patch coverage: 66.66% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff            @@
##              trunk    #7411   +/-   ##
=========================================
  Coverage     44.10%   44.10%           
- Complexity     3286     3290    +4     
=========================================
  Files           582      582           
  Lines         33126    33146   +20     
  Branches       4306     4310    +4     
=========================================
+ Hits          14609    14620   +11     
- Misses        17184    17188    +4     
- Partials       1333     1338    +5     
Impacted Files Coverage Δ
...ommerce/android/ui/mystore/data/StatsRepository.kt 3.77% <0.00%> (-0.03%) ⬇️
...woocommerce/android/ui/mystore/MyStoreViewModel.kt 76.52% <80.00%> (-2.78%) ⬇️
...erce/android/ui/mystore/domain/GetTopPerformers.kt 93.10% <91.66%> (-0.23%) ⬇️
...ommerce/android/push/NotificationMessageHandler.kt 66.66% <100.00%> (+0.38%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@JorgeMucientes JorgeMucientes marked this pull request as ready for review October 3, 2022 10:50
@hichamboushaba hichamboushaba self-assigned this Oct 5, 2022
Copy link
Member

@hichamboushaba hichamboushaba left a comment

Choose a reason for hiding this comment

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

Thanks for working on this @JorgeMucientes, the code looks good, but there is a minor issue, please check the comments, and let me know what you think.

refreshStoreStats[index] = true
private fun observeTopPerformerUpdates() {
viewModelScope.launch {
_activeStatsGranularity.collectLatest { granularity ->
Copy link
Member

Choose a reason for hiding this comment

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

np, flatMapLatest would fit the need here better than collectLatest, as it allows transforming items of the Flow receive (granulity) into another Flow (DB Results).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense! I have updated it here

Comment on lines 271 to 272
isLoading = false,
isError = false,
Copy link
Member

Choose a reason for hiding this comment

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

Setting isLoading is problematic, it'll cause this behavior:

screen-20221005-153227.mp4

The first loading of top performers of the Year tab didn't have any loading indicator.

I think the change should be part of loadTopPerformersStats, as it's the one that decides whether we need the loading state or not, WDYT?
I think the same applies for isError even though it doesn't seem to cause any visible issues in the current status, but it'll be more consistent, and respects the responsibilities better.

Copy link
Contributor Author

@JorgeMucientes JorgeMucientes Oct 6, 2022

Choose a reason for hiding this comment

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

Well spotted! I've removed isLoading or isError state updates done from observeTopPerformerUpdates function. This fixes the issue and also makes de loading behaviour more consistent across forced updates.
Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

Thanks @JorgeMucientes for making the change.
For the isError, I belive we still miss one case, we don't reset it to false after the loading, so in case of an error, it would stuck in the true state forever, do you think we should update it in the onSuccess here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yes, completely right @hichamboushaba

I decided to update it when we set the isLoading to true. Basically, because that way we ensure those 2 states are mutually exclusive and if someone decides to change the order of this code inside MyStoreFragment putting isError before isLoading, we'd still see the loading state:

        viewModel.topPerformersState.observe(viewLifecycleOwner) { topPerformers ->
            when {
                topPerformers.isError -> showTopPerformersError()
                topPerformers.isLoading -> showTopPerformersLoading()
                else -> showTopPerformers(topPerformers.topPerformers)
            }
        }

@peril-woocommerce
Copy link

peril-woocommerce bot commented Oct 6, 2022

Warnings
⚠️ PR is missing at least one label.

Generated by 🚫 dangerJS

@JorgeMucientes JorgeMucientes added this to the 10.7 milestone Oct 6, 2022
@wpmobilebot
Copy link
Collaborator

Found 1 violations:

The PR caused the following dependency changes:

expand

-+--- org.wordpress:fluxc:trunk-87eadb05bd327745850ff8accf8ca4dbaa03cece
-|    +--- org.wordpress:wellsql:1.7.0
-|    |    \--- org.wordpress.wellsql:wellsql-annotations:1.7.0
-|    +--- org.wordpress.fluxc:fluxc-annotations:trunk-87eadb05bd327745850ff8accf8ca4dbaa03cece
-|    +--- org.greenrobot:eventbus:3.3.1 (*)
-|    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.9.3 (*)
-|    +--- com.android.volley:volley:1.1.1 -> 1.2.0
-|    +--- androidx.paging:paging-runtime:2.1.2
-|    |    +--- androidx.paging:paging-common:2.1.2
-|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.4.0 (*)
-|    |    |    \--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
-|    |    +--- androidx.arch.core:core-runtime:2.0.0 -> 2.1.0 (*)
-|    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.5.1 (*)
-|    |    +--- androidx.lifecycle:lifecycle-livedata:2.0.0 -> 2.5.1 (*)
-|    |    \--- androidx.recyclerview:recyclerview:1.0.0 -> 1.2.1 (*)
-|    +--- com.goterl:lazysodium-android:5.0.2
-|    +--- net.java.dev.jna:jna:5.5.0
-|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10 -> 1.6.21 (*)
-|    +--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.6.10
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.6.10 -> 1.6.21 (*)
-|    +--- androidx.appcompat:appcompat:1.0.2 -> 1.4.2 (*)
-|    +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.2.1 (*)
-|    +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.3.3
-|    |    \--- androidx.annotation:annotation:1.2.0 -> 1.4.0 (*)
-|    +--- com.squareup.okhttp3:okhttp-urlconnection:4.9.0
-|    |    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.9.3 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10 -> 1.6.21 (*)
-|    +--- com.google.code.gson:gson:2.8.5 -> 2.9.0
-|    +--- org.apache.commons:commons-text:1.1 -> 1.8 (*)
-|    +--- androidx.room:room-runtime:2.4.2 (*)
-|    +--- androidx.room:room-ktx:2.4.2
-|    |    +--- androidx.room:room-common:2.4.2 (*)
-|    |    +--- androidx.room:room-runtime:2.4.2 (*)
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.6.10 -> 1.6.21 (*)
-|    |    \--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2 -> 1.6.4 (*)
-|    +--- com.google.dagger:dagger:2.42
-|    |    \--- javax.inject:javax.inject:1
-|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9 -> 1.6.4 (*)
-|    \--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9 -> 1.6.4 (*)
++--- org.wordpress:fluxc:trunk-6459816749ce343afcc072dba807f24db1164966
+|    +--- org.wordpress:wellsql:1.7.0
+|    |    \--- org.wordpress.wellsql:wellsql-annotations:1.7.0
+|    +--- org.wordpress.fluxc:fluxc-annotations:trunk-6459816749ce343afcc072dba807f24db1164966
+|    +--- org.greenrobot:eventbus:3.3.1 (*)
+|    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.9.3 (*)
+|    +--- com.android.volley:volley:1.1.1 -> 1.2.0
+|    +--- androidx.paging:paging-runtime:2.1.2
+|    |    +--- androidx.paging:paging-common:2.1.2
+|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.4.0 (*)
+|    |    |    \--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
+|    |    +--- androidx.arch.core:core-runtime:2.0.0 -> 2.1.0 (*)
+|    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.5.1 (*)
+|    |    +--- androidx.lifecycle:lifecycle-livedata:2.0.0 -> 2.5.1 (*)
+|    |    \--- androidx.recyclerview:recyclerview:1.0.0 -> 1.2.1 (*)
+|    +--- com.goterl:lazysodium-android:5.0.2
+|    +--- net.java.dev.jna:jna:5.5.0
+|    +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10 -> 1.6.21 (*)
+|    +--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.6.10
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib:1.6.10 -> 1.6.21 (*)
+|    +--- androidx.appcompat:appcompat:1.0.2 -> 1.4.2 (*)
+|    +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.2.1 (*)
+|    +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.3.3
+|    |    \--- androidx.annotation:annotation:1.2.0 -> 1.4.0 (*)
+|    +--- com.squareup.okhttp3:okhttp-urlconnection:4.9.0
+|    |    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.9.3 (*)
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10 -> 1.6.21 (*)
+|    +--- com.google.code.gson:gson:2.8.5 -> 2.9.0
+|    +--- org.apache.commons:commons-text:1.1 -> 1.8 (*)
+|    +--- androidx.room:room-runtime:2.4.2 (*)
+|    +--- androidx.room:room-ktx:2.4.2
+|    |    +--- androidx.room:room-common:2.4.2 (*)
+|    |    +--- androidx.room:room-runtime:2.4.2 (*)
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.6.10 -> 1.6.21 (*)
+|    |    \--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2 -> 1.6.4 (*)
+|    +--- com.google.dagger:dagger:2.42
+|    |    \--- javax.inject:javax.inject:1
+|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9 -> 1.6.4 (*)
+|    \--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9 -> 1.6.4 (*)
-\--- org.wordpress.fluxc.plugins:woocommerce:trunk-87eadb05bd327745850ff8accf8ca4dbaa03cece
-     +--- org.wordpress:wellsql:1.7.0 (*)
-     +--- org.wordpress.fluxc:fluxc-annotations:trunk-87eadb05bd327745850ff8accf8ca4dbaa03cece
-     +--- androidx.room:room-ktx:2.4.2 (*)
-     +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10 -> 1.6.21 (*)
-     +--- org.wordpress:fluxc:trunk-87eadb05bd327745850ff8accf8ca4dbaa03cece (*)
-     +--- org.apache.commons:commons-lang3:3.7 -> 3.9
-     +--- com.google.code.gson:gson:2.8.5 -> 2.9.0
-     +--- com.google.dagger:dagger:2.42 (*)
-     +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9 -> 1.6.4 (*)
-     +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9 -> 1.6.4 (*)
-     \--- androidx.room:room-runtime:2.4.2 (*)
+\--- org.wordpress.fluxc.plugins:woocommerce:trunk-6459816749ce343afcc072dba807f24db1164966
+     +--- org.wordpress:wellsql:1.7.0 (*)
+     +--- org.wordpress.fluxc:fluxc-annotations:trunk-6459816749ce343afcc072dba807f24db1164966
+     +--- androidx.room:room-ktx:2.4.2 (*)
+     +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10 -> 1.6.21 (*)
+     +--- org.wordpress:fluxc:trunk-6459816749ce343afcc072dba807f24db1164966 (*)
+     +--- org.apache.commons:commons-lang3:3.7 -> 3.9
+     +--- com.google.code.gson:gson:2.8.5 -> 2.9.0
+     +--- com.google.dagger:dagger:2.42 (*)
+     +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9 -> 1.6.4 (*)
+     +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9 -> 1.6.4 (*)
+     \--- androidx.room:room-runtime:2.4.2 (*)

Please review and act accordingly

Copy link
Member

@hichamboushaba hichamboushaba left a comment

Choose a reason for hiding this comment

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

Nice work @JorgeMucientes.

This can be merged after fixing the merge conflicts.

@hichamboushaba hichamboushaba merged commit 8cf276c into trunk Oct 6, 2022
@hichamboushaba hichamboushaba deleted the feature/6618-limit-stats-refresh branch October 6, 2022 15:25
@hichamboushaba hichamboushaba removed the status: do not merge Dependent on another PR, ready for review but not ready for merge. label Oct 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants