pub struct Cancel { /* private fields */ }Expand description
A reason for a running query to stop, which is either somebody asking or a clock running out.
Cheap to clone, and a clone shares the flag with the token it came from, so one thread can stop
a query another thread is running. The deadline is not shared, because a deadline belongs to one
statement and the flag belongs to whoever is allowed to interrupt: see Cancel::restart.
§How a query notices
Cancel::check between chunks, and nowhere else, which is what
spec/engine/10-scheduler.md section 10.9 asks for. That is a real limit and it is the one worth
having: an operator cannot notice halfway through a chunk without a branch in the inner loop over
values, and a thousand rows of arithmetic is microseconds, so the response time this gives is
already below anything a person can see. What it does not cover is an operator that spends an
unbounded time inside one call without pulling a chunk from below it, and there is none, because
every loop in rudb-exec that can run long runs by pulling chunks.
§Why the flag is read relaxed
The only thing a reader does with it is stop, and nothing it reads afterwards has to have been written before the flag was set. A relaxed load on one location is still coherent, so a query that is running when the flag is set sees it on the next chunk or the one after, and a query that has already finished does not care. An acquire load here would cost a fence per chunk to order writes that do not exist.
Implementations§
Source§impl Cancel
impl Cancel
Sourcepub fn restart(&self, timeout: Option<Duration>) -> Cancel
pub fn restart(&self, timeout: Option<Duration>) -> Cancel
The same flag, a fresh clock, and this time limit.
What a connection does at the top of each statement. The flag is shared, so a caller holding the connection’s token can still stop the new statement, and the clock starts now, so a timeout is a limit on this statement rather than on the connection’s whole life.
It clears the flag as well, which means an interrupt that arrives between two statements is dropped rather than killing the next one. That is the same thing DuckDB does and it is the right way round: an interrupt is about the query the person is watching, and carrying one forward would stop a statement nobody asked to stop.
Sourcepub fn cancel(&self)
pub fn cancel(&self)
Stop whatever is running on this token.
Returns immediately. The query stops at its next chunk boundary, so a caller that wants to know it has stopped waits for the query’s own thread to return an error.
Sourcepub fn is_cancelled(&self) -> bool
pub fn is_cancelled(&self) -> bool
Whether the query should stop.
Sourcepub fn check(&self) -> Result<(), Error>
pub fn check(&self) -> Result<(), Error>
An error when the query should stop, and nothing when it should keep going.
The two reasons produce different sentences, because they are different things to a person reading a log: one of them says somebody pressed a key and the other says the query needed more time than it was given, and a timeout reported as an interrupt sends whoever reads it looking for a person who was not there.
§Errors
crate::ErrorCode::Interrupt when the flag is set or the time is up.