Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-27 14:44:19 +03:00
parent f3f29813e0
commit b74e2b9168
25 changed files with 405 additions and 72 deletions

View file

@ -15,6 +15,7 @@ dependencies {
implementation(deps.kotlin.coroutines)
implementation(deps.jodatime)
implementation(deps.timber)
implementation(deps.arrow.core)
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)

View file

@ -0,0 +1,47 @@
package com.tangem.data.common.api
import arrow.core.raise.Raise
import arrow.core.raise.recover
import com.tangem.datasource.api.common.response.ApiResponse
import com.tangem.datasource.api.common.response.ApiResponseError
import timber.log.Timber
/**
* A wrapper around the [Raise] interface specific for [ApiResponseError]. It provides utility functions to
* operate on [ApiResponse] instances.
*
* @property raise A [Raise] instance for raising [ApiResponseError].
*/
@JvmInline
value class ApiResponseRaise(
private val raise: Raise<ApiResponseError>,
) : Raise<ApiResponseError> by raise {
/**
* Binds the given [ApiResponse] to its underlying value or raises an error.
*
* @return The underlying data of the response if it's successful.
*/
fun <T : Any> ApiResponse<T>.bind(): T = when (this) {
is ApiResponse.Success -> data
is ApiResponse.Error -> raise.raise(cause)
}
}
/**
* Attempts to execute an API call safely, providing error handling.
*
* @param call The API call block to execute.
* @param onError A function to handle errors and return a fallback value of type [T].
*
* @return The result of the API call or the fallback value provided by [onError] if an error occurs.
*/
inline fun <T> safeApiCall(call: ApiResponseRaise.() -> T, onError: (ApiResponseError) -> T): T {
return recover(
block = { call(ApiResponseRaise(raise = this)) },
recover = {
Timber.w(it, "Unable to perform safe API call")
onError(it)
},
)
}

View file

@ -24,6 +24,15 @@ interface CacheRegistry {
*/
suspend fun invalidate(key: String)
/**
* Invalidates cache keys in registry.
*
* If the key doesn't exist, or it's already invalidated, this method doesn't have any effect.
*
* @param keys cache keys.
*/
suspend fun invalidate(keys: Collection<String>)
/**
* Invalidates all cache keys in the registry.
*

View file

@ -23,6 +23,11 @@ internal class DefaultCacheRegistry(
cacheKeysStore.remove(key)
}
override suspend fun invalidate(keys: Collection<String>) {
Timber.d("Invalidate cache keys: $keys")
cacheKeysStore.remove(keys)
}
override suspend fun invalidateAll() {
Timber.d("Invalidate all cache keys")
cacheKeysStore.clear()
@ -32,14 +37,14 @@ internal class DefaultCacheRegistry(
key: String,
skipCache: Boolean,
expireIn: Duration,
action: suspend () -> Unit,
block: suspend () -> Unit,
) {
val isExpired = isExpired(key) || skipCache
if (!isExpired) return
try {
Timber.d("Invoke the action associated with the cache key: $key")
action()
block()
} catch (e: Throwable) {
Timber.w(e, "The action related to the cache key has failed: $key")
throw e