add CacheRecentlyWatchedRepository

This commit is contained in:
2026-08-19 21:47:34 +03:00
parent abb5727d02
commit 58c5da7d8f
7 changed files with 77 additions and 29 deletions
@@ -8,7 +8,7 @@ import ru.shadowsparky.vbox.shared.domain.model.VideoLinksResponse
import ru.shadowsparky.vbox.shared.domain.model.VideosResponse
import kotlin.time.Duration.Companion.days
class SessionVideoApi(
class CacheVideoApi(
private val wrapper: VideoApi,
private val filter: FuzzyMovieSearchFilter,
private val redis: RedisCache
@@ -1,4 +1,4 @@
package ru.shadowsparky.vbox.backend.data
package ru.shadowsparky.vbox.backend.data.recent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
@@ -38,18 +38,6 @@ class BackendRecentlyWatchedRepository(
}
}
suspend fun toggleInfo(info: RecentlyWatchedInfo) =
withContext(dispatcherProvider.io) {
val hasInfo =
db.recentQueries.selectByIds(info.movieId, info.episode, info.season, userId)
.executeAsOneOrNull() != null
if (hasInfo) {
remove(info)
} else {
write(info)
}
}
override fun queryRecentlyWatched(
movieId: Long,
seasonId: Long?
@@ -100,4 +88,4 @@ class BackendRecentlyWatchedRepository(
)
)
}
}
}
@@ -0,0 +1,59 @@
package ru.shadowsparky.vbox.backend.data.recent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import ru.shadowsparky.vbox.backend.data.RedisCache
import ru.shadowsparky.vbox.shared.domain.RecentlyWatchedRepository
import ru.shadowsparky.vbox.shared.domain.model.RecentlyWatchedInfo
import kotlin.time.Duration.Companion.days
class CacheRecentlyWatchedRepository(
private val wrapper: RecentlyWatchedRepository,
private val redis: RedisCache,
userId: Long
) : RecentlyWatchedRepository {
private val prefix = "$PREFIX:$userId"
override suspend fun remove(info: RecentlyWatchedInfo) {
info.obtainKeys().forEach { redis.delete(it) }
wrapper.remove(info)
}
override suspend fun write(info: RecentlyWatchedInfo) {
info.obtainKeys().forEach { redis.delete(it) }
wrapper.write(info)
}
private fun RecentlyWatchedInfo.obtainKeys(): Set<String> {
return setOf(
"$prefix:$movieId:$season",
prefix
)
}
override fun queryRecentlyWatched(
movieId: Long,
seasonId: Long?
): Flow<List<RecentlyWatchedInfo>> {
return flow {
emit(
redis.exec(
"$prefix:$movieId:$seasonId",
7.days
) { wrapper.queryRecentlyWatched(movieId, seasonId).first() }
)
}
}
override suspend fun getAllRecentlyWatched(): List<RecentlyWatchedInfo> {
return redis.exec(
prefix,
7.days
) { wrapper.getAllRecentlyWatched() }
}
companion object {
const val PREFIX = "recently_watched"
}
}
@@ -5,7 +5,7 @@ import org.koin.core.annotation.Module
import ru.shadowsparky.vbox.backend.data.FuzzyMovieSearchFilter
import ru.shadowsparky.vbox.backend.data.RedisCache
import ru.shadowsparky.vbox.backend.data.http.ExternalBackendApi
import ru.shadowsparky.vbox.backend.data.http.SessionVideoApi
import ru.shadowsparky.vbox.backend.data.http.CacheVideoApi
import ru.shadowsparky.vbox.shared.domain.VideoApi
@Module
@@ -17,6 +17,6 @@ class HttpModule {
filter: FuzzyMovieSearchFilter,
redisCache: RedisCache
): VideoApi {
return SessionVideoApi(impl, filter, redisCache)
return CacheVideoApi(impl, filter, redisCache)
}
}
@@ -2,17 +2,26 @@ package ru.shadowsparky.vbox.backend.di.factory
import org.koin.core.annotation.Factory
import ru.shadowsparky.vbox.backend.AppDatabase
import ru.shadowsparky.vbox.backend.data.BackendRecentlyWatchedRepository
import ru.shadowsparky.vbox.backend.data.RedisCache
import ru.shadowsparky.vbox.backend.data.recent.BackendRecentlyWatchedRepository
import ru.shadowsparky.vbox.backend.data.recent.CacheRecentlyWatchedRepository
import ru.shadowsparky.vbox.shared.di.factory.DispatcherProvider
import ru.shadowsparky.vbox.shared.domain.RecentlyWatchedRepository
import ru.shadowsparky.vbox.shared.domain.RemoteEventHandler
@Factory
class RecentlyWatchedRepositoryFactory(
private val db: AppDatabase,
private val dispatcherProvider: DispatcherProvider,
private val remoteEventHandler: RemoteEventHandler
private val remoteEventHandler: RemoteEventHandler,
private val redisCache: RedisCache
) {
fun create(userId: Long): BackendRecentlyWatchedRepository {
return BackendRecentlyWatchedRepository(db, userId, dispatcherProvider, remoteEventHandler)
fun create(userId: Long): RecentlyWatchedRepository {
val impl = BackendRecentlyWatchedRepository(db, userId, dispatcherProvider, remoteEventHandler)
return CacheRecentlyWatchedRepository(
impl,
redisCache,
userId
)
}
}
@@ -38,11 +38,4 @@ fun Route.setupRecentlyWatched(recentlyFactory: RecentlyWatchedRepositoryFactory
}
call.respond(HttpStatusCode.OK)
}
post(RecentlyWatchedRepository.TOGGLE) {
val repo = recentlyFactory.create(call.obtainUserId())
call.receive<RecentlyWatchedRequest>().info.forEach {
repo.toggleInfo(it)
}
call.respond(HttpStatusCode.OK)
}
}
@@ -28,7 +28,6 @@ interface RecentlyWatchedRepository {
const val REMOVE = "$PREFIX/delete"
const val WRITE = "$PREFIX/add"
const val TOGGLE = "$PREFIX/toggle"
const val GET_INFO = "$PREFIX/query"
const val MOVIE_ID_ARG = "movieId"