优化进度同步逻辑,减少同步次数

This commit is contained in:
kunfei
2023-08-02 00:22:19 +08:00
parent 3f46ccb3ae
commit 577ca2ad40
9 changed files with 1992 additions and 56 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@ import com.google.gson.Gson
import io.legado.app.api.controller.BookController
import io.legado.app.api.controller.BookSourceController
import io.legado.app.api.controller.RssSourceController
import kotlinx.coroutines.runBlocking
/**
* Export book data to other app.
@@ -76,28 +77,36 @@ class ReaderProvider : ContentProvider() {
override fun insert(uri: Uri, values: ContentValues?): Uri? {
if (sMatcher.match(uri) < 0) return null
when (RequestCode.values()[sMatcher.match(uri)]) {
RequestCode.SaveBookSource -> values?.let {
BookSourceController.saveSource(values.getAsString(postBodyKey))
runBlocking {
when (RequestCode.values()[sMatcher.match(uri)]) {
RequestCode.SaveBookSource -> values?.let {
BookSourceController.saveSource(values.getAsString(postBodyKey))
}
RequestCode.SaveBookSources -> values?.let {
BookSourceController.saveSources(values.getAsString(postBodyKey))
}
RequestCode.SaveRssSource -> values?.let {
RssSourceController.saveSource(values.getAsString(postBodyKey))
}
RequestCode.SaveRssSources -> values?.let {
RssSourceController.saveSources(values.getAsString(postBodyKey))
}
RequestCode.SaveBook -> values?.let {
BookController.saveBook(values.getAsString(postBodyKey))
}
RequestCode.SaveBookProgress -> values?.let {
BookController.saveBookProgress(values.getAsString(postBodyKey))
}
else -> throw IllegalStateException(
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
)
}
RequestCode.SaveBookSources -> values?.let {
BookSourceController.saveSources(values.getAsString(postBodyKey))
}
RequestCode.SaveRssSource -> values?.let {
RssSourceController.saveSource(values.getAsString(postBodyKey))
}
RequestCode.SaveRssSources -> values?.let {
RssSourceController.saveSources(values.getAsString(postBodyKey))
}
RequestCode.SaveBook -> values?.let {
BookController.saveBook(values.getAsString(postBodyKey))
}
RequestCode.SaveBookProgress -> values?.let {
BookController.saveBookProgress(values.getAsString(postBodyKey))
}
else -> throw IllegalStateException(
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
)
}
return null
}

View File

@@ -204,8 +204,8 @@ object BookController {
fun saveBook(postData: String?): ReturnData {
val returnData = ReturnData()
GSON.fromJsonObject<Book>(postData).getOrNull()?.let { book ->
book.save()
AppWebDav.uploadBookProgress(book)
book.save()
return returnData.setData("")
}
return returnData.setErrorMsg("格式不对")
@@ -226,7 +226,7 @@ object BookController {
/**
* 保存进度
*/
fun saveBookProgress(postData: String?): ReturnData {
suspend fun saveBookProgress(postData: String?): ReturnData {
val returnData = ReturnData()
GSON.fromJsonObject<BookProgress>(postData)
.onFailure { it.printOnDebug() }
@@ -236,8 +236,10 @@ object BookController {
book.durChapterPos = bookProgress.durChapterPos
book.durChapterTitle = bookProgress.durChapterTitle
book.durChapterTime = bookProgress.durChapterTime
AppWebDav.uploadBookProgress(bookProgress) {
book.syncTime = System.currentTimeMillis()
}
appDb.bookDao.update(book)
AppWebDav.uploadBookProgress(bookProgress)
ReadBook.book?.let {
if (it.name == bookProgress.name &&
it.author == bookProgress.author

View File

@@ -24,7 +24,7 @@ val appDb by lazy {
}
@Database(
version = 70,
version = 71,
exportSchema = true,
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
@@ -58,7 +58,8 @@ val appDb by lazy {
AutoMigration(from = 66, to = 67),
AutoMigration(from = 67, to = 68),
AutoMigration(from = 68, to = 69),
AutoMigration(from = 69, to = 70)
AutoMigration(from = 69, to = 70),
AutoMigration(from = 70, to = 71),
]
)
abstract class AppDatabase : RoomDatabase() {

View File

@@ -90,6 +90,7 @@ data class Book(
// 最近一次阅读书籍的时间(打开正文的时间)
@ColumnInfo(defaultValue = "0")
var durChapterTime: Long = System.currentTimeMillis(),
//字数
override var wordCount: String? = null,
// 刷新书架时更新书籍信息
@ColumnInfo(defaultValue = "1")
@@ -102,7 +103,11 @@ data class Book(
var originOrder: Int = 0,
// 自定义书籍变量信息(用于书源规则检索书籍信息)
override var variable: String? = null,
var readConfig: ReadConfig? = null
//阅读设置
var readConfig: ReadConfig? = null,
//同步时间
@ColumnInfo(defaultValue = "0")
var syncTime: Long = 0L
) : Parcelable, BaseBook {
override fun equals(other: Any?): Boolean {

View File

@@ -211,21 +211,23 @@ object AppWebDav {
val json = GSON.toJson(bookProgress)
val url = getProgressUrl(book.name, book.author)
WebDav(url, authorization).upload(json.toByteArray(), "application/json")
book.syncTime = System.currentTimeMillis()
}.onError {
AppLog.put("上传进度失败\n${it.localizedMessage}", it)
}
}
fun uploadBookProgress(bookProgress: BookProgress) {
val authorization = authorization ?: return
if (!AppConfig.syncBookProgress) return
if (!NetworkUtils.isAvailable()) return
Coroutine.async {
suspend fun uploadBookProgress(bookProgress: BookProgress, onSuccess: (() -> Unit)? = null) {
try {
val authorization = authorization ?: return
if (!AppConfig.syncBookProgress) return
if (!NetworkUtils.isAvailable()) return
val json = GSON.toJson(bookProgress)
val url = getProgressUrl(bookProgress.name, bookProgress.author)
WebDav(url, authorization).upload(json.toByteArray(), "application/json")
}.onError {
AppLog.put("上传进度失败\n${it.localizedMessage}", it)
onSuccess?.invoke()
} catch (e: Exception) {
AppLog.put("上传进度失败\n${e.localizedMessage}", e)
}
}
@@ -260,12 +262,19 @@ object AppWebDav {
suspend fun downloadAllBookProgress() {
val authorization = authorization ?: return
if (!NetworkUtils.isAvailable()) return
val bookProgressFiles = WebDav(bookProgressUrl, authorization).listFiles().map {
it.displayName
}.toHashSet()
val bookProgressFiles = WebDav(bookProgressUrl, authorization).listFiles()
val map = hashMapOf<String, WebDavFile>()
bookProgressFiles.forEach {
map[it.displayName] = it
}
appDb.bookDao.all.forEach { book ->
val progressFileName = getProgressFileName(book.name, book.author)
if (!bookProgressFiles.contains(progressFileName)) return@forEach
val webDavFile = map[progressFileName]
webDavFile ?: return
if (webDavFile.lastModify <= book.syncTime) {
//本地同步时间大于上传时间不用同步
return
}
getBookProgress(book)?.let { bookProgress ->
if (bookProgress.durChapterIndex > book.durChapterIndex
|| (bookProgress.durChapterIndex == book.durChapterIndex
@@ -275,6 +284,7 @@ object AppWebDav {
book.durChapterPos = bookProgress.durChapterPos
book.durChapterTitle = bookProgress.durChapterTitle
book.durChapterTime = bookProgress.durChapterTime
book.syncTime = System.currentTimeMillis()
appDb.bookDao.update(book)
}
}

View File

@@ -140,6 +140,7 @@ object ReadBook : CoroutineScope by MainScope() {
book?.let {
Coroutine.async {
AppWebDav.uploadBookProgress(it)
it.save()
}
}
}

View File

@@ -1312,6 +1312,7 @@ class ReadBookActivity : BaseReadBookActivity(),
delay(300000)
ReadBook.book?.let {
AppWebDav.uploadBookProgress(it)
it.save()
Backup.autoBack(this@ReadBookActivity)
}
}

View File

@@ -9,11 +9,18 @@ import io.legado.app.api.controller.ReplaceRuleController
import io.legado.app.api.controller.RssSourceController
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.service.WebService
import io.legado.app.utils.*
import io.legado.app.utils.GSON
import io.legado.app.web.utils.AssetsWeb
import kotlinx.coroutines.runBlocking
import okio.Pipe
import okio.buffer
import java.io.*
import java.io.BufferedWriter
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.OutputStreamWriter
import kotlin.collections.HashMap
import kotlin.collections.List
import kotlin.collections.set
class HttpServer(port: Int) : NanoHTTPD(port) {
private val assetsWeb = AssetsWeb("web")
@@ -41,22 +48,24 @@ class HttpServer(port: Int) : NanoHTTPD(port) {
session.parseBody(files)
val postData = files["postData"]
returnData = when (uri) {
"/saveBookSource" -> BookSourceController.saveSource(postData)
"/saveBookSources" -> BookSourceController.saveSources(postData)
"/deleteBookSources" -> BookSourceController.deleteSources(postData)
"/saveBook" -> BookController.saveBook(postData)
"/deleteBook" -> BookController.deleteBook(postData)
"/saveBookProgress" -> BookController.saveBookProgress(postData)
"/addLocalBook" -> BookController.addLocalBook(session.parameters)
"/saveReadConfig" -> BookController.saveWebReadConfig(postData)
"/saveRssSource" -> RssSourceController.saveSource(postData)
"/saveRssSources" -> RssSourceController.saveSources(postData)
"/deleteRssSources" -> RssSourceController.deleteSources(postData)
"/saveReplaceRule" -> ReplaceRuleController.saveRule(postData)
"/deleteReplaceRule" -> ReplaceRuleController.delete(postData)
"/testReplaceRule" -> ReplaceRuleController.testRule(postData)
else -> null
returnData = runBlocking {
when (uri) {
"/saveBookSource" -> BookSourceController.saveSource(postData)
"/saveBookSources" -> BookSourceController.saveSources(postData)
"/deleteBookSources" -> BookSourceController.deleteSources(postData)
"/saveBook" -> BookController.saveBook(postData)
"/deleteBook" -> BookController.deleteBook(postData)
"/saveBookProgress" -> BookController.saveBookProgress(postData)
"/addLocalBook" -> BookController.addLocalBook(session.parameters)
"/saveReadConfig" -> BookController.saveWebReadConfig(postData)
"/saveRssSource" -> RssSourceController.saveSource(postData)
"/saveRssSources" -> RssSourceController.saveSources(postData)
"/deleteRssSources" -> RssSourceController.deleteSources(postData)
"/saveReplaceRule" -> ReplaceRuleController.saveRule(postData)
"/deleteReplaceRule" -> ReplaceRuleController.delete(postData)
"/testReplaceRule" -> ReplaceRuleController.testRule(postData)
else -> null
}
}
}