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

Avoid using errors to communicate the state of other shards to the leader during query-status API. #1520

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

cberkhoff
Copy link
Collaborator

@cberkhoff cberkhoff commented Jan 10, 2025

Before this change, when the leader shard received a query-status API, it would call a match-status API on its shards, which would return an error if the state was different. The error contained the status of each shard, that the leader would use to compute the overall helper state. This wasn't the intended behavior, and was only done as a stop-gap solution, because the Transport::send (and consequently Transport::broadcast) returned unit "()", prohibiting from receiving the state from other shards. This PR changes this:

  • Transport::send now returns a configurable associated type for all requests (Transport::SendReponse)
  • MPC Query Status HTTP server handle was re-used as a Shard API. Match-status API is gone.
  • HTTP client query-status API can return either a QueryStatus object for compatibility or a BodyStream.
  • Processor now simply broadcast query-status API and compiles the results. Errors are handles as before. Previously used helper functions to cast the errors are gone. Tests were updated.
  • Added some calls to query-status in HTTP tests, to make sure the parsing is fine and that the changes work end-to-end.

I also tried a bunch of things so that Transport::send would return a specific type, bound to the route, but it all seemed very complex. The goal was that QueryStatus route would return a QueryStatusResponse, the rest could just return unit. That task can be tackled separately in the future.

Copy link
Collaborator

@akoshelev akoshelev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better than what we have right now, but would love @andyleiserson opinion on this. Particularly the changes to transport API

type RecordsStream: BytesStream;
/// The type used for responses to [`send`] and [`broadcast`].
type SendResponse: BytesStream;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this is the right way to do it. Send requests could be very different in nature and may not have the common response type. One may return a json while others can return a stream. Ideally, the return type should be defined by R: RouteParams trait but I am not sure if I have a suggestion how to use it here

/// # Errors
///
/// If the `BytesStream` cannot be collected into a `BytesMut`, an error is returned.
pub async fn from_bytesstream<B: BytesStream>(value: B) -> Result<HelperResponse, BoxError> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub async fn from_bytesstream<B: BytesStream>(value: B) -> Result<HelperResponse, BoxError> {
pub async fn from_bytes_stream<B: BytesStream>(value: B) -> Result<HelperResponse, BoxError> {

///
/// If the `BytesStream` cannot be collected into a `BytesMut`, an error is returned.
pub async fn from_bytesstream<B: BytesStream>(value: B) -> Result<HelperResponse, BoxError> {
let bytes: bytes::BytesMut = value.try_collect().await?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember this API in detail, but is BytesMut required or Bytes would work too?

Self { body: v }
}
}

impl From<HelperResponse> for QueryStatus {
fn from(value: HelperResponse) -> Self {
let response: QueryStatusResponse = serde_json::from_slice(value.body.as_ref()).unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is likely a fallible conversion, so a method on HelperResponse will do better imo. Or a TryFrom implementation

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

Successfully merging this pull request may close these issues.

2 participants