duckdb-rs icon indicating copy to clipboard operation
duckdb-rs copied to clipboard

Allow `Connection` to be interrupted

Open rebasedming opened this issue 1 year ago • 7 comments

Closes #342

Allows the Connection to be interrupted, which is useful for cancelling long-running queries.

rebasedming avatar Jun 20 '24 02:06 rebasedming

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.

rebasedming avatar Jun 20 '24 13:06 rebasedming

Could you merge this with main, and perhaps also add a test for this functionality?

Mytherin avatar Jul 10 '24 07:07 Mytherin

Yes, I got distracted with other things the last few weeks. I'll finish up this PR.

rebasedming avatar Jul 12 '24 21:07 rebasedming

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 Connection is moved to a thread, it can't really be called from another thread. For instance, the following code won't compile because db is moved to the thread and you can't call interrupt on it afterward.

  #[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(())
  }

rebasedming avatar Jul 12 '24 23:07 rebasedming

That idea for a test sounds good to me.

Unfortunately, once a Connection is moved to a thread, it can't really be called from another thread. For instance, the following code won't compile because db is moved to the thread and you can't call interrupt on it afterward.

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 interrupt from a different thread?

Mytherin avatar Jul 13 '24 11:07 Mytherin

That idea for a test sounds good to me.

Unfortunately, once a Connection is moved to a thread, it can't really be called from another thread. For instance, the following code won't compile because db is moved to the thread and you can't call interrupt on it afterward.

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 interrupt from a different thread?

In practice, I've stored the Connection in a static global. I can do the same for the tests if you're comfortable with it?

rebasedming avatar Jul 13 '24 16:07 rebasedming

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?

Mytherin avatar Jul 15 '24 13:07 Mytherin