Причина синхронизации и временная метка в логах
This commit is contained in:
@@ -4,6 +4,7 @@ import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncPaths
|
|||||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||||
import com.github.nullptroma.wallenc.ui.R
|
import com.github.nullptroma.wallenc.ui.R
|
||||||
import com.github.nullptroma.wallenc.ui.resources.UiStringResolver
|
import com.github.nullptroma.wallenc.ui.resources.UiStringResolver
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||||
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -61,7 +62,7 @@ class StorageSyncBootstrap @Inject constructor(
|
|||||||
}
|
}
|
||||||
syncRunner.enqueue(
|
syncRunner.enqueue(
|
||||||
displayTitle = uiStrings(R.string.task_title_storage_sync_background),
|
displayTitle = uiStrings(R.string.task_title_storage_sync_background),
|
||||||
logReason = "debounce",
|
reason = StorageSyncTriggerReason.Debounce,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import androidx.hilt.work.HiltWorker
|
import androidx.hilt.work.HiltWorker
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||||
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
@@ -19,7 +20,7 @@ class StorageSyncWorker @AssistedInject constructor(
|
|||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
Timber.d("Periodic storage sync started (attempt %d)", runAttemptCount)
|
Timber.d("Periodic storage sync started (attempt %d)", runAttemptCount)
|
||||||
return runCatching {
|
return runCatching {
|
||||||
syncRunner.runBlocking()
|
syncRunner.runBlocking(StorageSyncTriggerReason.Background)
|
||||||
Timber.d("Periodic storage sync finished")
|
Timber.d("Periodic storage sync finished")
|
||||||
Result.success()
|
Result.success()
|
||||||
}.getOrElse { error ->
|
}.getOrElse { error ->
|
||||||
|
|||||||
@@ -20,4 +20,7 @@ interface ITaskOrchestrator {
|
|||||||
fun cancel(taskId: TaskId): Boolean
|
fun cancel(taskId: TaskId): Boolean
|
||||||
|
|
||||||
fun cancelAll()
|
fun cancelAll()
|
||||||
|
|
||||||
|
/** Запись в общий лог пайплайна вне контекста [TaskContext] (например, WorkManager sync). */
|
||||||
|
fun appendPipelineLog(level: TaskLogLevel, key: TaskLogKey)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.UUID
|
|||||||
data class PipelineTask(
|
data class PipelineTask(
|
||||||
val id: TaskId,
|
val id: TaskId,
|
||||||
val title: String,
|
val title: String,
|
||||||
|
val enqueuedAtMs: Long,
|
||||||
val dispatcher: CoroutineDispatcher,
|
val dispatcher: CoroutineDispatcher,
|
||||||
val state: TaskRunState,
|
val state: TaskRunState,
|
||||||
/** UUID storage, для которого идёт задача (кнопки только этой строки в UI). */
|
/** UUID storage, для которого идёт задача (кнопки только этой строки в UI). */
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.github.nullptroma.wallenc.domain.tasks
|
||||||
|
|
||||||
|
/** Источник запуска синхронизации хранилищ (для логов пайплайна задач). */
|
||||||
|
enum class StorageSyncTriggerReason {
|
||||||
|
Debounce,
|
||||||
|
SyncTab,
|
||||||
|
Background,
|
||||||
|
}
|
||||||
@@ -3,7 +3,10 @@ package com.github.nullptroma.wallenc.domain.tasks
|
|||||||
import com.github.nullptroma.wallenc.domain.errors.WallencException
|
import com.github.nullptroma.wallenc.domain.errors.WallencException
|
||||||
|
|
||||||
sealed class TaskLogKey {
|
sealed class TaskLogKey {
|
||||||
data object SyncStarted : TaskLogKey()
|
data class SyncStarted(val reason: StorageSyncTriggerReason) : TaskLogKey()
|
||||||
data object SyncFinished : TaskLogKey()
|
data class SyncFinished(val reason: StorageSyncTriggerReason) : TaskLogKey()
|
||||||
data class SyncFailed(val error: WallencException) : TaskLogKey()
|
data class SyncFailed(
|
||||||
|
val error: WallencException,
|
||||||
|
val reason: StorageSyncTriggerReason,
|
||||||
|
) : TaskLogKey()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class TaskOrchestrator(
|
|||||||
val task = PipelineTask(
|
val task = PipelineTask(
|
||||||
id = id,
|
id = id,
|
||||||
title = title,
|
title = title,
|
||||||
|
enqueuedAtMs = System.currentTimeMillis(),
|
||||||
dispatcher = dispatcher,
|
dispatcher = dispatcher,
|
||||||
state = TaskRunState.Queued,
|
state = TaskRunState.Queued,
|
||||||
busyStorageUuid = busyStorageUuid,
|
busyStorageUuid = busyStorageUuid,
|
||||||
@@ -104,6 +105,10 @@ class TaskOrchestrator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun appendPipelineLog(level: TaskLogLevel, key: TaskLogKey) {
|
||||||
|
appendLogLine(level, message = "", logKey = key)
|
||||||
|
}
|
||||||
|
|
||||||
private fun replaceTask(id: TaskId, fn: (PipelineTask) -> PipelineTask) {
|
private fun replaceTask(id: TaskId, fn: (PipelineTask) -> PipelineTask) {
|
||||||
synchronized(tasksById) {
|
synchronized(tasksById) {
|
||||||
val cur = tasksById[id] ?: return
|
val cur = tasksById[id] ?: return
|
||||||
|
|||||||
@@ -1,13 +1,31 @@
|
|||||||
package com.github.nullptroma.wallenc.ui.resources
|
package com.github.nullptroma.wallenc.ui.resources
|
||||||
|
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskLogKey
|
import com.github.nullptroma.wallenc.domain.tasks.TaskLogKey
|
||||||
import com.github.nullptroma.wallenc.ui.R
|
import com.github.nullptroma.wallenc.ui.R
|
||||||
|
|
||||||
fun TaskLogKey.resolve(resolver: UiStringResolver): String = when (this) {
|
fun TaskLogKey.resolve(resolver: UiStringResolver): String = when (this) {
|
||||||
TaskLogKey.SyncStarted -> resolver(R.string.task_log_sync_started)
|
is TaskLogKey.SyncStarted -> resolver(
|
||||||
TaskLogKey.SyncFinished -> resolver(R.string.task_log_sync_finished)
|
R.string.task_log_sync_started,
|
||||||
|
resolver.resolveSyncTriggerReason(reason),
|
||||||
|
)
|
||||||
|
is TaskLogKey.SyncFinished -> resolver(
|
||||||
|
R.string.task_log_sync_finished,
|
||||||
|
resolver.resolveSyncTriggerReason(reason),
|
||||||
|
)
|
||||||
is TaskLogKey.SyncFailed -> {
|
is TaskLogKey.SyncFailed -> {
|
||||||
val notification = error.toUserNotification().resolve(resolver)
|
val notification = error.toUserNotification().resolve(resolver)
|
||||||
resolver(R.string.task_log_sync_failed, notification)
|
resolver(
|
||||||
|
R.string.task_log_sync_failed,
|
||||||
|
resolver.resolveSyncTriggerReason(reason),
|
||||||
|
notification,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun UiStringResolver.resolveSyncTriggerReason(reason: StorageSyncTriggerReason): String =
|
||||||
|
when (reason) {
|
||||||
|
StorageSyncTriggerReason.Debounce -> this(R.string.task_sync_trigger_debounce)
|
||||||
|
StorageSyncTriggerReason.SyncTab -> this(R.string.task_sync_trigger_sync_tab)
|
||||||
|
StorageSyncTriggerReason.Background -> this(R.string.task_sync_trigger_background)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.github.nullptroma.wallenc.ui.resources
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
private val pipelineTimeFormatter: DateTimeFormatter =
|
||||||
|
DateTimeFormatter.ofPattern("HH:mm:ss")
|
||||||
|
|
||||||
|
fun formatTaskPipelineTime(timestampMs: Long): String =
|
||||||
|
Instant.ofEpochMilli(timestampMs)
|
||||||
|
.atZone(ZoneId.systemDefault())
|
||||||
|
.format(pipelineTimeFormatter)
|
||||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.WindowInsets
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
@@ -36,7 +37,9 @@ import com.github.nullptroma.wallenc.domain.tasks.PipelineTask
|
|||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLevel
|
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLevel
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskRunState
|
import com.github.nullptroma.wallenc.domain.tasks.TaskRunState
|
||||||
import com.github.nullptroma.wallenc.ui.R
|
import com.github.nullptroma.wallenc.ui.R
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLine
|
||||||
import com.github.nullptroma.wallenc.ui.resources.displayText
|
import com.github.nullptroma.wallenc.ui.resources.displayText
|
||||||
|
import com.github.nullptroma.wallenc.ui.resources.formatTaskPipelineTime
|
||||||
import com.github.nullptroma.wallenc.ui.resources.resolveText
|
import com.github.nullptroma.wallenc.ui.resources.resolveText
|
||||||
import com.github.nullptroma.wallenc.ui.resources.toUserNotification
|
import com.github.nullptroma.wallenc.ui.resources.toUserNotification
|
||||||
|
|
||||||
@@ -91,18 +94,7 @@ fun TaskPipelineScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
) {
|
) {
|
||||||
items(logs.size) { i ->
|
items(logs.size) { i ->
|
||||||
val line = logs[i]
|
PipelineLogRow(line = logs[i])
|
||||||
val prefix = when (line.level) {
|
|
||||||
TaskLogLevel.Debug -> "D"
|
|
||||||
TaskLogLevel.Info -> "I"
|
|
||||||
TaskLogLevel.Warn -> "W"
|
|
||||||
TaskLogLevel.Error -> "E"
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
"[$prefix] ${line.displayText()}",
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
@@ -178,14 +170,59 @@ fun TaskPipelineScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun PipelineLogRow(line: TaskLogLine) {
|
||||||
|
val prefix = when (line.level) {
|
||||||
|
TaskLogLevel.Debug -> "D"
|
||||||
|
TaskLogLevel.Info -> "I"
|
||||||
|
TaskLogLevel.Warn -> "W"
|
||||||
|
TaskLogLevel.Error -> "E"
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.Top,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "[$prefix] ${line.displayText()}",
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 8.dp),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = formatTaskPipelineTime(line.timestampMs),
|
||||||
|
modifier = Modifier.widthIn(min = 56.dp),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun TaskRow(task: PipelineTask, isRunning: Boolean) {
|
private fun TaskRow(task: PipelineTask, isRunning: Boolean) {
|
||||||
Column(Modifier.fillMaxWidth()) {
|
Column(Modifier.fillMaxWidth()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
task.title,
|
text = task.title,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 8.dp),
|
||||||
style = if (isRunning) MaterialTheme.typography.titleSmall
|
style = if (isRunning) MaterialTheme.typography.titleSmall
|
||||||
else MaterialTheme.typography.bodyMedium,
|
else MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = formatTaskPipelineTime(task.enqueuedAtMs),
|
||||||
|
modifier = Modifier.widthIn(min = 56.dp),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
)
|
||||||
|
}
|
||||||
val runningProgress = (task.state as? TaskRunState.Running)?.progress
|
val runningProgress = (task.state as? TaskRunState.Running)?.progress
|
||||||
val progressLabel = runningProgress?.label?.resolveText()
|
val progressLabel = runningProgress?.label?.resolveText()
|
||||||
val stateLabel = when (val s = task.state) {
|
val stateLabel = when (val s = task.state) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.github.nullptroma.wallenc.ui.resources.resolve
|
|||||||
import com.github.nullptroma.wallenc.ui.resources.UserNotification
|
import com.github.nullptroma.wallenc.ui.resources.UserNotification
|
||||||
import com.github.nullptroma.wallenc.usecases.AddStorageToSyncGroupResult
|
import com.github.nullptroma.wallenc.usecases.AddStorageToSyncGroupResult
|
||||||
import com.github.nullptroma.wallenc.usecases.ManageStorageSyncGroupsUseCase
|
import com.github.nullptroma.wallenc.usecases.ManageStorageSyncGroupsUseCase
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||||
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
||||||
import com.github.nullptroma.wallenc.usecases.StorageSyncCompatibilityInput
|
import com.github.nullptroma.wallenc.usecases.StorageSyncCompatibilityInput
|
||||||
import com.github.nullptroma.wallenc.usecases.isStorageCompatibleWithGroup
|
import com.github.nullptroma.wallenc.usecases.isStorageCompatibleWithGroup
|
||||||
@@ -209,7 +210,7 @@ class StorageSyncViewModel @Inject constructor(
|
|||||||
fun runSyncNow() {
|
fun runSyncNow() {
|
||||||
val started = runStorageSyncUseCase.enqueue(
|
val started = runStorageSyncUseCase.enqueue(
|
||||||
displayTitle = uiStrings(R.string.task_title_storage_sync),
|
displayTitle = uiStrings(R.string.task_title_storage_sync),
|
||||||
logReason = "sync-tab",
|
reason = StorageSyncTriggerReason.SyncTab,
|
||||||
)
|
)
|
||||||
if (!started) {
|
if (!started) {
|
||||||
updateState(
|
updateState(
|
||||||
|
|||||||
@@ -289,9 +289,12 @@
|
|||||||
<string name="sync_progress_group_renewing_locks">Синхронизация: группа «%1$s» — продление блокировок</string>
|
<string name="sync_progress_group_renewing_locks">Синхронизация: группа «%1$s» — продление блокировок</string>
|
||||||
<string name="sync_progress_group_lock_renewal_failed">Синхронизация: группа «%1$s» — не удалось продлить блокировку</string>
|
<string name="sync_progress_group_lock_renewal_failed">Синхронизация: группа «%1$s» — не удалось продлить блокировку</string>
|
||||||
<string name="task_progress_clear_content">%1$d / %2$d</string>
|
<string name="task_progress_clear_content">%1$d / %2$d</string>
|
||||||
<string name="task_log_sync_started">Синхронизация хранилищ запущена</string>
|
<string name="task_log_sync_started">Синхронизация хранилищ запущена (%1$s)</string>
|
||||||
<string name="task_log_sync_finished">Синхронизация хранилищ завершена</string>
|
<string name="task_log_sync_finished">Синхронизация хранилищ завершена (%1$s)</string>
|
||||||
<string name="task_log_sync_failed">Синхронизация не удалась: %1$s</string>
|
<string name="task_log_sync_failed">Синхронизация не удалась (%1$s): %2$s</string>
|
||||||
|
<string name="task_sync_trigger_debounce">debounce</string>
|
||||||
|
<string name="task_sync_trigger_sync_tab">sync-tab</string>
|
||||||
|
<string name="task_sync_trigger_background">background</string>
|
||||||
<string name="task_log_enumerating">Перечисление файлов и папок…</string>
|
<string name="task_log_enumerating">Перечисление файлов и папок…</string>
|
||||||
<string name="task_log_creating_storage">Создание хранилища…</string>
|
<string name="task_log_creating_storage">Создание хранилища…</string>
|
||||||
<string name="task_log_storage_created">Хранилище создано</string>
|
<string name="task_log_storage_created">Хранилище создано</string>
|
||||||
|
|||||||
@@ -289,9 +289,12 @@
|
|||||||
<string name="sync_progress_group_renewing_locks">Storage sync: group "%1$s" renewing locks</string>
|
<string name="sync_progress_group_renewing_locks">Storage sync: group "%1$s" renewing locks</string>
|
||||||
<string name="sync_progress_group_lock_renewal_failed">Storage sync: group "%1$s" lock renewal failed</string>
|
<string name="sync_progress_group_lock_renewal_failed">Storage sync: group "%1$s" lock renewal failed</string>
|
||||||
<string name="task_progress_clear_content">%1$d / %2$d</string>
|
<string name="task_progress_clear_content">%1$d / %2$d</string>
|
||||||
<string name="task_log_sync_started">Storage sync started</string>
|
<string name="task_log_sync_started">Storage sync started (%1$s)</string>
|
||||||
<string name="task_log_sync_finished">Storage sync finished</string>
|
<string name="task_log_sync_finished">Storage sync finished (%1$s)</string>
|
||||||
<string name="task_log_sync_failed">Storage sync failed: %1$s</string>
|
<string name="task_log_sync_failed">Storage sync failed (%1$s): %2$s</string>
|
||||||
|
<string name="task_sync_trigger_debounce">debounce</string>
|
||||||
|
<string name="task_sync_trigger_sync_tab">sync-tab</string>
|
||||||
|
<string name="task_sync_trigger_background">background</string>
|
||||||
<string name="task_log_enumerating">Enumerating files and directories…</string>
|
<string name="task_log_enumerating">Enumerating files and directories…</string>
|
||||||
<string name="task_log_creating_storage">Creating storage…</string>
|
<string name="task_log_creating_storage">Creating storage…</string>
|
||||||
<string name="task_log_storage_created">Storage created</string>
|
<string name="task_log_storage_created">Storage created</string>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.github.nullptroma.wallenc.usecases
|
|||||||
import com.github.nullptroma.wallenc.domain.errors.toWallencException
|
import com.github.nullptroma.wallenc.domain.errors.toWallencException
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorageSyncEngine
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorageSyncEngine
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.ITaskOrchestrator
|
import com.github.nullptroma.wallenc.domain.tasks.ITaskOrchestrator
|
||||||
|
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskId
|
import com.github.nullptroma.wallenc.domain.tasks.TaskId
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskLogKey
|
import com.github.nullptroma.wallenc.domain.tasks.TaskLogKey
|
||||||
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLevel
|
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLevel
|
||||||
@@ -31,10 +32,10 @@ class RunStorageSyncUseCase @Inject constructor(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param displayTitle заголовок задачи в UI (локализованный на стороне вызова)
|
* @param displayTitle заголовок задачи в UI (локализованный на стороне вызова)
|
||||||
* @param logReason техническая метка для логов (не для UI)
|
* @param reason источник запуска — попадает в лог пайплайна
|
||||||
* @return false, если синхронизация уже в очереди или выполняется — новая задача не создана
|
* @return false, если синхронизация уже в очереди или выполняется — новая задача не создана
|
||||||
*/
|
*/
|
||||||
fun enqueue(displayTitle: String, logReason: String): Boolean {
|
fun enqueue(displayTitle: String, reason: StorageSyncTriggerReason): Boolean {
|
||||||
if (!running.compareAndSet(false, true)) {
|
if (!running.compareAndSet(false, true)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -45,36 +46,68 @@ class RunStorageSyncUseCase @Inject constructor(
|
|||||||
dispatcher = Dispatchers.IO,
|
dispatcher = Dispatchers.IO,
|
||||||
work = { ctx ->
|
work = { ctx ->
|
||||||
try {
|
try {
|
||||||
ctx.log(TaskLogLevel.Info, TaskLogKey.SyncStarted)
|
executeSync(
|
||||||
ctx.reportProgress(null, TaskProgressLabel.SyncStarted)
|
reason = reason,
|
||||||
syncEngine.syncAllGroups { fraction, label ->
|
reportProgress = { fraction, label ->
|
||||||
ctx.reportProgress(fraction, label)
|
ctx.reportProgress(fraction, label)
|
||||||
}
|
},
|
||||||
ctx.log(TaskLogLevel.Info, TaskLogKey.SyncFinished)
|
log = { level, key -> ctx.log(level, key) },
|
||||||
ctx.reportProgress(null, TaskProgressLabel.SyncCompleted)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
val err = e.toWallencException()
|
ctx.fail(e.toWallencException())
|
||||||
ctx.log(TaskLogLevel.Error, TaskLogKey.SyncFailed(err))
|
|
||||||
ctx.fail(err)
|
|
||||||
} finally {
|
} finally {
|
||||||
running.set(false)
|
clearRunningState()
|
||||||
_syncRunning.value = false
|
|
||||||
_activeSyncTaskId.value = null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
_activeSyncTaskId.value = taskId
|
_activeSyncTaskId.value = taskId
|
||||||
return true
|
return true
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
running.set(false)
|
clearRunningState()
|
||||||
_syncRunning.value = false
|
|
||||||
_activeSyncTaskId.value = null
|
|
||||||
throw t
|
throw t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun runBlocking() {
|
suspend fun runBlocking(reason: StorageSyncTriggerReason) {
|
||||||
|
if (!running.compareAndSet(false, true)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_syncRunning.value = true
|
||||||
|
try {
|
||||||
|
executeSync(
|
||||||
|
reason = reason,
|
||||||
|
reportProgress = { _, _ -> },
|
||||||
|
log = { level, key -> orchestrator.appendPipelineLog(level, key) },
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
clearRunningState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun executeSync(
|
||||||
|
reason: StorageSyncTriggerReason,
|
||||||
|
reportProgress: suspend (fraction: Float?, label: TaskProgressLabel?) -> Unit,
|
||||||
|
log: (TaskLogLevel, TaskLogKey) -> Unit,
|
||||||
|
) {
|
||||||
syncReadiness.awaitReady()
|
syncReadiness.awaitReady()
|
||||||
syncEngine.syncAllGroups()
|
log(TaskLogLevel.Info, TaskLogKey.SyncStarted(reason))
|
||||||
|
reportProgress(null, TaskProgressLabel.SyncStarted)
|
||||||
|
try {
|
||||||
|
syncEngine.syncAllGroups { fraction, label ->
|
||||||
|
reportProgress(fraction, label)
|
||||||
|
}
|
||||||
|
log(TaskLogLevel.Info, TaskLogKey.SyncFinished(reason))
|
||||||
|
reportProgress(null, TaskProgressLabel.SyncCompleted)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
val err = e.toWallencException()
|
||||||
|
log(TaskLogLevel.Error, TaskLogKey.SyncFailed(err, reason))
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearRunningState() {
|
||||||
|
running.set(false)
|
||||||
|
_syncRunning.value = false
|
||||||
|
_activeSyncTaskId.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user