曲库同步时效 30 天: 未到期启动不联网, 到期后才同步服务器数据库
- DatabaseBootstrapper: 新增 SYNC_TTL_DAYS=30 与 db_sync_at.txt 时间戳 (lastSyncAt/isSyncDue/syncRemainingMs/syncStatusText/markSynced) - initializeDatabase: 本地曲库可用且未到期时跳过服务器同步(无网络请求); 到期或本地不可用才查版本并在有更新时下载 - 设置页: 曲库行显示「30 天同步: N 天后/已到期」; 更新按钮改为手动强制检查 - download(): 成功后记录同步时间(去掉一次多余的远端版本请求)
This commit is contained in:
@@ -9,12 +9,55 @@ import java.util.Locale
|
||||
*
|
||||
* 说明:已移除分片/镜像数据库下载路径(database_publish 不再发布到代码仓库,
|
||||
* 代码仓库此后只存代码)。曲库统一从官方 Muse 服务(mconn.cherryonline.cn mls-api)
|
||||
* 同步,由 [MuseDbSync] 负责登录、同步、校验与安装;本类只做版本文件与可读错误包装。
|
||||
* 同步,由 [MuseDbSync] 负责登录、同步、校验与安装;本类负责同步时效、版本文件
|
||||
* 与可读错误包装。
|
||||
*
|
||||
* 同步时效:默认 **30 天**([SYNC_TTL_DAYS])。未到期时启动不联网同步,直接用
|
||||
* 本地曲库;到期后才向服务器查询版本并在有更新时下载。
|
||||
*/
|
||||
object DatabaseBootstrapper {
|
||||
private const val TAG = "DatabaseBootstrapper"
|
||||
|
||||
/** 曲库同步时效(天):达到时效后才触发服务器同步。 */
|
||||
const val SYNC_TTL_DAYS = 30
|
||||
private const val SYNC_TTL_MS = SYNC_TTL_DAYS * 24L * 60 * 60 * 1000
|
||||
private const val DAY_MS = 24L * 60 * 60 * 1000
|
||||
|
||||
private val versionFile: File get() = File(MuseDatabase.defaultDbFile().parentFile, "db_version.txt")
|
||||
private val syncStampFile: File get() = File(MuseDatabase.defaultDbFile().parentFile, "db_sync_at.txt")
|
||||
|
||||
/** 上次成功同步(或成功校验为最新)的时间戳(毫秒);无记录返回 0。 */
|
||||
fun lastSyncAt(): Long = runCatching {
|
||||
syncStampFile.takeIf { it.exists() }?.readText()?.trim()?.toLongOrNull()
|
||||
}.getOrNull() ?: 0L
|
||||
|
||||
/** 记录一次成功同步/校验,作为 30 天时效的起点。 */
|
||||
fun markSynced(at: Long = System.currentTimeMillis()) {
|
||||
runCatching { syncStampFile.writeText(at.toString()) }
|
||||
}
|
||||
|
||||
/** 同步是否已到期;无记录(从未同步)视为到期。 */
|
||||
fun isSyncDue(now: Long = System.currentTimeMillis()): Boolean {
|
||||
val last = lastSyncAt()
|
||||
return last <= 0L || now - last >= SYNC_TTL_MS
|
||||
}
|
||||
|
||||
/** 距离下次同步的剩余毫秒;已到期或无记录返回 0。 */
|
||||
fun syncRemainingMs(now: Long = System.currentTimeMillis()): Long {
|
||||
val last = lastSyncAt()
|
||||
if (last <= 0L) return 0L
|
||||
return (last + SYNC_TTL_MS - now).coerceAtLeast(0L)
|
||||
}
|
||||
|
||||
/** 同步状态文案(用于设置界面展示)。 */
|
||||
fun syncStatusText(now: Long = System.currentTimeMillis()): String {
|
||||
val last = lastSyncAt()
|
||||
if (last <= 0L) return "未同步"
|
||||
val remaining = syncRemainingMs(now)
|
||||
if (remaining <= 0L) return "已到期"
|
||||
val days = (remaining + DAY_MS - 1) / DAY_MS
|
||||
return "$days 天后同步"
|
||||
}
|
||||
|
||||
/** 远端曲库版本(官方 Muse);失败返回 null。 */
|
||||
fun fetchRemoteVersion(): String? = MuseDbSync.fetchVersion()
|
||||
@@ -23,16 +66,12 @@ object DatabaseBootstrapper {
|
||||
versionFile.takeIf { it.exists() }?.readText()?.trim()?.takeIf { it.isNotEmpty() }
|
||||
}.getOrNull()
|
||||
|
||||
private fun saveLocalDbVersion(version: String) {
|
||||
runCatching { versionFile.writeText(version.trim()) }
|
||||
}
|
||||
|
||||
/** 下载曲库:仅官方 Muse 同步源。 */
|
||||
/** 下载曲库:仅官方 Muse 同步源;成功后记录同步时间(重置 30 天时效)。 */
|
||||
fun download(onProgress: (Int) -> Unit): Result<File> {
|
||||
return runCatching {
|
||||
val file = MuseDbSync.download(onProgress)
|
||||
// MuseDbSync 内部已保存版本;此处幂等兜底。
|
||||
MuseDbSync.fetchVersion()?.let(::saveLocalDbVersion)
|
||||
// MuseDbSync 内部已保存版本文件;这里记录同步时间作为时效起点。
|
||||
markSynced()
|
||||
file
|
||||
}.mapError(::readableError)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user