|
|
@@ -0,0 +1,69 @@ |
|
|
|
package me.jfenn.gitrest.service |
|
|
|
|
|
|
|
import kotlinx.serialization.* |
|
|
|
import kotlinx.serialization.builtins.ListSerializer |
|
|
|
import kotlinx.serialization.builtins.list |
|
|
|
import kotlinx.serialization.builtins.serializer |
|
|
|
import kotlinx.serialization.modules.SerializersModule |
|
|
|
import me.jfenn.gitrest.model.GitrestConfig |
|
|
|
import me.jfenn.gitrest.provider.gitea.model.GiteaUser |
|
|
|
import java.io.File |
|
|
|
import java.io.IOException |
|
|
|
import java.io.PrintWriter |
|
|
|
|
|
|
|
/** |
|
|
|
* Naive caching implementation for the JVM that uses WeakReference |
|
|
|
* as a cache "buffer" that can be cleaned up by the GC when necessary. |
|
|
|
*/ |
|
|
|
class DiskCache( |
|
|
|
val config: GitrestConfig, |
|
|
|
appCacheDir: File, |
|
|
|
val cacheDuration: Long = 864000000 // cache for ~10 days by default |
|
|
|
) : Cache { |
|
|
|
|
|
|
|
val cacheDir = File(appCacheDir, "http") |
|
|
|
|
|
|
|
fun String.cacheFile() = File(cacheDir, "${this.replace(File.separator, "_")}.json") |
|
|
|
|
|
|
|
@ImplicitReflectionSerializer |
|
|
|
fun getSerializerOf(value: Any) : KSerializer<Any>? { |
|
|
|
return if (value is List<*>) { |
|
|
|
return (value.firstOrNull()?.let { it::class.serializerOrNull() } ?: String.serializer()).list as KSerializer<Any> |
|
|
|
} else { |
|
|
|
return value::class.serializerOrNull() as KSerializer<Any> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ImplicitReflectionSerializer |
|
|
|
override fun set(key: String, value: Any) { |
|
|
|
val serializer = getSerializerOf(value) ?: return |
|
|
|
val string = value.javaClass.name + "#" + System.currentTimeMillis() + "#" + config.jsonSerializer.stringify(serializer, value) |
|
|
|
|
|
|
|
try { |
|
|
|
cacheDir.mkdirs() |
|
|
|
key.cacheFile().writeText(string) |
|
|
|
} catch (e: IOException) { |
|
|
|
config.logError("GIT-REST: ${e::class.simpleName} - ${e.message}") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ImplicitReflectionSerializer |
|
|
|
override fun <T> get(key: String): T? { |
|
|
|
return try { |
|
|
|
val fileContents = key.cacheFile().readText().split("#", limit = 3) |
|
|
|
if (fileContents.size != 3) return null |
|
|
|
val (className, lastModified, json) = fileContents |
|
|
|
|
|
|
|
if (System.currentTimeMillis() - lastModified.toLong() < cacheDuration) { |
|
|
|
config.jsonSerializer.parse( |
|
|
|
Class.forName(className).kotlin.serializer(), |
|
|
|
json |
|
|
|
) as? T |
|
|
|
} else null |
|
|
|
} catch (e : IOException) { |
|
|
|
config.logError("GIT-REST: ${e::class.simpleName} - ${e.message}") |
|
|
|
null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |