-
Notifications
You must be signed in to change notification settings - Fork 134
[POS][Local Catalog] Repo for incremental sync timestamps #14511
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
Open
samiuelson
wants to merge
9
commits into
trunk
Choose a base branch
from
pos-local-catalog-sync-timestamp-repo
base: trunk
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+403
−0
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
102bce9
Create repository for sync timestamps
samiuelson b844fa6
Add layer for processing String <-> Date (de)serialization
samiuelson be5980d
Handle null site case
samiuelson 35b6cd1
Improve data parsing exception handling
samiuelson 1ce3f7a
Remove Singleton annotations
samiuelson 9553a2e
Add tests
samiuelson 0e9c15e
Make date parser strict
samiuelson 544baa7
Store timestamp instead of string date
malinajirka a2d9caf
Update tests
malinajirka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
...ain/kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosSyncTimestampManager.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package com.woocommerce.android.ui.woopos.util.datastore | ||
|
||
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper | ||
import java.time.Instant | ||
import java.time.LocalDateTime | ||
import java.time.ZoneOffset | ||
import java.time.format.DateTimeFormatter | ||
import java.time.format.DateTimeParseException | ||
import java.util.Locale | ||
import javax.inject.Inject | ||
|
||
class WooPosSyncTimestampManager @Inject constructor( | ||
private val timestampRepository: WooPosSyncTimestampRepository, | ||
private val logger: WooPosLogWrapper | ||
) { | ||
private val gmtFormatter = DateTimeFormatter.ofPattern(GMT_DATE_FORMAT, Locale.US).withZone(ZoneOffset.UTC) | ||
|
||
suspend fun storeProductsLastSyncTimestamp(timestamp: Long) { | ||
timestampRepository.storeProductsLastSyncTimestamp(timestamp) | ||
} | ||
|
||
suspend fun getProductsLastSyncTimestamp(): Long? = timestampRepository.getProductsLastSyncTimestamp() | ||
|
||
suspend fun clearProductsLastSyncTimestamp() = timestampRepository.clearProductsLastSyncTimestamp() | ||
|
||
suspend fun storeVariationsLastSyncTimestamp(timestamp: Long) = | ||
timestampRepository.storeVariationsLastSyncTimestamp(timestamp) | ||
|
||
suspend fun getVariationsLastSyncTimestamp(): Long? = timestampRepository.getVariationsLastSyncTimestamp() | ||
|
||
suspend fun clearVariationsLastSyncTimestamp() { | ||
timestampRepository.clearVariationsLastSyncTimestamp() | ||
} | ||
|
||
suspend fun clearAllSyncTimestamps() { | ||
timestampRepository.clearAllSyncTimestamps() | ||
} | ||
|
||
fun formatTimestampForApi(timestamp: Long): String { | ||
return gmtFormatter.format(Instant.ofEpochMilli(timestamp)) | ||
} | ||
|
||
fun parseTimestampFromApi(dateFromApi: String): Long? { | ||
return parseGmtTimestamp(dateFromApi) | ||
} | ||
|
||
private fun parseGmtTimestamp(dateFromApi: String): Long? { | ||
return try { | ||
val localDateTime = LocalDateTime.parse(dateFromApi, gmtFormatter) | ||
return localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli() | ||
} catch (e: DateTimeParseException) { | ||
logger.e("Failed to parse GMT timestamp: '$dateFromApi'", e) | ||
kidinov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
null | ||
} | ||
} | ||
|
||
private companion object { | ||
const val GMT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss" | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
.../kotlin/com/woocommerce/android/ui/woopos/util/datastore/WooPosSyncTimestampRepository.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package com.woocommerce.android.ui.woopos.util.datastore | ||
|
||
import androidx.datastore.core.DataStore | ||
import androidx.datastore.preferences.core.Preferences | ||
import androidx.datastore.preferences.core.edit | ||
import androidx.datastore.preferences.core.stringPreferencesKey | ||
import com.woocommerce.android.tools.SelectedSite | ||
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper | ||
import kotlinx.coroutines.flow.first | ||
import javax.inject.Inject | ||
|
||
class WooPosSyncTimestampRepository @Inject constructor( | ||
private val selectedSite: SelectedSite, | ||
private val dataStore: DataStore<Preferences>, | ||
private val logger: WooPosLogWrapper | ||
) { | ||
|
||
suspend fun storeProductsLastSyncTimestamp(timestamp: Long) { | ||
val key = buildSiteSpecificKey(PRODUCTS_TIMESTAMP_KEY) | ||
if (key != null) { | ||
dataStore.edit { preferences -> | ||
preferences[key] = timestamp.toString() | ||
} | ||
} | ||
} | ||
|
||
suspend fun getProductsLastSyncTimestamp(): Long? { | ||
val key = buildSiteSpecificKey(PRODUCTS_TIMESTAMP_KEY) | ||
return if (key != null) { | ||
dataStore.data.first()[key]?.toLong() | ||
} else { | ||
null | ||
} | ||
} | ||
|
||
suspend fun clearProductsLastSyncTimestamp() { | ||
val key = buildSiteSpecificKey(PRODUCTS_TIMESTAMP_KEY) | ||
if (key != null) { | ||
dataStore.edit { preferences -> | ||
preferences.remove(key) | ||
} | ||
} | ||
} | ||
|
||
suspend fun storeVariationsLastSyncTimestamp(timestamp: Long) { | ||
val key = buildSiteSpecificKey(VARIATIONS_TIMESTAMP_KEY) | ||
if (key != null) { | ||
dataStore.edit { preferences -> | ||
preferences[key] = timestamp.toString() | ||
} | ||
} | ||
} | ||
|
||
suspend fun getVariationsLastSyncTimestamp(): Long? { | ||
val key = buildSiteSpecificKey(VARIATIONS_TIMESTAMP_KEY) | ||
return if (key != null) { | ||
dataStore.data.first()[key]?.toLong() | ||
} else { | ||
null | ||
} | ||
} | ||
|
||
suspend fun clearVariationsLastSyncTimestamp() { | ||
val key = buildSiteSpecificKey(VARIATIONS_TIMESTAMP_KEY) | ||
if (key != null) { | ||
dataStore.edit { preferences -> | ||
preferences.remove(key) | ||
} | ||
} | ||
} | ||
|
||
suspend fun clearAllSyncTimestamps() { | ||
val productsKey = buildSiteSpecificKey(PRODUCTS_TIMESTAMP_KEY) | ||
val variationsKey = buildSiteSpecificKey(VARIATIONS_TIMESTAMP_KEY) | ||
|
||
if (productsKey != null && variationsKey != null) { | ||
dataStore.edit { preferences -> | ||
preferences.remove(productsKey) | ||
preferences.remove(variationsKey) | ||
samiuelson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
samiuelson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private fun buildSiteSpecificKey(key: String): Preferences.Key<String>? { | ||
val site = selectedSite.getOrNull() | ||
return if (site != null) { | ||
stringPreferencesKey("${site.siteId}-$key") | ||
} else { | ||
logger.e("Cannot build site-specific key '$key': no site selected") | ||
null | ||
} | ||
} | ||
|
||
private companion object { | ||
const val PRODUCTS_TIMESTAMP_KEY = "pos_products_sync_timestamp" | ||
const val VARIATIONS_TIMESTAMP_KEY = "pos_variations_sync_timestamp" | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.