diff --git a/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/DownloadRepository.kt b/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/DownloadRepository.kt index 421a1074..46f30cc2 100644 --- a/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/DownloadRepository.kt +++ b/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/DownloadRepository.kt @@ -7,8 +7,11 @@ import javax.inject.Inject class DownloadRepository @Inject -constructor(protoStore: ProtoStore, private val downloadApiHelper: DownloadApiHelper) : - BaseRepository(protoStore) { +constructor( + protoStore: ProtoStore, + private val downloadApiHelper: DownloadApiHelper, + private val unrestrictRepository: UnrestrictRepository, +) : BaseRepository(protoStore) { suspend fun getDownloads(offset: Int?, page: Int = 1, limit: Int = 50): List { val downloadResponse = @@ -32,6 +35,10 @@ constructor(protoStore: ProtoStore, private val downloadApiHelper: DownloadApiHe errorMessage = "Error deleting download", ) + if (response != null) { + unrestrictRepository.clearUnrestrictedLinkCache() + } + return response } } diff --git a/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/UnrestrictRepository.kt b/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/UnrestrictRepository.kt index 0bcf8851..44c91fbc 100644 --- a/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/UnrestrictRepository.kt +++ b/app/app/src/main/java/com/github/livingwithhippos/unchained/data/repository/UnrestrictRepository.kt @@ -1,27 +1,41 @@ package com.github.livingwithhippos.unchained.data.repository +import android.os.SystemClock +import android.util.LruCache import com.github.livingwithhippos.unchained.data.local.ProtoStore import com.github.livingwithhippos.unchained.data.model.DownloadItem import com.github.livingwithhippos.unchained.data.model.UnchainedNetworkException import com.github.livingwithhippos.unchained.data.remote.UnrestrictApiHelper import com.github.livingwithhippos.unchained.utilities.EitherResult import javax.inject.Inject +import javax.inject.Singleton import kotlinx.coroutines.delay import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody +@Singleton class UnrestrictRepository @Inject constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictApiHelper) : BaseRepository(protoStore) { + private val unrestrictedLinkCache = + LruCache( + UNRESTRICTED_LINK_CACHE_MAX_ENTRIES + ) + suspend fun getEitherUnrestrictedLink( link: String, password: String? = null, remote: Int? = null, ): EitherResult { val token = getToken() + val cacheKey = UnrestrictedLinkCacheKey(link = link, password = password, remote = remote) + + getCachedUnrestrictedLink(cacheKey)?.let { + return EitherResult.Success(it) + } val linkResponse = eitherApiResult( @@ -36,9 +50,17 @@ constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictA errorMessage = "Error Fetching Unrestricted Link Info", ) + if (linkResponse is EitherResult.Success) { + cacheUnrestrictedLink(cacheKey, linkResponse.success) + } + return linkResponse } + fun clearUnrestrictedLinkCache() { + synchronized(unrestrictedLinkCache) { unrestrictedLinkCache.evictAll() } + } + suspend fun getUnrestrictedLinkList( linksList: List, password: String? = null, @@ -110,4 +132,45 @@ constructor(protoStore: ProtoStore, private val unrestrictApiHelper: UnrestrictA return containerResponse } + + private fun cacheUnrestrictedLink(key: UnrestrictedLinkCacheKey, item: DownloadItem) { + synchronized(unrestrictedLinkCache) { + unrestrictedLinkCache.put( + key, + CachedUnrestrictedLink( + item = item, + createdAtElapsedRealtime = SystemClock.elapsedRealtime(), + ), + ) + } + } + + private fun getCachedUnrestrictedLink(key: UnrestrictedLinkCacheKey): DownloadItem? = + synchronized(unrestrictedLinkCache) { + val cachedLink = unrestrictedLinkCache.get(key) ?: return@synchronized null + val cacheAge = SystemClock.elapsedRealtime() - cachedLink.createdAtElapsedRealtime + + if (cacheAge <= UNRESTRICTED_LINK_CACHE_TTL_MS) { + cachedLink.item + } else { + unrestrictedLinkCache.remove(key) + null + } + } + + private data class UnrestrictedLinkCacheKey( + val link: String, + val password: String?, + val remote: Int?, + ) + + private data class CachedUnrestrictedLink( + val item: DownloadItem, + val createdAtElapsedRealtime: Long, + ) + + companion object { + private const val UNRESTRICTED_LINK_CACHE_MAX_ENTRIES = 5000 + private const val UNRESTRICTED_LINK_CACHE_TTL_MS = 2 * 60 * 60 * 1000L + } }