Compare commits

...

9 Commits

30 changed files with 278 additions and 33 deletions

View File

@@ -1,7 +1,23 @@
# Changelog # Changelog
## 0.25.2
* `Versions`:
* `Exposed`: `0.59.0` -> `0.60.0`
* `Repo`:
* `Cache`:
* Add extensions `alsoInvalidate`, `alsoInvalidateAsync`, `alsoInvalidateSync` and `alsoInvalidateSyncLogging`
* `Koin`:
* Add extensions `singleSuspend` and `factorySuspend` for defining of dependencies with suspendable blocks
## 0.25.1 ## 0.25.1
* `Coroutines`:
* Add `SortedMapLikeBinaryTreeNode`
* `Pagination`:
* `Compose`:
* One more rework of `InfinityPagedComponent` and `PagedComponent`
## 0.25.0 ## 0.25.0
* `Repos`: * `Repos`:

View File

@@ -71,7 +71,7 @@ fun <T, M> Flow<T>.subscribeAsync(
it.invoke(markersMap) it.invoke(markersMap)
} }
val job = subscribeSafelyWithoutExceptions(subscope) { data -> val job = subscribeLoggingDropExceptions(subscope) { data ->
val dataCommand = AsyncSubscriptionCommandData(data, subscope, markerFactory, block) { marker -> val dataCommand = AsyncSubscriptionCommandData(data, subscope, markerFactory, block) { marker ->
actor.send( actor.send(
AsyncSubscriptionCommandClearReceiver(marker) AsyncSubscriptionCommandClearReceiver(marker)

View File

@@ -7,7 +7,9 @@ fun <T> CoroutineScope.launchSynchronously(block: suspend CoroutineScope.() -> T
val objectToSynchronize = Object() val objectToSynchronize = Object()
synchronized(objectToSynchronize) { synchronized(objectToSynchronize) {
launch(start = CoroutineStart.UNDISPATCHED) { launch(start = CoroutineStart.UNDISPATCHED) {
result = safelyWithResult(block) result = runCatching {
block()
}
}.invokeOnCompletion { }.invokeOnCompletion {
synchronized(objectToSynchronize) { synchronized(objectToSynchronize) {
objectToSynchronize.notifyAll() objectToSynchronize.notifyAll()

View File

@@ -15,5 +15,5 @@ crypto_js_version=4.1.1
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.25.1 version=0.25.2
android_code_version=291 android_code_version=292

View File

@@ -7,7 +7,7 @@ kt-coroutines = "1.10.1"
kslog = "1.4.1" kslog = "1.4.1"
jb-compose = "1.7.3" jb-compose = "1.7.3"
jb-exposed = "0.59.0" jb-exposed = "0.60.0"
jb-dokka = "2.0.0" jb-dokka = "2.0.0"
sqlite = "3.49.1.0" sqlite = "3.49.1.0"

View File

@@ -17,11 +17,13 @@ kotlin {
jvmMain { jvmMain {
dependencies { dependencies {
api libs.kt.reflect api libs.kt.reflect
api project(":micro_utils.coroutines")
} }
} }
androidMain { androidMain {
dependencies { dependencies {
api libs.kt.reflect api libs.kt.reflect
api project(":micro_utils.coroutines")
} }
} }
} }

View File

@@ -0,0 +1,32 @@
package dev.inmo.micro_utils.koin
import dev.inmo.micro_utils.coroutines.doSynchronously
import kotlinx.coroutines.CoroutineScope
import org.koin.core.module.Module
import org.koin.core.parameter.ParametersHolder
import org.koin.core.qualifier.Qualifier
import org.koin.core.qualifier.StringQualifier
import org.koin.core.scope.Scope
import kotlin.reflect.KClass
inline fun <reified T : Any> Module.factorySuspend(
qualifier: Qualifier? = null,
coroutineScope: CoroutineScope? = null,
noinline definition: suspend Scope.(ParametersHolder) -> T
) = factory(
qualifier,
if (coroutineScope == null) {
{
doSynchronously {
definition(it)
}
}
} else {
{
coroutineScope.doSynchronously {
definition(it)
}
}
}
)

View File

@@ -0,0 +1,32 @@
package dev.inmo.micro_utils.koin
import dev.inmo.micro_utils.coroutines.doSynchronously
import kotlinx.coroutines.CoroutineScope
import org.koin.core.module.Module
import org.koin.core.parameter.ParametersHolder
import org.koin.core.qualifier.StringQualifier
import org.koin.core.scope.Scope
inline fun <reified T : Any> Module.singleSuspend(
qualifier: StringQualifier,
createdAtStart: Boolean = false,
coroutineScope: CoroutineScope? = null,
noinline definition: suspend Scope.(ParametersHolder) -> T
) = single(
qualifier,
createdAtStart,
if (coroutineScope == null) {
{
doSynchronously {
definition(it)
}
}
} else {
{
coroutineScope.doSynchronously {
definition(it)
}
}
}
)

View File

@@ -86,7 +86,7 @@ internal fun <T> InfinityPagedComponent(
val scope = predefinedScope ?: rememberCoroutineScope() val scope = predefinedScope ?: rememberCoroutineScope()
val context = remember { InfinityPagedComponentContext<T>(page, size, scope, loader) } val context = remember { InfinityPagedComponentContext<T>(page, size, scope, loader) }
remember { remember {
context.loadNext() context.reload()
} }
val dataState = context.dataState.collectAsState() val dataState = context.dataState.collectAsState()

View File

@@ -2,7 +2,12 @@ package dev.inmo.micro_utils.pagination.compose
import androidx.compose.runtime.* import androidx.compose.runtime.*
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow
import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
/** /**
* Context for managing paginated data in a Compose UI. * Context for managing paginated data in a Compose UI.
@@ -18,39 +23,73 @@ import dev.inmo.micro_utils.pagination.*
*/ */
class PagedComponentContext<T> internal constructor( class PagedComponentContext<T> internal constructor(
initialPage: Int, initialPage: Int,
size: Int size: Int,
private val scope: CoroutineScope,
private val loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>
) { ) {
internal val startPage = SimplePagination(initialPage, size) internal val startPage = SimplePagination(initialPage, size)
internal val currentlyLoadingPageState = SpecialMutableStateFlow<Pagination?>(startPage)
internal val latestLoadedPage = SpecialMutableStateFlow<PaginationResult<T>?>(null) internal val latestLoadedPage = SpecialMutableStateFlow<PaginationResult<T>?>(null)
internal val dataState = SpecialMutableStateFlow<PaginationResult<T>?>(null)
internal var loadingJob: Job? = null
internal val loadingMutex = Mutex()
private fun initLoadingJob(
skipCheckerInLock: () -> Boolean,
pageGetter: () -> Pagination
): Job {
return scope.launchLoggingDropExceptions {
loadingMutex.withLock {
if (skipCheckerInLock()) return@launchLoggingDropExceptions
loadingJob = loadingJob ?: scope.launchLoggingDropExceptions {
runCatching {
loader(pageGetter())
}.onSuccess {
latestLoadedPage.value = it
dataState.value = it
}
loadingMutex.withLock {
loadingJob = null
}
}
loadingJob
} ?.join()
}
}
/** /**
* Loads the next page of data. If the last page is reached, this function returns early. * Loads the next page of data. If the last page is reached, this function returns early.
*/ */
fun loadNext() { fun loadNext(): Job {
when { return initLoadingJob(
currentlyLoadingPageState.value != null -> return { latestLoadedPage.value ?.isLastPage == true }
latestLoadedPage.value ?.isLastPage == true -> return ) {
else -> currentlyLoadingPageState.value = (latestLoadedPage.value ?.nextPage()) ?: startPage latestLoadedPage.value ?.nextPage() ?: startPage
} }
} }
/** /**
* Loads the previous page of data if available. * Loads the previous page of data if available.
*/ */
fun loadPrevious() { fun loadPrevious(): Job {
when { return initLoadingJob(
currentlyLoadingPageState.value != null -> return { latestLoadedPage.value ?.isFirstPage == true }
latestLoadedPage.value ?.isFirstPage == true -> return ) {
else -> currentlyLoadingPageState.value = (latestLoadedPage.value ?.previousPage()) ?: startPage latestLoadedPage.value ?.previousPage() ?: startPage
} }
} }
/** /**
* Reloads the current page, refreshing the data. * Reloads the current page, refreshing the data.
*/ */
fun reload() { fun reload(): Job {
currentlyLoadingPageState.value = latestLoadedPage.value return initLoadingJob(
{
latestLoadedPage.value = null
true
}
) {
startPage
}
} }
} }
@@ -69,18 +108,16 @@ internal fun <T> PagedComponent(
initialPage: Int, initialPage: Int,
size: Int, size: Int,
loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>, loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>,
predefinedScope: CoroutineScope? = null,
block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit
) { ) {
val context = remember { PagedComponentContext<T>(initialPage, size) } val scope = predefinedScope ?: rememberCoroutineScope()
val context = remember { PagedComponentContext<T>(initialPage, size, scope, loader) }
val currentlyLoadingState = context.currentlyLoadingPageState.collectAsState() remember {
LaunchedEffect(currentlyLoadingState.value) { context.reload()
val paginationResult = loader(context, currentlyLoadingState.value ?: return@LaunchedEffect)
context.latestLoadedPage.value = paginationResult
context.currentlyLoadingPageState.value = null
} }
val pageState = context.latestLoadedPage.collectAsState() val pageState = context.dataState.collectAsState()
pageState.value ?.let { pageState.value ?.let {
context.block(it) context.block(it)
} }
@@ -98,12 +135,14 @@ internal fun <T> PagedComponent(
fun <T> PagedComponent( fun <T> PagedComponent(
pageInfo: Pagination, pageInfo: Pagination,
loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>, loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>,
predefinedScope: CoroutineScope? = null,
block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit
) { ) {
PagedComponent( PagedComponent(
pageInfo.page, pageInfo.page,
pageInfo.size, pageInfo.size,
loader, loader,
predefinedScope,
block block
) )
} }
@@ -120,7 +159,8 @@ fun <T> PagedComponent(
fun <T> PagedComponent( fun <T> PagedComponent(
size: Int, size: Int,
loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>, loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>,
predefinedScope: CoroutineScope? = null,
block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit block: @Composable PagedComponentContext<T>.(PaginationResult<T>) -> Unit
) { ) {
PagedComponent(0, size, loader, block) PagedComponent(0, size, loader, predefinedScope, block)
} }

View File

@@ -0,0 +1,14 @@
package dev.inmo.micro_utils.repos.annotations
@RequiresOptIn(
"Overriding of this invalidate message requires manual launching of invalidation on class initialization process",
RequiresOptIn.Level.WARNING
)
@Target(
AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.FIELD,
AnnotationTarget.PROPERTY,
AnnotationTarget.FUNCTION,
)
annotation class OverrideRequireManualInvalidation

View File

@@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.SmartRWLocker
import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withReadAcquire
import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.cache.KVCache import dev.inmo.micro_utils.repos.cache.cache.KVCache
import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
@@ -39,6 +40,7 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>(
kvCache.contains(id) kvCache.contains(id)
} || parentRepo.contains(id) } || parentRepo.contains(id)
@OverrideRequireManualInvalidation
override suspend fun invalidate() = locker.withWriteLock { override suspend fun invalidate() = locker.withWriteLock {
kvCache.clear() kvCache.clear()
} }
@@ -117,6 +119,7 @@ open class WriteCRUDCacheRepo<ObjectType, IdType, InputValueType>(
return created return created
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() = locker.withWriteLock { override suspend fun invalidate() = locker.withWriteLock {
kvCache.clear() kvCache.clear()
} }
@@ -150,6 +153,7 @@ WriteCRUDRepo<ObjectType, IdType, InputValueType> by WriteCRUDCacheRepo(
idGetter idGetter
), ),
CRUDRepo<ObjectType, IdType, InputValueType> { CRUDRepo<ObjectType, IdType, InputValueType> {
@OverrideRequireManualInvalidation
override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
} }

View File

@@ -1,5 +1,8 @@
package dev.inmo.micro_utils.repos.cache package dev.inmo.micro_utils.repos.cache
import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions
import kotlinx.coroutines.CoroutineScope
interface InvalidatableRepo { interface InvalidatableRepo {
/** /**
* Invalidates its internal data. It __may__ lead to autoreload of data. In case when repo makes autoreload, * Invalidates its internal data. It __may__ lead to autoreload of data. In case when repo makes autoreload,
@@ -8,4 +11,14 @@ interface InvalidatableRepo {
suspend fun invalidate() suspend fun invalidate()
} }
suspend fun <T : InvalidatableRepo> T.alsoInvalidate() = also {
invalidate()
}
fun <T : InvalidatableRepo> T.alsoInvalidateAsync(scope: CoroutineScope) = also {
scope.launchLoggingDropExceptions {
invalidate()
}
}
typealias CacheRepo = InvalidatableRepo typealias CacheRepo = InvalidatableRepo

View File

@@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.withReadAcquire
import dev.inmo.micro_utils.coroutines.withWriteLock import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.cache.KVCache import dev.inmo.micro_utils.repos.cache.cache.KVCache
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -49,6 +50,7 @@ open class ReadKeyValueCacheRepo<Key,Value>(
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
} }

View File

@@ -6,6 +6,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.pagination.utils.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.cache.KVCache import dev.inmo.micro_utils.repos.cache.cache.KVCache
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -48,6 +49,7 @@ open class ReadKeyValuesCacheRepo<Key,Value>(
kvCache.contains(k) kvCache.contains(k)
} || parentRepo.contains(k) } || parentRepo.contains(k)
@OverrideRequireManualInvalidation
override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker) override suspend fun invalidate() = kvCache.actualizeAll(parentRepo, locker = locker)
} }

View File

@@ -6,6 +6,7 @@ import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.KeyValueRepo import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.MapKeyValueRepo import dev.inmo.micro_utils.repos.MapKeyValueRepo
import dev.inmo.micro_utils.repos.ReadCRUDRepo import dev.inmo.micro_utils.repos.ReadCRUDRepo
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
@@ -90,6 +91,7 @@ open class AutoRecacheReadCRUDRepo<RegisteredObject, Id>(
kvCache.set(idGetter(it), it) kvCache.set(idGetter(it), it)
} ?: kvCache.get(id) } ?: kvCache.get(id)
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }

View File

@@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.cache.fallback.crud
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -53,6 +54,7 @@ open class AutoRecacheWriteCRUDRepo<RegisteredObject, Id, InputObject>(
kvCache.set(idGetter(it), it) kvCache.set(idGetter(it), it)
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.clear() kvCache.clear()
} }

View File

@@ -6,6 +6,7 @@ import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.KeyValueRepo import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.MapKeyValueRepo import dev.inmo.micro_utils.repos.MapKeyValueRepo
import dev.inmo.micro_utils.repos.ReadKeyValueRepo import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
@@ -100,6 +101,7 @@ open class AutoRecacheReadKeyValueRepo<Id, RegisteredObject>(
originalRepo.keys(v, pagination, reversed) originalRepo.keys(v, pagination, reversed)
}.getOrElse { kvCache.keys(v, pagination, reversed) } }.getOrElse { kvCache.keys(v, pagination, reversed) }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }

View File

@@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.cache.fallback.keyvalue
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -44,6 +45,7 @@ open class AutoRecacheWriteKeyValueRepo<Id, RegisteredObject>(
kvCache.set(toSet) kvCache.set(toSet)
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.clear() kvCache.clear()
} }

View File

@@ -13,6 +13,7 @@ import dev.inmo.micro_utils.pagination.utils.paginate
import dev.inmo.micro_utils.repos.KeyValueRepo import dev.inmo.micro_utils.repos.KeyValueRepo
import dev.inmo.micro_utils.repos.MapKeyValueRepo import dev.inmo.micro_utils.repos.MapKeyValueRepo
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper import dev.inmo.micro_utils.repos.cache.fallback.ActionWrapper
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
@@ -140,6 +141,7 @@ open class AutoRecacheReadKeyValuesRepo<Id, RegisteredObject>(
}) ?: (kvCache.get(k) ?.contains(v) == true) }) ?: (kvCache.get(k) ?.contains(v) == true)
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }

View File

@@ -3,6 +3,7 @@ package dev.inmo.micro_utils.repos.cache.fallback.keyvalues
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo import dev.inmo.micro_utils.repos.cache.FallbackCacheRepo
import dev.inmo.micro_utils.repos.pagination.maxPagePagination import dev.inmo.micro_utils.repos.pagination.maxPagePagination
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -89,6 +90,7 @@ open class AutoRecacheWriteKeyValuesRepo<Id, RegisteredObject>(
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.clear() kvCache.clear()
} }

View File

@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.* import dev.inmo.micro_utils.repos.cache.*
import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
@@ -133,6 +134,7 @@ open class FullCRUDCacheRepo<ObjectType, IdType, InputValueType>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }

View File

@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -86,6 +87,7 @@ open class FullReadKeyValueCacheRepo<Key,Value>(
{ if (it.results.isNotEmpty()) actualizeAll() } { if (it.results.isNotEmpty()) actualizeAll() }
) )
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }
@@ -160,6 +162,7 @@ open class FullKeyValueCacheRepo<Key,Value>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.actualizeAll(parentRepo, locker) kvCache.actualizeAll(parentRepo, locker)
} }

View File

@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.pagination.utils.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import dev.inmo.micro_utils.repos.pagination.maxPagePagination import dev.inmo.micro_utils.repos.pagination.maxPagePagination
@@ -153,6 +154,7 @@ open class FullReadKeyValuesCacheRepo<Key,Value>(
{ if (it.results.isNotEmpty()) actualizeAll() } { if (it.results.isNotEmpty()) actualizeAll() }
) )
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }
@@ -235,6 +237,7 @@ open class FullKeyValuesCacheRepo<Key,Value>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.actualizeAll(parentRepo, locker = locker) kvCache.actualizeAll(parentRepo, locker = locker)
} }

View File

@@ -1,11 +1,13 @@
package dev.inmo.micro_utils.repos.cache.full.direct package dev.inmo.micro_utils.repos.cache.full.direct
import dev.inmo.micro_utils.common.Warning
import dev.inmo.micro_utils.coroutines.SmartRWLocker import dev.inmo.micro_utils.coroutines.SmartRWLocker
import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions
import dev.inmo.micro_utils.coroutines.withReadAcquire import dev.inmo.micro_utils.coroutines.withReadAcquire
import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.* import dev.inmo.micro_utils.repos.cache.*
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -96,6 +98,8 @@ open class DirectFullCRUDCacheRepo<ObjectType, IdType, InputValueType>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }

View File

@@ -7,6 +7,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.Pagination import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.micro_utils.pagination.PaginationResult import dev.inmo.micro_utils.pagination.PaginationResult
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.full.FullKeyValueCacheRepo import dev.inmo.micro_utils.repos.cache.full.FullKeyValueCacheRepo
import dev.inmo.micro_utils.repos.cache.full.FullReadKeyValueCacheRepo import dev.inmo.micro_utils.repos.cache.full.FullReadKeyValueCacheRepo
import dev.inmo.micro_utils.repos.cache.full.FullWriteKeyValueCacheRepo import dev.inmo.micro_utils.repos.cache.full.FullWriteKeyValueCacheRepo
@@ -54,6 +55,7 @@ open class DirectFullReadKeyValueCacheRepo<Key, Value>(
kvCache.keys(v, pagination, reversed) kvCache.keys(v, pagination, reversed)
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }
@@ -86,6 +88,7 @@ open class DirectFullWriteKeyValueCacheRepo<Key, Value>(
} }
}.launchIn(scope) }.launchIn(scope)
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
locker.withWriteLock { locker.withWriteLock {
kvCache.clear() kvCache.clear()
@@ -135,6 +138,7 @@ open class DirectFullKeyValueCacheRepo<Key, Value>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.actualizeAll(parentRepo, locker) kvCache.actualizeAll(parentRepo, locker)
} }

View File

@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.coroutines.withWriteLock
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.pagination.utils.* import dev.inmo.micro_utils.pagination.utils.*
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.annotations.OverrideRequireManualInvalidation
import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode import dev.inmo.micro_utils.repos.cache.util.ActualizeAllClearMode
import dev.inmo.micro_utils.repos.cache.util.actualizeAll import dev.inmo.micro_utils.repos.cache.util.actualizeAll
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -88,6 +89,7 @@ open class DirectFullReadKeyValuesCacheRepo<Key,Value>(
return result ?: emptyPaginationResult() return result ?: emptyPaginationResult()
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
actualizeAll() actualizeAll()
} }
@@ -121,6 +123,7 @@ open class DirectFullWriteKeyValuesCacheRepo<Key,Value>(
} }
}.launchIn(scope) }.launchIn(scope)
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
locker.withWriteLock { locker.withWriteLock {
kvCache.clear() kvCache.clear()
@@ -170,6 +173,7 @@ open class DirectFullKeyValuesCacheRepo<Key,Value>(
locker.unlockWrite() locker.unlockWrite()
} }
} }
@OverrideRequireManualInvalidation
override suspend fun invalidate() { override suspend fun invalidate() {
kvCache.actualizeAll(parentRepo, locker = locker) kvCache.actualizeAll(parentRepo, locker = locker)
} }

View File

@@ -0,0 +1,54 @@
package dev.inmo.micro_utils.repos.cache
import dev.inmo.kslog.common.KSLog
import dev.inmo.micro_utils.coroutines.doSynchronously
import dev.inmo.micro_utils.coroutines.runCatchingLogging
import kotlinx.coroutines.CoroutineScope
fun <T : InvalidatableRepo> T.alsoInvalidateSync(
scope: CoroutineScope,
onFailure: suspend (Throwable) -> Unit = {},
) = also {
scope.doSynchronously {
runCatching {
invalidate()
}.onFailure {
onFailure(it)
}
}
}
fun <T : InvalidatableRepo> T.alsoInvalidateSync(
onFailure: suspend (Throwable) -> Unit = {},
) = also {
doSynchronously {
runCatching {
invalidate()
}.onFailure {
onFailure(it)
}
}
}
fun <T : InvalidatableRepo> T.alsoInvalidateSyncLogging(
scope: CoroutineScope,
errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" },
logger: KSLog = KSLog,
) = also {
scope.doSynchronously {
runCatchingLogging(errorMessageBuilder, logger) {
invalidate()
}
}
}
fun <T : InvalidatableRepo> T.alsoInvalidateSyncLogging(
errorMessageBuilder: CoroutineScope.(Throwable) -> Any = { "Something web wrong" },
logger: KSLog = KSLog,
) = also {
doSynchronously {
runCatchingLogging(errorMessageBuilder, logger) {
invalidate()
}
}
}

View File

@@ -73,7 +73,7 @@ class KtorCRUDRepoTests : CommonCRUDRepoTests() {
} }
val server = io.ktor.server.engine.embeddedServer( val server = io.ktor.server.engine.embeddedServer(
CIO, CIO,
34567, 34568,
"127.0.0.1" "127.0.0.1"
) { ) {
install(ContentNegotiation) { install(ContentNegotiation) {
@@ -100,7 +100,7 @@ class KtorCRUDRepoTests : CommonCRUDRepoTests() {
} }
} }
val crudClient = KtorCRUDRepoClient<ComplexData, Int, SimpleData>( val crudClient = KtorCRUDRepoClient<ComplexData, Int, SimpleData>(
"http://127.0.0.1:34567", "http://127.0.0.1:34568",
client, client,
ContentType.Application.Json ContentType.Application.Json
) { ) {

View File

@@ -63,7 +63,7 @@ class KtorKeyValueRepoTests : CommonKeyValueRepoTests() {
val repo = MapKeyValueRepo<Int, ComplexData>(map) val repo = MapKeyValueRepo<Int, ComplexData>(map)
val server = io.ktor.server.engine.embeddedServer( val server = io.ktor.server.engine.embeddedServer(
CIO, CIO,
34567, 34569,
"127.0.0.1" "127.0.0.1"
) { ) {
install(ContentNegotiation) { install(ContentNegotiation) {
@@ -91,7 +91,7 @@ class KtorKeyValueRepoTests : CommonKeyValueRepoTests() {
} }
} }
val crudClient = KtorKeyValueRepoClient<Int, ComplexData>( val crudClient = KtorKeyValueRepoClient<Int, ComplexData>(
"http://127.0.0.1:34567", "http://127.0.0.1:34569",
client, client,
ContentType.Application.Json, ContentType.Application.Json,
Int.serializer(), Int.serializer(),