thunderbird / thunderbird/thunderbird-android
Handle failing 'pending commands'
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 14k
- Forks
- 2.8k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 57
Description
Whenever K-9 Mail is asked to modify a message (e.g. mark as read, move to another folder), the local message is updated and a PendingCommand is created that describes the operation to be performed on the server. This queue of pending commands is persisted in the database because it might be a while before the device is online again and the operations can be performed on the server.
When the queue is processed there's currently three error cases that can occur:
- The command fails with a
MessagingExceptionwithisPermanentFailure()returningtrue. This happens when the backend is sure repeating the command won't change the outcome (failure). In that case the command is removed from the queue and the next command is processed. - The command fails with a
MessagingExceptionwithisPermanentFailure()returningfalse. This can happen on e.g. network errors or authentication failures. In this case processing the queue is halted. The assumption is that all other commands will fail, too. - The command fails with any other exception. In this case processing the queue is halted. This case isn't explicitly handled. An outer layer catches
Exceptionand prevents the app from crashing.
The problem with the current approach is that (repeatedly) failing commands that are not removed from the queue will block it forever. Every time the queue is processed (e.g. before a sync) the command will fail and all following commands will never be executed. The local changes will still be made. So in K-9 Mail it looks like everything is working fine.
The problem with removing failing commands is that we currently don't revert local changes or notify the user about the error.
In theory there could also be dependencies between commands in the queue (a later command depends on the successful execution of a previous command). I'm not sure we currently support such a scenario. But it's something to be aware of. And it's something that makes removing commands from the queue without causing additional issues much more work.
I think a good first step would be to remove each command that is failing with anything other than a MessagingException (we might have to handle IOException like MessagingException with isPermanentFailure() returning false because backends might not wrap them).
Without reverting the local change and notifying the user it's not great. But it's strictly better than blocking the pending commands queue forever.
Suggestions for a strategy to properly handle failing pending commands are very welcome.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue does not name a file or test. Start by locating the pending-command queue processing and its exception handling; compare the three failure cases described, then verify that non-MessagingException failures no longer block later commands while rollback, user notification, and command dependencies remain explicit follow-up concerns.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100