feat: add remote sync capability - downloader will now wait when upload scheduler is throttling job

This commit is contained in:
Martin Filo 2023-05-08 19:45:34 +02:00
parent dee51d8695
commit 0405cdca7f
3 changed files with 23 additions and 7 deletions

View file

@ -105,10 +105,13 @@ interface BackupAPI<LOGIN_DATA> {
restore(newData, keysToUpdate) restore(newData, keysToUpdate)
} }
var willQueueSoon: Boolean?
var uploadJob: Job? var uploadJob: Job?
fun shouldUpdate(changedKey: String, isSettings: Boolean): Boolean fun shouldUpdate(changedKey: String, isSettings: Boolean): Boolean
fun addToQueue(changedKey: String, isSettings: Boolean) { fun addToQueue(changedKey: String, isSettings: Boolean) {
if (!shouldUpdate(changedKey, isSettings)) { if (!shouldUpdate(changedKey, isSettings)) {
willQueueSoon = false
Log.d(LOG_KEY, "upload not required, data is same") Log.d(LOG_KEY, "upload not required, data is same")
return return
} }
@ -122,6 +125,7 @@ interface BackupAPI<LOGIN_DATA> {
} }
uploadJob = ioScope.launchSafe { uploadJob = ioScope.launchSafe {
willQueueSoon = false
Log.d(LOG_KEY, "upload is running now") Log.d(LOG_KEY, "upload is running now")
uploadSyncData() uploadSyncData()
} }

View file

@ -39,11 +39,9 @@ import java.util.Date
* *
* | State | Priority | Description * | State | Priority | Description
* |---------:|:--------:|--------------------------------------------------------------------- * |---------:|:--------:|---------------------------------------------------------------------
* | Progress | 1 | When scheduler has queued upload job (but is not working in backupApi
* | | | yet) we should postpone download and prioritize upload
* | Waiting | 2 | Add button to manually trigger sync
* | Waiting | 3 | Move "https://chiff.github.io/cloudstream-sync/google-drive" * | Waiting | 3 | Move "https://chiff.github.io/cloudstream-sync/google-drive"
* | Waiting | 5 | Choose what should be synced and recheck `invalidKeys` in createBackupScheduler * | Someday | 4 | Add button to manually trigger sync
* | Someday | 5 | Choose what should be synced and recheck `invalidKeys` in createBackupScheduler
* | Someday | 3 | Add option to use proper OAuth through Google Services One Tap * | Someday | 3 | Add option to use proper OAuth through Google Services One Tap
* | Someday | 5 | Encrypt data on Drive (low priority) * | Someday | 5 | Encrypt data on Drive (low priority)
* | Solved | 1 | Racing conditions when multiple devices in use * | Solved | 1 | Racing conditions when multiple devices in use
@ -53,6 +51,8 @@ import java.util.Date
* | Solved | 4 | Implement backup before user quits application * | Solved | 4 | Implement backup before user quits application
* | Solved | 1 | Do not write sync meta when user is not syncing data * | Solved | 1 | Do not write sync meta when user is not syncing data
* | Solved | 1 | Fix sync/restore bugs * | Solved | 1 | Fix sync/restore bugs
* | Solved | 1 | When scheduler has queued upload job (but is not working in backupApi
* | | | yet) we should postpone download and prioritize upload
*/ */
class GoogleDriveApi(index: Int) : class GoogleDriveApi(index: Int) :
InAppOAuth2APIManager(index), InAppOAuth2APIManager(index),
@ -74,6 +74,7 @@ class GoogleDriveApi(index: Int) :
override val defaultRedirectUrl = "https://chiff.github.io/cloudstream-sync/google-drive" override val defaultRedirectUrl = "https://chiff.github.io/cloudstream-sync/google-drive"
override var isActive: Boolean? = false override var isActive: Boolean? = false
override var willQueueSoon: Boolean? = false
override var uploadJob: Job? = null override var uploadJob: Job? = null
private var tempAuthFlow: AuthorizationCodeFlow? = null private var tempAuthFlow: AuthorizationCodeFlow? = null
@ -344,8 +345,8 @@ class GoogleDriveApi(index: Int) :
// Internal // Internal
private val continuousDownloader = Scheduler<Boolean>( private val continuousDownloader = Scheduler<Boolean>(
BackupAPI.DOWNLOAD_THROTTLE.inWholeMilliseconds, BackupAPI.DOWNLOAD_THROTTLE.inWholeMilliseconds,
{ overwrite -> onWork = { overwrite ->
if (uploadJob?.isActive == true) { if (uploadJob?.isActive == true || willQueueSoon == true) {
uploadJob!!.invokeOnCompletion { uploadJob!!.invokeOnCompletion {
Log.d(LOG_KEY, "upload is running, reschedule download") Log.d(LOG_KEY, "upload is running, reschedule download")
runDownloader(false, overwrite == true) runDownloader(false, overwrite == true)
@ -357,7 +358,8 @@ class GoogleDriveApi(index: Int) :
} }
runDownloader() runDownloader()
} }
}) }
)
private fun runDownloader(runNow: Boolean = false, overwrite: Boolean = false) { private fun runDownloader(runNow: Boolean = false, overwrite: Boolean = false) {
if (runNow) { if (runNow) {

View file

@ -15,6 +15,7 @@ import com.lagradost.cloudstream3.utils.BackupUtils.nonTransferableKeys
class Scheduler<INPUT>( class Scheduler<INPUT>(
private val throttleTimeMs: Long, private val throttleTimeMs: Long,
private val onWork: (INPUT?) -> Unit, private val onWork: (INPUT?) -> Unit,
private val beforeWork: ((INPUT?) -> Unit)? = null,
private val canWork: ((INPUT?) -> Boolean)? = null private val canWork: ((INPUT?) -> Boolean)? = null
) { ) {
companion object { companion object {
@ -44,6 +45,13 @@ class Scheduler<INPUT>(
) )
} }
}, },
beforeWork = {
AccountManager.BackupApis.filter {
it.isActive == true
}.forEach {
it.willQueueSoon = true
}
},
canWork = { input -> canWork = { input ->
if (input == null) { if (input == null) {
throw IllegalStateException() throw IllegalStateException()
@ -111,6 +119,7 @@ class Scheduler<INPUT>(
} }
Log.d(BackupAPI.LOG_KEY, "[$id] wants to schedule [${input}]") Log.d(BackupAPI.LOG_KEY, "[$id] wants to schedule [${input}]")
beforeWork?.invoke(input)
throttle(input) throttle(input)
return true return true
@ -124,6 +133,7 @@ class Scheduler<INPUT>(
Log.d(BackupAPI.LOG_KEY, "[$id] runs immediate [${input}]") Log.d(BackupAPI.LOG_KEY, "[$id] runs immediate [${input}]")
beforeWork?.invoke(input)
stop() stop()
onWork(input) onWork(input)