mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	start to add fallback repos
This commit is contained in:
		@@ -10,12 +10,14 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>(
 | 
			
		||||
    protected open val parentRepo: ReadCRUDRepo<ObjectType, IdType>,
 | 
			
		||||
    protected open val kvCache: KVCache<IdType, ObjectType>,
 | 
			
		||||
    protected open val idGetter: (ObjectType) -> IdType
 | 
			
		||||
) : ReadCRUDRepo<ObjectType, IdType> by parentRepo, CacheRepo {
 | 
			
		||||
) : ReadCRUDRepo<ObjectType, IdType> by parentRepo, CommonCacheRepo {
 | 
			
		||||
    override suspend fun getById(id: IdType): ObjectType? = kvCache.get(id) ?: (parentRepo.getById(id) ?.also {
 | 
			
		||||
        kvCache.set(id, it)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    override suspend fun contains(id: IdType): Boolean = kvCache.contains(id) || parentRepo.contains(id)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <ObjectType, IdType> ReadCRUDRepo<ObjectType, IdType>.cached(
 | 
			
		||||
@@ -28,7 +30,7 @@ open class WriteCRUDCacheRepo<ObjectType, IdType, InputValueType>(
 | 
			
		||||
    protected open val kvCache: KVCache<IdType, ObjectType>,
 | 
			
		||||
    protected open val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
 | 
			
		||||
    protected open val idGetter: (ObjectType) -> IdType
 | 
			
		||||
) : WriteCRUDRepo<ObjectType, IdType, InputValueType>, CacheRepo {
 | 
			
		||||
) : WriteCRUDRepo<ObjectType, IdType, InputValueType>, CommonCacheRepo {
 | 
			
		||||
    override val newObjectsFlow: Flow<ObjectType> by parentRepo::newObjectsFlow
 | 
			
		||||
    override val updatedObjectsFlow: Flow<ObjectType> by parentRepo::updatedObjectsFlow
 | 
			
		||||
    override val deletedObjectsIdsFlow: Flow<IdType> by parentRepo::deletedObjectsIdsFlow
 | 
			
		||||
@@ -72,6 +74,8 @@ open class WriteCRUDCacheRepo<ObjectType, IdType, InputValueType>(
 | 
			
		||||
 | 
			
		||||
        return created
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <ObjectType, IdType, InputType> WriteCRUDRepo<ObjectType, IdType, InputType>.caching(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
package dev.inmo.micro_utils.repos.cache
 | 
			
		||||
 | 
			
		||||
interface CacheRepo
 | 
			
		||||
interface CacheRepo {
 | 
			
		||||
    suspend fun invalidate()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CommonCacheRepo.kt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CommonCacheRepo.kt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
package dev.inmo.micro_utils.repos.cache
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Any inheritor of this should work with next logic: try to take data from some [dev.inmo.micro_utils.repos.cache.cache.KVCache] and,
 | 
			
		||||
 * if not exists, take from origin and save to the cache for future reuse
 | 
			
		||||
 */
 | 
			
		||||
interface CommonCacheRepo : CacheRepo
 | 
			
		||||
							
								
								
									
										8
									
								
								repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/FallbackCacheRepo.kt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
package dev.inmo.micro_utils.repos.cache
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Any inheritor of this should work with next logic: try to take data from original repo and,
 | 
			
		||||
 * if not exists, try to take from the cache some. In case if original repo have returned result, it should be saved to the internal
 | 
			
		||||
 * [dev.inmo.micro_utils.repos.cache.cache.KVCache]
 | 
			
		||||
 */
 | 
			
		||||
interface FallbackCacheRepo : CacheRepo
 | 
			
		||||
@@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.*
 | 
			
		||||
open class ReadKeyValueCacheRepo<Key,Value>(
 | 
			
		||||
    protected open val parentRepo: ReadKeyValueRepo<Key, Value>,
 | 
			
		||||
    protected open val kvCache: KVCache<Key, Value>,
 | 
			
		||||
) : ReadKeyValueRepo<Key,Value> by parentRepo, CacheRepo {
 | 
			
		||||
) : ReadKeyValueRepo<Key,Value> by parentRepo, CommonCacheRepo {
 | 
			
		||||
    override suspend fun get(k: Key): Value? = kvCache.get(k) ?: parentRepo.get(k) ?.also { kvCache.set(k, it) }
 | 
			
		||||
    override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key)
 | 
			
		||||
 | 
			
		||||
@@ -23,6 +23,8 @@ open class ReadKeyValueCacheRepo<Key,Value>(
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
 | 
			
		||||
@@ -33,9 +35,11 @@ open class KeyValueCacheRepo<Key,Value>(
 | 
			
		||||
    parentRepo: KeyValueRepo<Key, Value>,
 | 
			
		||||
    kvCache: KVCache<Key, Value>,
 | 
			
		||||
    scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
 | 
			
		||||
) : ReadKeyValueCacheRepo<Key,Value>(parentRepo, kvCache), KeyValueRepo<Key,Value>, WriteKeyValueRepo<Key, Value> by parentRepo, CacheRepo {
 | 
			
		||||
) : ReadKeyValueCacheRepo<Key,Value>(parentRepo, kvCache), KeyValueRepo<Key,Value>, WriteKeyValueRepo<Key, Value> by parentRepo, CommonCacheRepo {
 | 
			
		||||
    protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope)
 | 
			
		||||
    protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> KeyValueRepo<Key, Value>.cached(
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.*
 | 
			
		||||
open class ReadKeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
    protected open val parentRepo: ReadKeyValuesRepo<Key, Value>,
 | 
			
		||||
    protected open val kvCache: KVCache<Key, List<Value>>
 | 
			
		||||
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
 | 
			
		||||
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CommonCacheRepo {
 | 
			
		||||
    override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
 | 
			
		||||
        return getAll(k, reversed).paginate(
 | 
			
		||||
            pagination
 | 
			
		||||
@@ -30,6 +30,8 @@ open class ReadKeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
    override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
 | 
			
		||||
@@ -40,7 +42,7 @@ open class KeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
    parentRepo: KeyValuesRepo<Key, Value>,
 | 
			
		||||
    kvCache: KVCache<Key, List<Value>>,
 | 
			
		||||
    scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
 | 
			
		||||
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
 | 
			
		||||
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CommonCacheRepo {
 | 
			
		||||
    protected val onNewJob = parentRepo.onNewValue.onEach { (k, v) ->
 | 
			
		||||
        kvCache.set(
 | 
			
		||||
            k,
 | 
			
		||||
@@ -56,6 +58,8 @@ open class KeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
    protected val onDataClearedJob = parentRepo.onDataCleared.onEach {
 | 
			
		||||
        kvCache.unset(it)
 | 
			
		||||
    }.launchIn(scope)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() = kvCache.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> KeyValuesRepo<Key, Value>.cached(
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,10 @@ open class FullReadCRUDCacheRepo<ObjectType, IdType>(
 | 
			
		||||
        { getById(id) },
 | 
			
		||||
        { it ?.let { set(idGetter(it), it) } }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        actualizeAll()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <ObjectType, IdType> ReadCRUDRepo<ObjectType, IdType>.cached(
 | 
			
		||||
@@ -92,7 +96,11 @@ open class FullCRUDCacheRepo<ObjectType, IdType, InputValueType>(
 | 
			
		||||
        scope,
 | 
			
		||||
        idGetter
 | 
			
		||||
    ),
 | 
			
		||||
    CRUDRepo<ObjectType, IdType, InputValueType>
 | 
			
		||||
    CRUDRepo<ObjectType, IdType, InputValueType> {
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        actualizeAll()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached(
 | 
			
		||||
    kvCache: FullKVCache<IdType, ObjectType>,
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,10 @@ open class FullReadKeyValueCacheRepo<Key,Value>(
 | 
			
		||||
        { parentRepo.keys(v, pagination, reversed) },
 | 
			
		||||
        { if (it.results.isNotEmpty()) actualizeAll() }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        actualizeAll()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
 | 
			
		||||
@@ -81,6 +85,10 @@ open class FullWriteKeyValueCacheRepo<Key,Value>(
 | 
			
		||||
) : WriteKeyValueRepo<Key, Value> by parentRepo, FullCacheRepo {
 | 
			
		||||
    protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope)
 | 
			
		||||
    protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        kvCache.clear()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> WriteKeyValueRepo<Key, Value>.caching(
 | 
			
		||||
@@ -96,6 +104,10 @@ open class FullKeyValueCacheRepo<Key,Value>(
 | 
			
		||||
    KeyValueRepo<Key,Value>,
 | 
			
		||||
    ReadKeyValueRepo<Key, Value> by FullReadKeyValueCacheRepo(parentRepo, kvCache) {
 | 
			
		||||
    override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        super<ReadKeyValueRepo>.invalidate()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> KeyValueRepo<Key, Value>.cached(
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,9 @@ open class FullReadKeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
        { if (it.results.isNotEmpty()) actualizeAll() }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        actualizeAll()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
 | 
			
		||||
@@ -125,6 +128,10 @@ open class FullWriteKeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
            kvCache.get(it.first) ?.minus(it.second) ?: return@onEach
 | 
			
		||||
        )
 | 
			
		||||
    }.launchIn(scope)
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        kvCache.clear()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> WriteKeyValuesRepo<Key, Value>.caching(
 | 
			
		||||
@@ -146,6 +153,10 @@ open class FullKeyValuesCacheRepo<Key,Value>(
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun invalidate() {
 | 
			
		||||
        super<ReadKeyValuesRepo>.invalidate()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <Key, Value> KeyValuesRepo<Key, Value>.caching(
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,11 @@ interface KeyValueRepo<Key, Value> : ReadKeyValueRepo<Key, Value>, WriteKeyValue
 | 
			
		||||
     * By default, will remove all the data of current repo using [doAllWithCurrentPaging], [keys] and [unset]
 | 
			
		||||
     */
 | 
			
		||||
    suspend fun clear() {
 | 
			
		||||
        doAllWithCurrentPaging { keys(it).also { unset(it.results) } }
 | 
			
		||||
        var count: Int
 | 
			
		||||
        do {
 | 
			
		||||
            count = count().takeIf { it < Int.MAX_VALUE } ?.toInt() ?: Int.MAX_VALUE
 | 
			
		||||
            keys(FirstPagePagination(count)).also { unset(it.results) }
 | 
			
		||||
        } while(count > 0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
typealias StandardKeyValueRepo<Key,Value> = KeyValueRepo<Key, Value>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user