Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-20 20:00:23 +03:00
parent a57d077863
commit 11f4759544
13 changed files with 273 additions and 0 deletions

View file

@ -0,0 +1 @@
<manifest package="com.tangem.data.common" />

View file

@ -0,0 +1,52 @@
package com.tangem.data.common.cache
import org.joda.time.Duration
/**
* Represents a registry for managing cache.
*/
interface CacheRegistry {
/**
* Checks whether the cache key is expired.
*
* @param key cache key.
* @return `true` if the cache key is expired, `false` otherwise.
*/
suspend fun isExpired(key: String): Boolean
/**
* Invalidates the cache key in registry.
*
* If the key doesn't exist, or it's already invalidated, this method doesn't have any effect.
*
* @param key cache key.
*/
suspend fun invalidate(key: String)
/**
* Invalidates all cache keys in the registry.
*
* After the call, the registry doesn't contain any valid keys.
*/
suspend fun invalidateAll()
/**
* Defines a callback to be invoked when the cache key expires.
*
* @param key cache key.
* @param skipCache if `true`, the callback will be invoked regardless of whether the key has expired or not.
* @param expireIn the duration after which the cache key is considered expired.
* @param block the block of code to be executed when the cache key expires.
*/
suspend fun invokeOnExpire(
key: String,
skipCache: Boolean,
expireIn: Duration = Duration.standardMinutes(DEFAULT_CACHE_KEY_EXPIRE_IN_MINUTES),
block: suspend () -> Unit,
)
private companion object {
const val DEFAULT_CACHE_KEY_EXPIRE_IN_MINUTES = 5L
}
}

View file

@ -0,0 +1,52 @@
package com.tangem.data.common.cache
import com.tangem.datasource.local.cache.CacheKeysStore
import com.tangem.datasource.local.cache.model.CacheKey
import org.joda.time.Duration
import org.joda.time.LocalDateTime
internal class DefaultCacheRegistry(
private val cacheKeysStore: CacheKeysStore,
) : CacheRegistry {
override suspend fun isExpired(key: String): Boolean {
val cacheKey = cacheKeysStore.get(key) ?: return true
return cacheKey.updatedAt
.plus(cacheKey.expiresIn)
.isBefore(LocalDateTime.now())
}
override suspend fun invalidate(key: String) {
cacheKeysStore.remove(key)
}
override suspend fun invalidateAll() {
cacheKeysStore.clear()
}
override suspend fun invokeOnExpire(
key: String,
skipCache: Boolean,
expireIn: Duration,
block: suspend () -> Unit,
) {
val isExpired = isExpired(key) || skipCache
if (!isExpired) return
cacheKeysStore.addOrReplace(
key = CacheKey(
id = key,
updatedAt = LocalDateTime.now(),
expiresIn = expireIn,
),
)
try {
block()
} catch (e: Throwable) {
invalidate(key)
throw e
}
}
}

View file

@ -0,0 +1,21 @@
package com.tangem.data.common.cache.di
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.common.cache.DefaultCacheRegistry
import com.tangem.datasource.local.cache.CacheKeysStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object CacheRegistryModule {
@Provides
@Singleton
fun provideCacheRegistry(cacheKeysStore: CacheKeysStore): CacheRegistry {
return DefaultCacheRegistry(cacheKeysStore)
}
}