fix: webdav backup resume and modal problem
This commit is contained in:
parent
d0cb333f3c
commit
8cb11e6d55
@ -60,14 +60,25 @@ export async function reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 备份到 webdav
|
// 备份到 webdav
|
||||||
|
/**
|
||||||
|
* @param autoBackupProcess
|
||||||
|
* if call in auto backup process, not show any message, any error will be thrown
|
||||||
|
*/
|
||||||
export async function backupToWebdav({
|
export async function backupToWebdav({
|
||||||
showMessage = false,
|
showMessage = false,
|
||||||
customFileName = ''
|
customFileName = '',
|
||||||
}: { showMessage?: boolean; customFileName?: string } = {}) {
|
autoBackupProcess = false
|
||||||
|
}: { showMessage?: boolean; customFileName?: string; autoBackupProcess?: boolean } = {}) {
|
||||||
if (isManualBackupRunning) {
|
if (isManualBackupRunning) {
|
||||||
Logger.log('[Backup] Manual backup already in progress')
|
Logger.log('[Backup] Manual backup already in progress')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// force set showMessage to false when auto backup process
|
||||||
|
if (autoBackupProcess) {
|
||||||
|
showMessage = false
|
||||||
|
}
|
||||||
|
|
||||||
|
isManualBackupRunning = true
|
||||||
|
|
||||||
store.dispatch(setWebDAVSyncState({ syncing: true, lastSyncError: null }))
|
store.dispatch(setWebDAVSyncState({ syncing: true, lastSyncError: null }))
|
||||||
|
|
||||||
@ -98,25 +109,41 @@ export async function backupToWebdav({
|
|||||||
lastSyncError: null
|
lastSyncError: null
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
showMessage && window.message.success({ content: i18n.t('message.backup.success'), key: 'backup' })
|
if (showMessage && !autoBackupProcess) {
|
||||||
|
window.message.success({ content: i18n.t('message.backup.success'), key: 'backup' })
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// if auto backup process, throw error
|
||||||
|
if (autoBackupProcess) {
|
||||||
|
throw new Error(i18n.t('message.backup.failed'))
|
||||||
|
}
|
||||||
|
|
||||||
store.dispatch(setWebDAVSyncState({ lastSyncError: 'Backup failed' }))
|
store.dispatch(setWebDAVSyncState({ lastSyncError: 'Backup failed' }))
|
||||||
window.message.error({ content: i18n.t('message.backup.failed'), key: 'backup' })
|
showMessage && window.message.error({ content: i18n.t('message.backup.failed'), key: 'backup' })
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// if auto backup process, throw error
|
||||||
|
if (autoBackupProcess) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
store.dispatch(setWebDAVSyncState({ lastSyncError: error.message }))
|
store.dispatch(setWebDAVSyncState({ lastSyncError: error.message }))
|
||||||
console.error('[Backup] backupToWebdav: Error uploading file to WebDAV:', error)
|
console.error('[Backup] backupToWebdav: Error uploading file to WebDAV:', error)
|
||||||
|
showMessage &&
|
||||||
window.modal.error({
|
window.modal.error({
|
||||||
title: i18n.t('message.backup.failed'),
|
title: i18n.t('message.backup.failed'),
|
||||||
content: error.message
|
content: error.message
|
||||||
})
|
})
|
||||||
|
throw error
|
||||||
} finally {
|
} finally {
|
||||||
|
if (!autoBackupProcess) {
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
setWebDAVSyncState({
|
setWebDAVSyncState({
|
||||||
lastSyncTime: Date.now(),
|
lastSyncTime: Date.now(),
|
||||||
syncing: false
|
syncing: false
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
}
|
||||||
isManualBackupRunning = false
|
isManualBackupRunning = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +176,7 @@ let syncTimeout: NodeJS.Timeout | null = null
|
|||||||
let isAutoBackupRunning = false
|
let isAutoBackupRunning = false
|
||||||
let isManualBackupRunning = false
|
let isManualBackupRunning = false
|
||||||
|
|
||||||
export function startAutoSync() {
|
export function startAutoSync(immediate = false) {
|
||||||
if (autoSyncStarted) {
|
if (autoSyncStarted) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -165,9 +192,15 @@ export function startAutoSync() {
|
|||||||
|
|
||||||
stopAutoSync()
|
stopAutoSync()
|
||||||
|
|
||||||
scheduleNextBackup()
|
scheduleNextBackup(immediate ? 'immediate' : 'fromLastSyncTime')
|
||||||
|
|
||||||
function scheduleNextBackup() {
|
/**
|
||||||
|
* @param type 'immediate' | 'fromLastSyncTime' | 'fromNow'
|
||||||
|
* 'immediate', first backup right now
|
||||||
|
* 'fromLastSyncTime', schedule next backup from last sync time
|
||||||
|
* 'fromNow', schedule next backup from now
|
||||||
|
*/
|
||||||
|
function scheduleNextBackup(type: 'immediate' | 'fromLastSyncTime' | 'fromNow' = 'fromLastSyncTime') {
|
||||||
if (syncTimeout) {
|
if (syncTimeout) {
|
||||||
clearTimeout(syncTimeout)
|
clearTimeout(syncTimeout)
|
||||||
syncTimeout = null
|
syncTimeout = null
|
||||||
@ -185,10 +218,15 @@ export function startAutoSync() {
|
|||||||
// 用户指定的自动备份时间间隔(毫秒)
|
// 用户指定的自动备份时间间隔(毫秒)
|
||||||
const requiredInterval = webdavSyncInterval * 60 * 1000
|
const requiredInterval = webdavSyncInterval * 60 * 1000
|
||||||
|
|
||||||
// 如果存在最后一次同步WebDAV的时间,以它为参考计算下一次同步的时间
|
let timeUntilNextSync = 1000 //also immediate
|
||||||
const timeUntilNextSync = webdavSync?.lastSyncTime
|
switch (type) {
|
||||||
? Math.max(1000, webdavSync.lastSyncTime + requiredInterval - Date.now())
|
case 'fromLastSyncTime': // 如果存在最后一次同步WebDAV的时间,以它为参考计算下一次同步的时间
|
||||||
: requiredInterval
|
timeUntilNextSync = Math.max(1000, (webdavSync?.lastSyncTime || 0) + requiredInterval - Date.now())
|
||||||
|
break
|
||||||
|
case 'fromNow':
|
||||||
|
timeUntilNextSync = requiredInterval
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
syncTimeout = setTimeout(performAutoBackup, timeUntilNextSync)
|
syncTimeout = setTimeout(performAutoBackup, timeUntilNextSync)
|
||||||
|
|
||||||
@ -207,14 +245,62 @@ export function startAutoSync() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAutoBackupRunning = true
|
isAutoBackupRunning = true
|
||||||
|
const maxRetries = 4
|
||||||
|
let retryCount = 0
|
||||||
|
|
||||||
|
while (retryCount < maxRetries) {
|
||||||
try {
|
try {
|
||||||
console.log('[AutoSync] Starting auto backup...')
|
console.log(`[AutoSync] Starting auto backup... (attempt ${retryCount + 1}/${maxRetries})`)
|
||||||
await backupToWebdav({ showMessage: false })
|
|
||||||
} catch (error) {
|
await backupToWebdav({ autoBackupProcess: true })
|
||||||
console.error('[AutoSync] Auto backup failed:', error)
|
|
||||||
} finally {
|
store.dispatch(
|
||||||
|
setWebDAVSyncState({
|
||||||
|
lastSyncError: null,
|
||||||
|
lastSyncTime: Date.now(),
|
||||||
|
syncing: false
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
isAutoBackupRunning = false
|
isAutoBackupRunning = false
|
||||||
scheduleNextBackup()
|
scheduleNextBackup()
|
||||||
|
|
||||||
|
break
|
||||||
|
} catch (error: any) {
|
||||||
|
retryCount++
|
||||||
|
if (retryCount === maxRetries) {
|
||||||
|
console.error('[AutoSync] Auto backup failed after all retries:', error)
|
||||||
|
|
||||||
|
store.dispatch(
|
||||||
|
setWebDAVSyncState({
|
||||||
|
lastSyncError: 'Auto backup failed',
|
||||||
|
lastSyncTime: Date.now(),
|
||||||
|
syncing: false
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
//only show 1 time error modal, and autoback stopped until user click ok
|
||||||
|
await window.modal.error({
|
||||||
|
title: i18n.t('message.backup.failed'),
|
||||||
|
content: `[WebDAV Auto Backup] ${new Date().toLocaleString()} ` + error.message
|
||||||
|
})
|
||||||
|
|
||||||
|
scheduleNextBackup('fromNow')
|
||||||
|
isAutoBackupRunning = false
|
||||||
|
} else {
|
||||||
|
//Exponential Backoff with Base 2: 7s、17s、37s
|
||||||
|
const backoffDelay = Math.pow(2, retryCount - 1) * 10000 - 3000
|
||||||
|
console.log(`[AutoSync] Failed, retry ${retryCount}/${maxRetries} after ${backoffDelay / 1000}s`)
|
||||||
|
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, backoffDelay))
|
||||||
|
|
||||||
|
//in case auto backup is stopped by user
|
||||||
|
if (!isAutoBackupRunning) {
|
||||||
|
console.log('[AutoSync] retry cancelled by user, exit')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user