Handling Thread.interrupts
Hello @rbygrave ,
In our application, we have a scheduler that starts multiple threads in parallel for various tasks that can be completed independently of each other (e.g. importing customers, evaluating user logins, etc.). It's also possible for users to cancel/abort such tasks in the UI. Aborting involves the scheduler sending an interrupt signal to the Java threads. We have the problem that the threads often just keep running and don't notice the interrupt because they're busy executing DB actions.
We've been considering whether it would be useful to implement a mechanism in a very central location in ebean and/or ebean-datasource that detects whether the thread has been interrupted and:
- If there isn't an open transaction yet, it would prevent ebean-datasource from releasing the connection: https://github.com/FOCONIS/ebean-datasource/pull/7
- If you're working in an open (large) transaction, you won't be able to access the internal connection: https://github.com/FOCONIS/ebean/pull/122
We'd like to ask for your opinion on what you would do regarding interrupts. Are we thinking in the right direction? We've read this article regarding Thread.interrupt(): https://medium.com/@AlexanderObregon/javas-thread-interrupt-method-explained-0df0f8f6a428
What does busy executing DB actions mean? The linked changes are within connection methods so they are clearly outside the code that waits for a SQL query to complete. This gives me the impression that you do not mean SQL query exection when saying DB actions.
Why does your thread managed by your scheduler does not check for the interrupt state between your "db actions" so it can terminate once the most recent DB action has been completed? Interruption does not have to be instant. At least that is what I do in a thread I know can take longer. I split the work into logical chunks and between these chunks I check the interrupt state regularly just liked described in your linked article.
If you are in a situation that the SQL query itself is slow (e.g. data warehouse) the linked changes won't help, right? For this situation you have to call Statement.cancel() and hope that the JDBC driver you are using has it implemented. PostgreSQL for example has it implemented. If not, the DB likely have a different mechanism to stop queries programmatically via some non-JDBC API. You would call Statement.cancel() from a second watchdog thread which monitors the interrupted state of your scheduler thread. The javadoc of Statement.cancel() explicitly mentions that they would expect it being called from a different thread.
I don't see this as an Ebean issue. If a long running transaction needs some sort of cancel mechanism then you can make the transaction available to the application code, and hence the underlying java.sql.Connection available to application code ... and the application code can then look to cancel queries etc.
Aborting involves the scheduler sending an interrupt signal to the Java threads.
Assuming I'm understanding this, a "Background Job System" would have "Jobs" that have awareness that they can be cancelled and that means if they are a very long running multi-step process that they check their "should this job continue" status periodically as they progress a job. So in that sense, no that wouldn't really rely on Thread interrupts but more ... job periodic callbacks (to check its continue/cancelled status).