| 4 | |
| 5 | I have been thinking a bit of this. It is not trivial since it requires that the plug-in is willing to be killed. |
| 6 | |
| 7 | There are two main approaches: |
| 8 | |
| 9 | '''1. Send a signal using the Thread class''' |
| 10 | |
| 11 | * The BASE core is calling {{{Thread.interrupt()}}} on the thread that is executing the plug-in. |
| 12 | * The plug-in must regularly check {{{Thread.interrupted()}}}. If this return true, it should stop what it is doing, rollback any changes and exit. |
| 13 | * The call to {{{Thread.interrupt()}}} may also throw an InterruptedException if the plug-in is waiting in a blocking call. |
| 14 | |
| 15 | There are a number of problems with this approach: |
| 16 | |
| 17 | * Plug-ins must be aware of this and be coded to check the Thread.interrupted() status and be able to act on it. Most plug-ins today are not coded like this. |
| 18 | * If the plug-in is running on a job agent the kill signal must be communicated to the job agent first. The problem is that the only way to know which job agent a plug-in is running on is to ask all of them. |
| 19 | * Plug-ins may be running on something else that we don't know of. |
| 20 | |
| 21 | Possible solutions to the above problems include: |
| 22 | |
| 23 | * Create a tagging interface: {{{Killable}}}. If a plug-in implements this interface it must also promise to check and act on the {{{Thread.interrupted()}}} status. The core (and web client) will know if a plug-in is killable or not and doesn't have to put up a "Kill" button for those plug-ins that aren't killable. |
| 24 | |
| 25 | * Store some kind of callback hook in the database. A callback hook is registered by the application that is starting the job (ie. internal job queue, job agent, etc.). If no hook has been registered for a job, it can't be killed (even if it implements the {{{Killable}}} interface). The core could provide simple implementations for "same-process-hook" and "external-process-hook". |
| 26 | |
| 27 | |
| 28 | '''2. Send a signal using the ProgressReporter''' |
| 29 | |
| 30 | The idea is that since most plug-ins already regularly reports their progress, the same mechanism could be used to convey information in the other direction. This could be implemented as a flag in the Jobs table. The flag is set when a user clicks the "Kill" button in the web interface. When the progress reporter is about to update the status, it could just as well check this flag and throw an exception if it has been set. |
| 31 | |
| 32 | The good thing with this solution is that it requires no (or very little) cooperation from the plug-in side or from the job agent side. Plug-ins should already be prepared to handle exceptions properly (rollback, cleanup and exit). |
| 33 | |
| 34 | There are some problems also: |
| 35 | |
| 36 | * Plug-ins are not required to use the progress reporter at all, and even if they do, there may be long intervals between the updates. For example, the {{{Base1PluginExecuter}}} doesn't update the progress when the external plug-in code is running, thus it would only be possible to kill this plug-in during the data export or import phase. |
| 37 | |
| 38 | |
| 39 | '''Note'''! The ability to kill a plug-in via the progress reporter could just be a special hook in solution 1 above. The {{{Killable}}} interface could have one method where the core could query the plug-in if it should use the thread or the progress reporter to kill it. |
| 40 | |