-
Notifications
You must be signed in to change notification settings - Fork 158
Allow Connection
to be interrupted
#343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub 8000 ? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please get some tests and docs added? And remove the dsstore files
Yep! Put this up hastily to see if there was appetite for this functionality. I can clean it up now and add tests if there is. |
Could you merge this with main, and perhaps also add a test for this functionality? |
Yes, I got distracted with other things the last few weeks. I'll finish up this PR. |
Hey @Mause @Mytherin, I could use your input on how you'd like to see this tested. What I'm envisioning is spawning a long-running query in one thread, and then interrupting the same connection from another thread. Unfortunately, once a #[test]
fn test_interrupt() -> Result<()> {
let db = checked_memory_handle();
let query_handle = std::thread::spawn(move || {
let mut stmt = db.prepare("CREATE TABLE foo AS SELECT generate_series(1, 10000000) AS id;")?;
stmt.execute([])?;
Ok(())
});
db.interrupt();
let query_result: Result<(), Error> = query_handle.join().unwrap();
assert!(query_result.is_err());
Ok(())
} |
That idea for a test sounds good to me.
I'm not too familiar with Rust specifics - but how do you envision this method to be used in practice if this is not possible? Maybe there needs to be some annotation that signifies it is safe to call |
In practice, I've stored the |
If the tests are completely stand-alone I don't mind - but ideally we don't ship any static globals. Is there no other way? |
This PR adds an `InterruptHandle` that allows interrupting long-running queries from another thread. Internally, this calls the `duckdb_interrupt` function from the C API. The implementation is inspired by [rusqlite][1]. It seems to get the job done, but a couple of thoughts: 1. Testing the interrupts is a bit tricky. I wasn't able to come up with a deterministic approach, so I took inspiration from tests in other client API: simply kick off an expensive query and interrupt it. 2. Unfortunately, the error code returned on interrupt is `ErrorCode::Unknown`, so we have to resort to a match on the error message. Works for now, but I'm wondering if there is a way to do this in a cleaner way, or if the actual error code is simply not exposed from the underlying API. 3. I'm not very familiar with the safety aspects of interfacing with the C API, so a critical pair of eyes is welcome. Previous attempt at adding this feature: #343. [1]: https://docs.rs/rusqlite/latest/rusqlite/struct.InterruptHandle.html
Superseded by #493 |
Closes #342
Allows the
Connection
to be interrupted, which is useful for cancelling long-running queries.