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

V1: Initial server implementation #593

Merged
merged 16 commits into from
Oct 18, 2023
Merged

V1: Initial server implementation #593

merged 16 commits into from
Oct 18, 2023

Conversation

smaye81
Copy link
Member

@smaye81 smaye81 commented Oct 13, 2023

This adds a first attempt at the reference implementation for a conformance server.

It adds the full implementation of all endpoints as well as an ability to run it via cmd/server/main.go.

internal/app/server/impl.go Outdated Show resolved Hide resolved
@smaye81 smaye81 requested a review from jhump October 13, 2023 17:48
cmd/server/main.go Outdated Show resolved Hide resolved
Comment on lines 32 to 33
h1Port := flag.String("h1Port", "8080", "port for HTTP/1.1 traffic")
h2Port := flag.String("h2Port", "8081", "port for HTTP/2 traffic")
Copy link
Member

Choose a reason for hiding this comment

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

I apologize that I did not put any details in the design doc about how the server is supposed to work. I had it in my head and failed to actually write it down 🤦.

There was some context about it in the doc, but it was very unclear. I can remedy that and revise the doc. In the meantime, it was supposed to work like this, where the messages sent to/from the server are these.

Copy link
Member Author

Choose a reason for hiding this comment

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

Gotcha. My approach for this was to mainly just be able to get the server running and get the logic for each endpoint sound. I was thinking of expanding on how the server is actually fed the test cases in follow-up PRs if that's OK.

Copy link
Member

Choose a reason for hiding this comment

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

Absolutely. Sorry I wasn't clear -- I wasn't necessarily intending that to be a blocking comment. I'm totally good with adding rampant TODO comments. That way we can always grep for TODO close to the end to see if we are really done. So let's add a TODO for it, but fine to leave as is.

internal/app/server/server.go Outdated Show resolved Hide resolved
internal/app/server/server.go Outdated Show resolved Hide resolved
internal/app/server/server.go Outdated Show resolved Hide resolved
internal/app/server/impl.go Outdated Show resolved Hide resolved
internal/app/server/impl.go Show resolved Hide resolved
internal/app/server/impl.go Outdated Show resolved Hide resolved
internal/app/server/impl.go Outdated Show resolved Hide resolved
}
payload, err := parseUnaryResponseDefinition(req.Msg.ResponseDefinition, req.Header(), []*anypb.Any{msgAsAny})
if err != nil {
return nil, err
Copy link
Member

Choose a reason for hiding this comment

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

You still need to populate response metadata. For unary RPCs, this is done by adding header metadata to a *connect.Error. It has a Meta() method that returns a mutable http.Header.

Sadly, the API provides no way to distinguish between headers and trailers in the error metadata. I think this is because, in practice, errors from unary RPCs often result in "trailers-only responses" in gRPC, which also cannot distinguish.

So I would do something like this here:

Suggested change
return nil, err
addHeaders(req.Msg.ResponseDefinition.ResponseHeaders, err.Meta())
addHeaders(req.Msg.ResponseDefinition.ResponseTrailers, err.Meta())
return nil, err

Copy link
Member Author

Choose a reason for hiding this comment

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

I added this to unary and client stream requests. Should this also be included on the server and bidi requests in the event we return with an error?

Copy link
Member

Choose a reason for hiding this comment

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

Nah. For those, the stream type the handler gets has ways to set headers and trailers separately. If you do add metadata to the error, it will get merged into the trailers. But I don't think we want or need to do that here for those endpoints.

Comment on lines +200 to +211
requestInfo := createRequestInfo(stream.RequestHeader(), reqs)
resp := &v1alpha1.BidiStreamResponse{
Payload: &v1alpha1.ConformancePayload{
RequestInfo: requestInfo,
Data: responseDefinition.ResponseData[respNum],
},
}
time.Sleep((time.Duration(responseDefinition.ResponseDelayMs) * time.Millisecond))

if err := stream.Send(resp); err != nil {
return connect.NewError(connect.CodeInternal, fmt.Errorf("error sending on stream: %w", err))
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This could probably be pulled out into its own function also. Lmk if you think it is worth it.

@smaye81
Copy link
Member Author

smaye81 commented Oct 17, 2023

@jhump ready for round 2.


// Parses the given unary response definition and returns either
// a built payload or a connect error based on the definition.
func parseUnaryResponseDefinition(
Copy link
Member

Choose a reason for hiding this comment

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

I guess I think or "parse" differently than that. It's fine either way -- not a strongly held opinion :)

@smaye81 smaye81 changed the title Initial server implementation V2: Initial server implementation Oct 18, 2023
@smaye81
Copy link
Member Author

smaye81 commented Oct 18, 2023

OK, just going to leave the function name as-is for now. We can definitely rename it later if it's confusing.

@smaye81 smaye81 merged commit ae8d036 into v2 Oct 18, 2023
2 checks passed
@smaye81 smaye81 deleted the sayers/server_impl branch October 18, 2023 15:24
@jhump jhump changed the title V2: Initial server implementation V1: Initial server implementation Nov 20, 2023
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