Skip to content
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? Sign in to your account

Add backend support for cancellation #40

Open
willcrichton opened this issue Aug 23, 2024 · 0 comments
Open

Add backend support for cancellation #40

willcrichton opened this issue Aug 23, 2024 · 0 comments

Comments

@willcrichton
Copy link
Contributor

willcrichton commented Aug 23, 2024

Task

Functionality

In {{ 06-select pr }}, a colleague added support on the frontend for cancellation. A user can click a new "Cancel" button which will send a post request to the /cancel route. When this route is posted, then the server should cancel any query_chat computation that is currently running.

To handle the case of cancellation, the frontend now expects a new field in response from the /chat route. The response should have a type field that contains the string "Success" or "Cancelled". If the /cancel route is called while /chat is waiting on query_chat, then the /chat route should return {type: "Cancelled"}. Otherwise, it should return a success message like:

{
  "type": "Success",
  "messages": ["A message", "A response"]
}

Performance

The server should cancel running chat computations as soon as /cancel is called. To simplify this problem, we have reverted query_chat from being compute-bound to being I/O-bound.

Background

Serializing enums

If you want to represent a JSON data structure that can have one of two schemas (and you're using Serde), then check out Serde's internally-tagged enum representation.

Selecting from different futures

The join! macro is used when you want to wait for all of multiple futures to complete. Similarly, the select! macro lets you wait for one of multiple futures to complete. For example, you could implement a simple 1-second timeout like this:

async fn long_op() -> i32 {
    tokio::time::sleep(/* ... */).await;
    0
}

async fn long_op_timeout() -> Option<i32> {
    let op_fut = long_op();
    let sleep_fut = tokio::time::sleep(Duration::from_secs(1));
    tokio::select! {
        n = op_fut => Some(n),  // if op_fut returns, then return its value
        _ = sleep_fut => None   // if the sleep_fut returns, we've timed out
    }
}

select! has a bit of a specialized syntax, described in its docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant