feat: add an API to time out query executions

Currently, if a predicate is hard to match on the Rust side, a sizable
query against a very large file can take forever, and ends up hanging.
This commit adds an API function `ts_query_cursor_set_timeout_micros` to
limit how long query execution is allowed to take, thereby negating the
chance of a hang to occur.
This commit is contained in:
Amaan Qureshi 2024-08-29 17:21:52 -04:00
parent a748488596
commit 3f424c0121
11 changed files with 132 additions and 8 deletions

View file

@ -1,4 +1,4 @@
/* automatically generated by rust-bindgen 0.69.4 */
/* automatically generated by rust-bindgen 0.70.0 */
pub const TREE_SITTER_LANGUAGE_VERSION: u32 = 14;
pub const TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION: u32 = 13;
@ -462,7 +462,7 @@ extern "C" {
pub fn ts_tree_cursor_delete(self_: *mut TSTreeCursor);
}
extern "C" {
#[doc = " Re-initialize a tree cursor to start at a different node."]
#[doc = " Re-initialize a tree cursor to start at the original node that the cursor was\n constructed with."]
pub fn ts_tree_cursor_reset(self_: *mut TSTreeCursor, node: TSNode);
}
extern "C" {
@ -637,6 +637,14 @@ extern "C" {
extern "C" {
pub fn ts_query_cursor_set_match_limit(self_: *mut TSQueryCursor, limit: u32);
}
extern "C" {
#[doc = " Set the maximum duration in microseconds that query execution should be allowed to\n take before halting.\n\n If query execution takes longer than this, it will halt early, returning NULL.\n See [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] for more information."]
pub fn ts_query_cursor_set_timeout_micros(self_: *mut TSQueryCursor, timeout_micros: u64);
}
extern "C" {
#[doc = " Get the duration in microseconds that query execution is allowed to take."]
pub fn ts_query_cursor_timeout_micros(self_: *const TSQueryCursor) -> u64;
}
extern "C" {
#[doc = " Set the range of bytes or (row, column) positions in which the query\n will be executed."]
pub fn ts_query_cursor_set_byte_range(

View file

@ -2362,6 +2362,26 @@ impl QueryCursor {
}
}
/// Set the maximum duration in microseconds that query execution should be allowed to
/// take before halting.
///
/// If query execution takes longer than this, it will halt early, returning None.
#[doc(alias = "ts_query_cursor_set_timeout_micros")]
pub fn set_timeout_micros(&mut self, timeout: u64) {
unsafe {
ffi::ts_query_cursor_set_timeout_micros(self.ptr.as_ptr(), timeout);
}
}
/// Get the duration in microseconds that query execution is allowed to take.
///
/// This is set via [`set_timeout_micros`](QueryCursor::set_timeout_micros).
#[doc(alias = "ts_query_cursor_timeout_micros")]
#[must_use]
pub fn timeout_micros(&self) -> u64 {
unsafe { ffi::ts_query_cursor_timeout_micros(self.ptr.as_ptr()) }
}
/// Check if, on its last execution, this cursor exceeded its maximum number
/// of in-progress matches.
#[doc(alias = "ts_query_cursor_did_exceed_match_limit")]