Skip to content

Conversation

@toupper
Copy link
Contributor

@toupper toupper commented Sep 4, 2025

Description

Closes WOOMOB-1145

With this PR, we add an in-memory cache when fetching the POS Orders. The cache content is removed when leaving POS.

Steps to reproduce

  1. Open the app.
  2. Navigate to POS.
  3. Go to Orders.
  4. Confirm that a loading state is shown while the orders are being fetched.
  5. Once the orders are fetched, they are displayed.
  6. Return to the POS home, then go back to Orders.
  7. Confirm that cached orders are shown immediately (no loading state). Once the new fetch completes, the list refreshes.
  8. Exit POS.
  9. Open POS again and go to Orders.
  10. Confirm that, since cached orders are cleared on exit, the loading state is shown first, followed by the fetched orders.

Testing information

Tested on Samsung Tab A8 Android 14

Images/gif

Screen_Recording_20250904_120742_Woo.Dev.mp4
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

toupper added 13 commits August 29, 2025 11:09
…nto feat/WOOMOB-1145-pos-historical-orders-in-memory-cache

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersDataSource.kt
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersViewModel.kt
…eat/WOOMOB-1145-pos-historical-orders-in-memory-cache

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersDataSource.kt
…eat/WOOMOB-1145-pos-historical-orders-in-memory-cache

# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersDataSource.kt
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersViewModel.kt
@toupper toupper added this to the 23.2 milestone Sep 4, 2025
@toupper toupper requested a review from kidinov September 4, 2025 10:16
@toupper toupper added the type: task An internally driven task. label Sep 4, 2025
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Sep 4, 2025

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App Name WooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commit9720e3c
Direct Downloadwoocommerce-wear-prototype-build-pr14569-9720e3c.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Sep 4, 2025

📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App Name WooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commit9720e3c
Direct Downloadwoocommerce-prototype-build-pr14569-9720e3c.apk

@kidinov kidinov self-assigned this Sep 5, 2025
private val mutex = Mutex()

companion object {
private const val INITIAL_CAPACITY = MAX_CACHE_SIZE
Copy link
Contributor

@kidinov kidinov Sep 5, 2025

Choose a reason for hiding this comment

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

As the goal is to have this equal to the page size, I think we should reference the same constant used in WooPosOrdersDataSource and here.

Maybe adding const val ORDERS_PAGE_SIZE = 25 to WooPosOrdersDataSource.kt and then

private const val INITIAL_CAPACITY = ORDERS_PAGE_SIZE

?

@@ -0,0 +1,41 @@
package com.woocommerce.android.ui.woopos.common.data
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to place it into woopos.orders. The product-related code here is because it's used in the list and the search.


private val ordersCache = LinkedHashMap<Long, Order>(INITIAL_CAPACITY, LOAD_FACTOR, true)

override suspend fun addAll(orders: List<Order>) = mutex.withLock {
Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed on the call, this should probably be setAll that just replaces all you have in the cache with the new list.

private const val LOAD_FACTOR = 0.75f
}

private val ordersCache = LinkedHashMap<Long, Order>(INITIAL_CAPACITY, LOAD_FACTOR, true)
Copy link
Contributor

Choose a reason for hiding this comment

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

Any specific reason to use hash map here? I think we can have just a list of orders here

}

override fun onDestroy() {
runBlocking {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure about that for 2 reasons:

  • You are blocking the main thread here
  • Overall, are you sure that we want to clean the cache here? Keep in mind that on Android, activity can be destroyed on configuration change. I wouldn't do that at all, especially since currently there are up to 25 orders in memory

Copy link
Contributor Author

@toupper toupper Sep 5, 2025

Choose a reason for hiding this comment

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

Thanks for the comment @kidinov!

You are blocking the main thread here

If we do it asynchronously, we lose the reference to the cache, so we end up not deleting the cache.

Overall, are you sure that we want to clean the cache here? Keep in mind that on Android, activity can be destroyed on configuration change. I wouldn't do that at all, especially since currently there are up to 25 orders in memory

What other place would be more suitable for this action?

_state.update {
it.copy(
isLoading = false,
error = result.message ?: "Unknown error"
Copy link
Contributor

Choose a reason for hiding this comment

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

Just keep in mind to not show this error to a user, as this won't be localized

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, and btw message is never null so ?: "Unknown error" not needed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Awesome, I removed it 👍

}

private suspend fun List<OrderEntity>.toAppModels(): List<Order> = map {
private suspend fun List<OrderEntity>?.toAppModels(): List<Order> = this?.map {
Copy link
Contributor

@kidinov kidinov Sep 5, 2025

Choose a reason for hiding this comment

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

I’m a bit confused about this change. I thought the list here was always non-nullable, right?


import com.woocommerce.android.model.Order

interface WooPosOrdersCache {
Copy link
Contributor

Choose a reason for hiding this comment

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

np: I think we don't really need an interface here. For the products, it was introduced because we were planning to migrate to persistent storage; therefore, we declared one interface with potential for two implementations. Here, at least for now, there are no plans for that, so maybe keeping it simple would be easier.

Copy link
Contributor

@kidinov kidinov left a comment

Choose a reason for hiding this comment

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

LGTM. I left a few comments; please take a look!

@wpmobilebot wpmobilebot modified the milestones: 23.2, 23.3 Sep 5, 2025
@wpmobilebot
Copy link
Collaborator

Version 23.2 has now entered code-freeze, so the milestone of this PR has been updated to 23.3.

@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 48.71795% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.99%. Comparing base (13b352d) to head (9720e3c).
⚠️ Report is 245 commits behind head on trunk.

Files with missing lines Patch % Lines
.../android/ui/woopos/orders/WooPosOrdersViewModel.kt 0.00% 18 Missing ⚠️
.../android/ui/woopos/splash/WooPosSplashViewModel.kt 33.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##              trunk   #14569   +/-   ##
=========================================
  Coverage     37.99%   37.99%           
- Complexity     9450     9453    +3     
=========================================
  Files          2040     2041    +1     
  Lines        114311   114328   +17     
  Branches      15162    15162           
=========================================
+ Hits          43430    43443   +13     
- Misses        66900    66902    +2     
- Partials       3981     3983    +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@toupper toupper merged commit 08931bc into trunk Sep 5, 2025
17 checks passed
@toupper toupper deleted the feat/WOOMOB-1145-pos-historical-orders-in-memory-cache branch September 5, 2025 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: task An internally driven task.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants