mirror of
https://github.com/immich-app/immich.git
synced 2026-03-26 11:50:53 +03:00
fix(mobile): cronet image cache clearing on android (#27054)
This commit is contained in:
@@ -23,10 +23,18 @@ import okhttp3.HttpUrl
|
|||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.chromium.net.CronetEngine
|
import org.chromium.net.CronetEngine
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.file.FileVisitResult
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.SimpleFileVisitor
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes
|
||||||
import java.net.Authenticator
|
import java.net.Authenticator
|
||||||
import java.net.CookieHandler
|
import java.net.CookieHandler
|
||||||
import java.net.PasswordAuthentication
|
import java.net.PasswordAuthentication
|
||||||
@@ -277,10 +285,13 @@ object HttpClientManager {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rebuildCronetEngine(): CronetEngine {
|
suspend fun rebuildCronetEngine(): Result<Long> {
|
||||||
val old = cronetEngine!!
|
return runCatching {
|
||||||
cronetEngine = buildCronetEngine()
|
cronetEngine?.shutdown()
|
||||||
return old
|
val deletionResult = deleteFolderAndGetSize(cronetStoragePath.toPath())
|
||||||
|
cronetEngine = buildCronetEngine()
|
||||||
|
deletionResult
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val cronetStoragePath: File get() = cronetStorageDir
|
val cronetStoragePath: File get() = cronetStorageDir
|
||||||
@@ -301,7 +312,7 @@ object HttpClientManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildCronetEngine(): CronetEngine {
|
fun buildCronetEngine(): CronetEngine {
|
||||||
return CronetEngine.Builder(appContext)
|
return CronetEngine.Builder(appContext)
|
||||||
.enableHttp2(true)
|
.enableHttp2(true)
|
||||||
.enableQuic(true)
|
.enableQuic(true)
|
||||||
@@ -312,6 +323,27 @@ object HttpClientManager {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun deleteFolderAndGetSize(root: Path): Long = withContext(Dispatchers.IO) {
|
||||||
|
var totalSize = 0L
|
||||||
|
|
||||||
|
Files.walkFileTree(root, object : SimpleFileVisitor<Path>() {
|
||||||
|
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||||
|
totalSize += attrs.size()
|
||||||
|
Files.delete(file)
|
||||||
|
return FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
||||||
|
if (dir != root) {
|
||||||
|
Files.delete(dir)
|
||||||
|
}
|
||||||
|
return FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
totalSize
|
||||||
|
}
|
||||||
|
|
||||||
private fun build(cacheDir: File): OkHttpClient {
|
private fun build(cacheDir: File): OkHttpClient {
|
||||||
val connectionPool = ConnectionPool(
|
val connectionPool = ConnectionPool(
|
||||||
maxIdleConnections = KEEP_ALIVE_CONNECTIONS,
|
maxIdleConnections = KEEP_ALIVE_CONNECTIONS,
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ import java.io.EOFException
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.file.FileVisitResult
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.nio.file.SimpleFileVisitor
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
private class RemoteRequest(val cancellationSignal: CancellationSignal)
|
private class RemoteRequest(val cancellationSignal: CancellationSignal)
|
||||||
@@ -205,18 +200,15 @@ private class CronetImageFetcher : ImageFetcher {
|
|||||||
|
|
||||||
private fun onDrained() {
|
private fun onDrained() {
|
||||||
val onCacheCleared = synchronized(stateLock) {
|
val onCacheCleared = synchronized(stateLock) {
|
||||||
val onCacheCleared = onCacheCleared
|
val onCacheCleared = this.onCacheCleared
|
||||||
this.onCacheCleared = null
|
this.onCacheCleared = null
|
||||||
onCacheCleared
|
onCacheCleared
|
||||||
}
|
} ?: return
|
||||||
if (onCacheCleared != null) {
|
|
||||||
val oldEngine = HttpClientManager.rebuildCronetEngine()
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
oldEngine.shutdown()
|
val result = HttpClientManager.rebuildCronetEngine()
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
synchronized(stateLock) { draining = false }
|
||||||
val result = runCatching { deleteFolderAndGetSize(HttpClientManager.cronetStoragePath.toPath()) }
|
onCacheCleared(result)
|
||||||
synchronized(stateLock) { draining = false }
|
|
||||||
onCacheCleared(result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,26 +298,6 @@ private class CronetImageFetcher : ImageFetcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteFolderAndGetSize(root: Path): Long = withContext(Dispatchers.IO) {
|
|
||||||
var totalSize = 0L
|
|
||||||
|
|
||||||
Files.walkFileTree(root, object : SimpleFileVisitor<Path>() {
|
|
||||||
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
|
||||||
totalSize += attrs.size()
|
|
||||||
Files.delete(file)
|
|
||||||
return FileVisitResult.CONTINUE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
|
|
||||||
if (dir != root) {
|
|
||||||
Files.delete(dir)
|
|
||||||
}
|
|
||||||
return FileVisitResult.CONTINUE
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
totalSize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OkHttpImageFetcher private constructor(
|
private class OkHttpImageFetcher private constructor(
|
||||||
|
|||||||
Reference in New Issue
Block a user