Fix sync worker stall on persistent errors#1305
Open
Left024 wants to merge 3 commits into
Open
Conversation
- SyncWorker: cap retry at 3 attempts, then fail to let periodic reset; use accountId from inputData to dispatch correct service type - ReaderWorker: cap retry to avoid blocking POST_SYNC_WORK chain indefinitely - AbstractRssRepository: extract reschedulePeriodicWork() for reuse - AccountViewModel: reschedule periodic tasks immediately after account switch or sync setting change - FeverRssService: use retry instead of failure for consistency
- SyncWorker.enqueuePeriodicWork: use CANCEL_AND_REENQUEUE for ENQUEUED state (only keep UPDATE for RUNNING), so that lastEnqueueTime is reset to current system time on every app start - WidgetUpdateWorker.enqueuePeriodicWork: same treatment - This prevents a one-time clock anomaly from permanently polluting the nextScheduleTimeMillis (symptom: always showing Aug 17 regardless of real date)
- AbstractRssRepository: clearKeepArchivedArticles 接受 accountId 参数;initSync 遍历所有账户独立调度 - SyncWorker: doWork 顶捕异常;POST_SYNC_WORK 传递 accountId;一次性任务 setExpedited;抽取 schedule 构建逻辑 - ReaderWorker: 注入 AccountService;从 inputData 读取 accountId 兼容旧任务回退 - AndroidApp: 注册 NetworkCallback,网络恢复时触发一次性同步 - AndroidManifest: 添加 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限 - NotificationHelper: InboxStyle 展示标题列表;setAutoCancel;确定性通知 ID - ContextExt: 新增电池优化状态检查与设置跳转扩展 - AccountViewModel: 删除账户后重建周期同步;修复局部变量命名歧义 - TroubleshootingPage: 新增电池优化状态卡片;修复 nextScheduledMillis 异常崩溃 - strings: 新增电池优化相关字符串(中英文)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Credits
This change was made by DeepSeek V4 Pro and has been manually tested by @Left024 on device — verified working correctly.
Problem
When background sync encounters an error (e.g., FreshRSS credentials expire, network issues), the SyncWorker enters infinite exponential backoff (capped at 5h). Users experience this as "auto-refresh stopped working completely" — it never recovers until manual refresh or app restart.
Additional issues:
Root Cause
sync()returnsResult.Retry()→ WorkManager exponential backoff. Each retry doubles the wait, permanently suspending the normal sync interval rhythmenqueuePeriodicWorkbakesaccountIdintoinputData, butdoWork()usesrssService.get()(current account type) — cross-account dispatch fails with type checksPOST_SYNC_WORKnever completes → subsequent syncs can't enqueue new ReaderWorker/WidgetUpdateWorkerinitSync()Changes
Result.Failure— for periodic tasks this triggersresetPeriodic(), allowing the next sync interval to proceed normally. Also injectingAccountServiceto dispatch byinputData.accountIdinstead of current accountPOST_SYNC_WORKchain indefinitely; missing full content will be re-fetched by the next sync cyclereschedulePeriodicWork(account)frominitSync()for external reusereschedulePeriodicWorkimmediately on account switch and sync setting changes, no longer requires app restartResult.Failure()toResult.Retry()for behavior consistency with Local/GoogleReaderAdditional Improvements (2026-07-22)
Based on testing and further analysis, these incremental changes enhance sync reliability and user experience:
SyncWorker & AbstractRssRepository
initSync()now iterates all accounts (not just the current one), enqueuing periodic work for each — ensures all accounts get synced after app restartdoWork()wrapped in try-catch to prevent unhandled exceptions from crashing the workerPOST_SYNC_WORKchain passesaccountIdtoReaderWorkerfor correct account dispatchsetExpedited()for faster executionenqueuePeriodicWorkschedule constraints extracted into a reusable builderReaderWorker
AccountServiceinjected to resolve account type frominputData.accountId, with fallback to current account for backward compatibility with old tasksNetwork Recovery (AndroidApp.kt)
NetworkCallbackthat triggers a one-shot sync when network becomes available after a disconnect — prevents missed sync windows when offlineBattery Optimization (AndroidManifest + ContextExt + TroubleshootingPage)
REQUEST_IGNORE_BATTERY_OPTIMIZATIONSpermission to both manifestsisIgnoringBatteryOptimizations()andopenBatteryOptimizationSettings()extension functionsnextScheduledMillis(shows "N/A")Notifications (NotificationHelper.kt)
InboxStyleto display article title listsetAutoCancel(true)for automatic dismissalarticle.id.hashCode()) instead of random numbersAccountViewModel
rssService→rssRepoto disambiguate from member propertyStrings
Files Updated (both commits combined)