add api cache cleanup
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package ru.shadowsparky.vbox.shared.data.api
|
||||||
|
|
||||||
|
import app.cash.sqldelight.async.coroutines.awaitAsOneOrNull
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.koin.core.annotation.Factory
|
||||||
|
import ru.shadowsparky.domain.DispatcherProvider
|
||||||
|
import ru.shadowsparky.vbox.domain.ApiCacheQueries
|
||||||
|
import ru.shadowsparky.vbox.shared.data.AppDatabaseProvider
|
||||||
|
|
||||||
|
@Factory
|
||||||
|
class ApiCache(
|
||||||
|
val dbProvider: AppDatabaseProvider,
|
||||||
|
val json: Json,
|
||||||
|
val dispatcherProvider: DispatcherProvider
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend inline fun <reified T> writeByKey(key: String, value: T) =
|
||||||
|
withContext(dispatcherProvider.io) {
|
||||||
|
getCache().insert(
|
||||||
|
key,
|
||||||
|
json.encodeToString(value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun clear() {
|
||||||
|
getCache().clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend inline fun <reified T> getByKey(key: String): T? {
|
||||||
|
val value = getCache().selectByKey(key)
|
||||||
|
.awaitAsOneOrNull()?.cache_value
|
||||||
|
?: return null
|
||||||
|
return json.decodeFromString(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCache(): ApiCacheQueries {
|
||||||
|
return dbProvider.get().apiCacheQueries
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-35
@@ -1,31 +1,23 @@
|
|||||||
package ru.shadowsparky.vbox.shared.data.api
|
package ru.shadowsparky.vbox.shared.data.api
|
||||||
|
|
||||||
import app.cash.sqldelight.async.coroutines.awaitAsOneOrNull
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import ru.shadowsparky.domain.DispatcherProvider
|
|
||||||
import ru.shadowsparky.vbox.domain.ApiCacheQueries
|
|
||||||
import ru.shadowsparky.vbox.shared.data.AppDatabaseProvider
|
|
||||||
import ru.shadowsparky.vbox.shared.domain.VideoApi
|
import ru.shadowsparky.vbox.shared.domain.VideoApi
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideoDetails
|
import ru.shadowsparky.vbox.shared.domain.model.VideoDetails
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideoLinksResponse
|
import ru.shadowsparky.vbox.shared.domain.model.VideoLinksResponse
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideosResponse
|
import ru.shadowsparky.vbox.shared.domain.model.VideosResponse
|
||||||
|
|
||||||
class FallbackVideoApi(
|
class FallbackVideoApi(
|
||||||
private val dbProvider: AppDatabaseProvider,
|
private val cache: ApiCache,
|
||||||
private val wrapper: VideoApi,
|
private val wrapper: VideoApi
|
||||||
private val json: Json,
|
|
||||||
private val dispatcherProvider: DispatcherProvider
|
|
||||||
) : VideoApi {
|
) : VideoApi {
|
||||||
|
|
||||||
override suspend fun fetchNewVideos(query: String?): VideosResponse {
|
override suspend fun fetchNewVideos(query: String?): VideosResponse {
|
||||||
val key = "fetchNewVideos_${query};1;date;"
|
val key = "fetchNewVideos_${query};1;date;"
|
||||||
return try {
|
return try {
|
||||||
wrapper.fetchNewVideos(query).apply {
|
wrapper.fetchNewVideos(query).apply {
|
||||||
writeByKey(key, this)
|
cache.writeByKey(key, this)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getByKey(key) ?: throw e
|
cache.getByKey(key) ?: throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,10 +25,10 @@ class FallbackVideoApi(
|
|||||||
val key = "fetchDetails_${id};"
|
val key = "fetchDetails_${id};"
|
||||||
return try {
|
return try {
|
||||||
wrapper.fetchDetails(id).apply {
|
wrapper.fetchDetails(id).apply {
|
||||||
writeByKey(key, this)
|
cache.writeByKey(key, this)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getByKey(key) ?: throw e
|
cache.getByKey(key) ?: throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,29 +36,10 @@ class FallbackVideoApi(
|
|||||||
val key = "fetchVideoLinks_${id};$seasonId;"
|
val key = "fetchVideoLinks_${id};$seasonId;"
|
||||||
return try {
|
return try {
|
||||||
wrapper.fetchVideoLinks(id, seasonId).apply {
|
wrapper.fetchVideoLinks(id, seasonId).apply {
|
||||||
writeByKey(key, this)
|
cache.writeByKey(key, this)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getByKey(key) ?: throw e
|
cache.getByKey(key) ?: throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getCache(): ApiCacheQueries {
|
|
||||||
return dbProvider.get().apiCacheQueries
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend inline fun <reified T> getByKey(key: String): T? {
|
|
||||||
val value = getCache().selectByKey(key)
|
|
||||||
.awaitAsOneOrNull()?.cache_value
|
|
||||||
?: return null
|
|
||||||
return json.decodeFromString(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend inline fun <reified T> writeByKey(key: String, value: T) =
|
|
||||||
withContext(dispatcherProvider.io) {
|
|
||||||
getCache().insert(
|
|
||||||
key,
|
|
||||||
json.encodeToString(value)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -1,11 +1,9 @@
|
|||||||
package ru.shadowsparky.vbox.shared.di
|
package ru.shadowsparky.vbox.shared.di
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import org.koin.core.annotation.Module
|
import org.koin.core.annotation.Module
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import ru.shadowsparky.domain.DispatcherProvider
|
import ru.shadowsparky.vbox.shared.data.api.ApiCache
|
||||||
import ru.shadowsparky.vbox.shared.data.AppDatabaseProvider
|
|
||||||
import ru.shadowsparky.vbox.shared.data.api.FallbackVideoApi
|
import ru.shadowsparky.vbox.shared.data.api.FallbackVideoApi
|
||||||
import ru.shadowsparky.vbox.shared.data.api.PosterWithoutSuffixVideoApi
|
import ru.shadowsparky.vbox.shared.data.api.PosterWithoutSuffixVideoApi
|
||||||
import ru.shadowsparky.vbox.shared.data.api.VideoApiImpl
|
import ru.shadowsparky.vbox.shared.data.api.VideoApiImpl
|
||||||
@@ -19,13 +17,11 @@ class HttpModule {
|
|||||||
fun provideVideoApi(
|
fun provideVideoApi(
|
||||||
httpClient: HttpClient,
|
httpClient: HttpClient,
|
||||||
serverConfigurationProvider: ServerConfigurationRepository,
|
serverConfigurationProvider: ServerConfigurationRepository,
|
||||||
json: Json,
|
apiCache: ApiCache
|
||||||
dbProvider: AppDatabaseProvider,
|
|
||||||
dispatcherProvider: DispatcherProvider
|
|
||||||
): VideoApi {
|
): VideoApi {
|
||||||
val impl = VideoApiImpl(httpClient, serverConfigurationProvider)
|
val impl = VideoApiImpl(httpClient, serverConfigurationProvider)
|
||||||
return PosterWithoutSuffixVideoApi(
|
return PosterWithoutSuffixVideoApi(
|
||||||
FallbackVideoApi(dbProvider, impl, json, dispatcherProvider)
|
FallbackVideoApi(apiCache, impl)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -6,6 +6,7 @@ import org.koin.core.annotation.Factory
|
|||||||
import org.koin.core.annotation.Named
|
import org.koin.core.annotation.Named
|
||||||
import ru.shadowsparky.http.domain.LogoutAction
|
import ru.shadowsparky.http.domain.LogoutAction
|
||||||
import ru.shadowsparky.http.domain.TokenStorage
|
import ru.shadowsparky.http.domain.TokenStorage
|
||||||
|
import ru.shadowsparky.vbox.shared.data.api.ApiCache
|
||||||
import ru.shadowsparky.vbox.shared.di.DbType
|
import ru.shadowsparky.vbox.shared.di.DbType
|
||||||
import ru.shadowsparky.vbox.shared.domain.tag.MovieTagRepository
|
import ru.shadowsparky.vbox.shared.domain.tag.MovieTagRepository
|
||||||
import ru.shadowsparky.vbox.shared.domain.tag.UserTagRepository
|
import ru.shadowsparky.vbox.shared.domain.tag.UserTagRepository
|
||||||
@@ -21,7 +22,8 @@ class LogoutUseCase(
|
|||||||
private val bearerAuthProvider: BearerAuthProvider,
|
private val bearerAuthProvider: BearerAuthProvider,
|
||||||
private val tokenStorage: TokenStorage,
|
private val tokenStorage: TokenStorage,
|
||||||
private val authTokenRepository: AuthTokenRepository,
|
private val authTokenRepository: AuthTokenRepository,
|
||||||
private val pendingOperationRepository: PendingOperationRepository
|
private val pendingOperationRepository: PendingOperationRepository,
|
||||||
|
private val apiCache: ApiCache
|
||||||
) : LogoutAction {
|
) : LogoutAction {
|
||||||
|
|
||||||
override suspend fun logout() {
|
override suspend fun logout() {
|
||||||
@@ -37,5 +39,6 @@ class LogoutUseCase(
|
|||||||
localUserTagRepository.clear()
|
localUserTagRepository.clear()
|
||||||
AggregateType.entries.forEach { syncRepository.set(it, false) }
|
AggregateType.entries.forEach { syncRepository.set(it, false) }
|
||||||
pendingOperationRepository.clear()
|
pendingOperationRepository.clear()
|
||||||
|
apiCache.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -12,3 +12,6 @@ deleteByKey:
|
|||||||
|
|
||||||
selectByKey:
|
selectByKey:
|
||||||
SELECT * FROM ApiCache WHERE cache_key = ?;
|
SELECT * FROM ApiCache WHERE cache_key = ?;
|
||||||
|
|
||||||
|
clear:
|
||||||
|
DELETE FROM ApiCache;
|
||||||
|
|||||||
Reference in New Issue
Block a user