Skip to content

Commit 6389cb4

Browse files
authored
Merge pull request #14794 from woocommerce/woomob-1556-woo-poslocal-catalog-skip-background-full-sync-if-pos-was
[Woo POS][Local Catalog] Skip background full sync if POS has not been used recently
2 parents fced2f1 + f72077d commit 6389cb4

File tree

6 files changed

+115
-108
lines changed

6 files changed

+115
-108
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.woocommerce.android.ui.woopos.localcatalog
2+
3+
import javax.inject.Inject
4+
5+
class DateTimeProvider @Inject constructor() {
6+
fun now(): Long = System.currentTimeMillis()
7+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/localcatalog/WooPosLocalCatalogSyncWorker.kt

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import com.woocommerce.android.ui.woopos.featureflags.WooPosLocalCatalogM1Enable
1111
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
1212
import dagger.assisted.Assisted
1313
import dagger.assisted.AssistedInject
14+
import org.wordpress.android.fluxc.model.SiteModel
15+
import kotlin.time.Duration.Companion.milliseconds
1416

1517
@HiltWorker
1618
class WooPosLocalCatalogSyncWorker
@@ -21,37 +23,25 @@ constructor(
2123
@Assisted workerParams: WorkerParameters,
2224
private val accountRepository: AccountRepository,
2325
private val selectedSite: SelectedSite,
24-
private val syncRepository: WooPosLocalCatalogSyncRepository,
25-
private val logger: WooPosLogWrapper,
2626
private val featureFlagM1Enabled: WooPosLocalCatalogM1Enabled,
2727
private val preferencesRepository: WooPosPreferencesRepository,
28+
private val syncRepository: WooPosLocalCatalogSyncRepository,
29+
private val logger: WooPosLogWrapper,
30+
private val timeProvider: DateTimeProvider,
2831
) : CoroutineWorker(appContext, workerParams) {
2932

3033
companion object {
3134
const val WORK_NAME = "PosLocalCatalogSyncWork"
35+
private const val DAYS_SINCE_LAST_USE_THRESHOLD = 30L
3236
}
3337

3438
@Suppress("ReturnCount")
3539
override suspend fun doWork(): Result {
36-
if (!featureFlagM1Enabled.invoke()) {
37-
logger.d("Feature flag disabled, skipping local catalog sync")
38-
return Result.failure()
39-
}
40-
if (!accountRepository.isUserLoggedIn()) {
41-
logger.d("User not logged in, skipping local catalog sync")
42-
return Result.failure()
43-
}
44-
45-
val site = selectedSite.getOrNull()
46-
if (site == null) {
47-
logger.w("No selected WooCommerce site found, skipping local catalog sync")
48-
return Result.failure()
40+
if (isPosInactive()) {
41+
return Result.success()
4942
}
5043

51-
if (!preferencesRepository.isPeriodicSyncEnabledForSite(site.siteId)) {
52-
logger.w("Periodic sync permanently disabled for site ${site.url}, skipping local catalog sync.")
53-
return Result.failure()
54-
}
44+
val site = isCatalogSyncSupported() ?: return Result.failure()
5545

5646
logger.d("Starting FULL local catalog sync")
5747

@@ -87,4 +77,44 @@ constructor(
8777
}
8878
}
8979
}
80+
81+
private suspend fun isPosInactive(): Boolean {
82+
val lastUsedTimestamp = preferencesRepository.getLastUsedTimestamp() ?: return false
83+
val daysSinceLastUse = (timeProvider.now() - lastUsedTimestamp).milliseconds.inWholeDays
84+
return if (daysSinceLastUse > DAYS_SINCE_LAST_USE_THRESHOLD) {
85+
logger.d(
86+
"POS not used in the last $DAYS_SINCE_LAST_USE_THRESHOLD days " +
87+
"(last used $daysSinceLastUse days ago), skipping background full catalog sync."
88+
)
89+
true
90+
} else {
91+
false
92+
}
93+
}
94+
95+
@Suppress("ReturnCount")
96+
private suspend fun isCatalogSyncSupported(): SiteModel? {
97+
if (!featureFlagM1Enabled.invoke()) {
98+
logger.d("Feature flag disabled, skipping local catalog sync")
99+
return null
100+
}
101+
102+
if (!accountRepository.isUserLoggedIn()) {
103+
logger.d("User not logged in, skipping local catalog sync")
104+
return null
105+
}
106+
107+
val site = selectedSite.getOrNull()
108+
if (site == null) {
109+
logger.w("No selected WooCommerce site found, skipping local catalog sync")
110+
return null
111+
}
112+
113+
if (!preferencesRepository.isPeriodicSyncEnabledForSite(site.siteId)) {
114+
logger.w("Periodic sync permanently disabled for site ${site.url}, skipping local catalog sync.")
115+
return null
116+
}
117+
118+
return site
119+
}
90120
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/splash/WooPosSplashViewModel.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.woocommerce.android.ui.woopos.tab.WooPosCanBeLaunchedInTab
1111
import com.woocommerce.android.ui.woopos.tab.WooPosLaunchability
1212
import com.woocommerce.android.ui.woopos.util.analytics.WooPosAnalyticsEvent.Event.Loaded
1313
import com.woocommerce.android.ui.woopos.util.analytics.WooPosAnalyticsTracker
14+
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
1415
import dagger.hilt.android.lifecycle.HiltViewModel
1516
import kotlinx.coroutines.flow.FlowCollector
1617
import kotlinx.coroutines.flow.MutableStateFlow
@@ -28,6 +29,7 @@ class WooPosSplashViewModel @Inject constructor(
2829
private val posCanBeLaunchedInTab: WooPosCanBeLaunchedInTab,
2930
private val ordersCache: WooPosOrdersInMemoryCache,
3031
private val performInitialFullSync: WooPosPerformLocalCatalogInitialFullSync,
32+
private val preferencesRepository: WooPosPreferencesRepository,
3133
) : ViewModel() {
3234
private val _state = MutableStateFlow<WooPosSplashState>(WooPosSplashState.Loading)
3335
val state: StateFlow<WooPosSplashState> = _state
@@ -36,6 +38,8 @@ class WooPosSplashViewModel @Inject constructor(
3638
val splashScreenStartTime = System.currentTimeMillis()
3739

3840
viewModelScope.launch {
41+
preferencesRepository.setLastUsedTimestamp()
42+
3943
val launchability = posCanBeLaunchedInTab()
4044

4145
if (launchability is WooPosLaunchability.NotLaunchable) {

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosPreferencesRepository.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.datastore.core.DataStore
44
import androidx.datastore.preferences.core.Preferences
55
import androidx.datastore.preferences.core.booleanPreferencesKey
66
import androidx.datastore.preferences.core.edit
7+
import androidx.datastore.preferences.core.longPreferencesKey
78
import androidx.datastore.preferences.core.stringPreferencesKey
89
import com.woocommerce.android.tools.SelectedSite
910
import kotlinx.coroutines.flow.Flow
@@ -18,6 +19,7 @@ class WooPosPreferencesRepository @Inject constructor(
1819
private val recentProductSearchesSiteSpecificKey = buildSiteSpecificKey(RECENT_PRODUCT_SEARCHES_KEY)
1920
private val recentCouponSearchesSiteSpecificKey = buildSiteSpecificKey(RECENT_COUPON_SEARCHES_KEY)
2021
private val wasOpenedOnceKey = booleanPreferencesKey(POS_WAS_OPENED_ONCE_KEY)
22+
private val lastUsedTimestampKey = longPreferencesKey(POS_LAST_USED_TIMESTAMP_KEY)
2123
private val allowCellularDataUpdateKey = booleanPreferencesKey(ALLOW_FULL_SYNC_ON_CELLULAR_DATA_KEY)
2224

2325
val recentProductSearches: Flow<List<String>> = dataStore.data
@@ -76,6 +78,18 @@ class WooPosPreferencesRepository @Inject constructor(
7678
}
7779
}
7880

81+
suspend fun setLastUsedTimestamp(timestamp: Long = System.currentTimeMillis()) {
82+
dataStore.edit { preferences ->
83+
preferences[lastUsedTimestampKey] = timestamp
84+
}
85+
}
86+
87+
suspend fun getLastUsedTimestamp(): Long? {
88+
return dataStore.data.map { preferences ->
89+
preferences[lastUsedTimestampKey]
90+
}.first()
91+
}
92+
7993
suspend fun setAllowCellularDataUpdate(allow: Boolean) {
8094
dataStore.edit { preferences ->
8195
preferences[allowCellularDataUpdateKey] = allow
@@ -104,6 +118,7 @@ class WooPosPreferencesRepository @Inject constructor(
104118
const val RECENT_PRODUCT_SEARCHES_KEY = "recent_product_searches_key"
105119
const val RECENT_COUPON_SEARCHES_KEY = "recent_coupon_searches_key"
106120
const val POS_WAS_OPENED_ONCE_KEY = "pos_was_opened_once_key"
121+
const val POS_LAST_USED_TIMESTAMP_KEY = "pos_last_used_timestamp_key"
107122
const val ALLOW_FULL_SYNC_ON_CELLULAR_DATA_KEY = "allow_full_sync_on_cellular_data_key"
108123

109124
const val MAX_RECENT_SEARCHES_COUNT = 10

0 commit comments

Comments
 (0)