Something like ranger's task window, where for instance statuses of yet unsent (due to poor network for example) outgoing messages would be displayed, perhaps with the possibility to cancel or edit them, could be nice. #84 could also profit from this. Other background tasks could be displayed there as well.
Some further ideas:
I'm thinking that perhaps a new
TaskManager
could be introduced which would keep track of relevant background tasks. Instead of backgrounding tasks manually usinggo func()
, one would instead callTaskManager.New(func, chan)
which would runfunc
in goroutine and usechan
to receive status messages messages from it, which would then be accessible to the user in the task view. I imagine the latest message would be displayed at the given task in the task view plus it could be forwarded to the status line (app.PushStatus/Error
) for some duration.If the task failed the user could try to run it again through the task view and perhaps there could even be some more parameters (like a map mapping an action description (
string
) to the function which would be invoked -- this could be different for while the task is still runnning and while it has already exited) toTaskManager.New
which would allow the user to take more actions on a task, both while it is in progress and when it fails.I think this could make sense for many things in aerc, although of course not everything that gets background deserves to be called "a task" and get its own slot in the task view -- or does it? I can for example imagine that the actions of workers could be shown there, perhaps it could be made possible to pause polling an IMAP/JMAP server for new emails through it.
However, what originally gave me this idea was sending of messages: right now when I send a message, the "Sending" status is displayed, however one of my servers gives me a "logged out" error every 30 seconds which overwrites the status and if I look away, I cannot discern if it is still sending or not, until the "Message sent" status appears (one way would be to try to exit aerc). And if it does not appear, it is not clear whether the message is still pending or whether the status has already appeared and has been overwritten by the server error. Of course, it usually does not take too long before the sending failure is indicated by the composer being reopened and, conversely, the presence of the message in the sent folder can be taken as indication that sending was successful, but it is really not clear for bouncing (which is currently being implemented) for instance.
I imagine that in this case (sending), the task would be backgrounded and the user could see the task view to find out the status. The status messages which are now shown in the status bar would stay the same except they would be sent there by the
TaskManager
which would also display the latest message in the appropriate task slot in the task view. If there was an error, the auxilary actions permitted to the user here could be either to attempt to resend or to reopen the composer, which would no longer happen automatically. Or perhaps even copy the message to drafts. Similarly for bouncing: if it failed, the user would know even if he walked away from the computer for those 10 seconds when the relevant error was displayed, plus he could rerun the function with the same arguments to attempt again, instead of having to invoke:bounce
again manually (although that would probably not be too much work as the precise command line would be saved in his command history).So to sum up, I think the main advantages of this feature would be the ability to clearly discern which status message was produced by what task and to explicitly check the status of a task even after the usual duration for which the status message is shown in the status bar has elapsed. Plus it would give more options and a common interface for influencing things running in the background, both before and after they have finished (successfully or not).
The notion of
TaskManager
sounds like something that could already exist so it might be a good idea to check whether part of the implementation of this could be delegated to some library.Also, the task view could store all the status messages produced by a task, just as they are now logged, so the user could view the whole progress with timestamps even. Also, not all messages would have to be forwarded to the status bar -- perhaps some integration with
log
could even be implemented as it seems there are some shared traits.I don't know if people usually run aerc for longer periods of time, if so, it could be made possible to remove finished/failed task from the view (and thus the manager) manually or to limit their amount/age.
This sounds really nice.
Maybe there could even be some task hiearchy, such as if the workers run several subtasks at once, but it shouldn't get too complicated.
Also, I forgot to mention (although it's in the original post) that the tasks should also ideally be stoppable, although that would probably require some cooperation from the tasks as I don't think it's quite possible to just stop a goroutine. But that would not be a good idea anyway, usually some clean up would be necessary, so the tasks would probably have to listen on a channel for a signal to exit prematurely. As such, there would probably be just a few exit points where the task would check if abort was requested and it would probably not be possible to force the task to exit in an arbitrary moment.
Maybe there could even be some task hiearchy, such as if the workers run several subtasks at once, but it shouldn't get too complicated.
If you use contexts, the task hierarchy is build into the context structures.
Also, I forgot to mention (although it's in the original post) that the tasks should also ideally be stoppable, although that would probably require some cooperation from the tasks as I don't think it's quite possible to just stop a goroutine. But that would not be a good idea anyway, usually some clean up would be necessary, so the tasks would probably have to listen on a channel for a signal to exit prematurely. As such, there would probably be just a few exit points where the task would check if abort was requested and it would probably not be possible to force the task to exit in an arbitrary moment.
Did you have a look at https://git.sr.ht/~sircmpwn/dowork? This seems useful for dispatching, scheduling, restarting of failed tasks etc. and appears to cover most of the requirements.
Thank you for the tips! In particular, the library does indeed seem to handle many of the presented ideas.