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

Server streaming body #1023

Merged
merged 5 commits into from
Feb 3, 2022
Merged

Server streaming body #1023

merged 5 commits into from
Feb 3, 2022

Conversation

guymguym
Copy link
Contributor

@guymguym guymguym commented Jan 2, 2022

Signed-off-by: Guy Margalit [email protected]

Motivation and Context

  1. Support streaming body in server requests and responses.

Description

Testing

Generated s3 server codegen and tested get-object/put-object with streams.

Checklist

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

CC @crisidev @david-perez

@guymguym guymguym requested review from a team as code owners January 2, 2022 15:43
@guymguym
Copy link
Contributor Author

guymguym commented Jan 2, 2022

Hmm, I wonder why hyper::Body::wrap_stream is not found when building codegen-server-test

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1742:59
     |
1742 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1771:59
     |
1771 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1800:59
     |
1800 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

@crisidev
Copy link
Contributor

crisidev commented Jan 3, 2022

Hmm, I wonder why hyper::Body::wrap_stream is not found when building codegen-server-test

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1742:59
     |
1742 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1771:59
     |
1771 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

error[E0599]: no function or associated item named `wrap_stream` found for struct `Body` in the current scope
    --> rest_json/rust-server-codegen/src/operation_ser.rs:1800:59
     |
1800 |         let payload = aws_smithy_http_server::body::Body::wrap_stream(output.blob);
     |                                                           ^^^^^^^^^^^ function or associated item not found in `Body`

wrap_stream is available only with the stream feature. You will need to add the feature to aws-smithy-http-server Cargo.toml.

Copy link
Contributor

@crisidev crisidev left a comment

Choose a reason for hiding this comment

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

This is amazing @guymguym !! I left a couple of comments, nothing major :)

@guymguym guymguym force-pushed the s3d-streaming branch 2 times, most recently from 80580c8 to d57232d Compare January 20, 2022 07:17
@guymguym guymguym changed the title [Server] streaming body + response headers Server streaming body Jan 27, 2022
Copy link
Contributor

@david-perez david-perez left a comment

Choose a reason for hiding this comment

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

I'd like to merge this PR this week.

I did another pass and only found one more nitpick.

I'm approving. Can you please merge and resolve conflicts?

@@ -132,13 +134,18 @@ class ServerOperationHandlerGenerator(
} else {
symbolProvider.toSymbol(operation.outputShape(model)).fullName
}
val streamingBodyTraitBounds = if (operation.inputShape(model).hasStreamingMember(model)) {
"\n B: Into<#{SmithyHttpServer}::ByteStream>,"
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove the \n and interpolate the variable in the next line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@david-perez the reason I did this was that the output is usually not including this streaming member and then it generates an empty line, which is not causing any compilation issues, but is weird to watch...

Copy link
Contributor

Choose a reason for hiding this comment

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

We run "cargo fmt" at the end of the codegen, so the weird look should go away.. Is it not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, the empty line is still there. Perhaps because it's just an empty line then cargo fmt will not remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

is there a better way to generate an optional line?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not that I know of. Maybe @rcoh knows.

@crisidev
Copy link
Contributor

crisidev commented Feb 1, 2022

I'll give this another pass this morning as well.

@david-perez david-perez added the server Rust server SDK label Feb 1, 2022
Copy link
Contributor

@crisidev crisidev left a comment

Choose a reason for hiding this comment

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

Looks good!

@@ -132,13 +134,18 @@ class ServerOperationHandlerGenerator(
} else {
symbolProvider.toSymbol(operation.outputShape(model)).fullName
}
val streamingBodyTraitBounds = if (operation.inputShape(model).hasStreamingMember(model)) {
"\n B: Into<#{SmithyHttpServer}::ByteStream>,"
Copy link
Contributor

Choose a reason for hiding this comment

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

We run "cargo fmt" at the end of the codegen, so the weird look should go away.. Is it not?

@guymguym guymguym force-pushed the s3d-streaming branch 2 times, most recently from 25e8ede to 9792c9c Compare February 1, 2022 13:22
@@ -525,14 +525,14 @@ class ServerProtocolTestGenerator(
FailingTest(RestJson, "RestJsonSupportsNegativeInfinityFloatInputs", Action.Response),
FailingTest(RestJson, "RestJsonStreamingTraitsWithBlob", Action.Request),
FailingTest(RestJson, "RestJsonStreamingTraitsWithNoBlobBody", Action.Request),
FailingTest(RestJson, "RestJsonStreamingTraitsWithBlob", Action.Response),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@david-perez @crisidev I was not sure what to do here - should I remove these tests from the expect-fail list as these now seem to pass...?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, if it passes it can be removed from the failing list.

Copy link
Contributor

@david-perez david-perez Feb 2, 2022

Choose a reason for hiding this comment

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

@guymguym I manually verified the now-passing tests and they look good.

I also had a look at the remaining failing request streaming protocol tests and pushed a new commit to this branch, Add blob streaming support for server request protocol tests, to get rid of them.

The only remaining failing protocol test for streaming is RestJsonStreamingTraitsRequireLengthWithBlob, but that is due to us not setting Content-Length appropriately, so I've cut #1146 to track that.

Let me know if you agree with the fix or have any questions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's great @david-perez. Thank you for making it so easy!

if (parsedValue != null) {
withBlock("input = input.${member.setterName()}(", ");") {
parsedValue(this)
if (streamingMember == null) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to highlight this condition I added - I had to check it so that with streaming there will be no bindings parsers generated. The weird thing is just the flow of this function - the conditions seems a bit detached from one another but I wasn't sure if there's a way to simplify:

if (parser != null) { ... } 
else if (streamingMember != null) { ... }
if (streamingMember == null) { ... }

Copy link
Contributor

@david-perez david-perez Feb 2, 2022

Choose a reason for hiding this comment

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

@guymguym Thanks for calling this out. We still need to generate HTTP bindings for blob streaming (e.g. HTTP header bindings). This also led me to discover there's a bug in Smithy that is now being fixed over at smithy-lang/smithy#1075

I have pushed a new commit to this branch, Move blob streaming handling to httpPayload binding generation, that refactors this part and generates the stream handling when we handle @httpPayload.

Let me know if you agree with the fix or have any questions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah now I see. I think my problem was probably that the previous headers code that I used was not very accurate, but since your PR to implement server response headers that might have fixed this issue. I will test a bit later and report back if I still see any issues in the S3 server codegen, but it looks good to me. Thanks!

@guymguym
Copy link
Contributor Author

guymguym commented Feb 1, 2022

@david-perez I'm done rebasing and updating. Couple questions for you in the comments above. Thanks

@guymguym guymguym force-pushed the s3d-streaming branch 2 times, most recently from 3722ea5 to d5e4174 Compare February 1, 2022 22:21
@crisidev
Copy link
Contributor

crisidev commented Feb 2, 2022

Wonderful work @guymguym!! @rcoh, when you have some time, would you mind reviewing this from a client codegen perspective? We'd like to merge this. There is still some work to do to have a good streaming experience, but this PR is paving the way!

@guymguym guymguym force-pushed the s3d-streaming branch 2 times, most recently from 0033f7e to 9b268db Compare February 2, 2022 18:43
@david-perez
Copy link
Contributor

One last thought: given that we decided on using aws_smithy_http::byte_stream::ByteStream, I don't see any value in aws_smithy_http_server re-exporting ByteStream. We should just use ByteStream directly and work on #1125 to hide SdkBody from its public API.

@guymguym
Copy link
Contributor Author

guymguym commented Feb 3, 2022

done @david-perez

Comment on lines 537 to 540
FailingTest(RestJson, "RestJsonSupportsNaNFloatInputs", Action.Response),
FailingTest(RestJson, "RestJsonSimpleScalarProperties", Action.Response),
FailingTest(RestJson, "RestJsonSupportsInfinityFloatInputs", Action.Response),
FailingTest(RestJson, "RestJsonSupportsNegativeInfinityFloatInputs", Action.Response),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@david-perez These seem to fail in CI - did I accidentally add these changes when rebasing from main?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, earlier today I had pushed to this branch a commit merging from main 907c0f3 (which removes these now-passing tests), so that you wouldn't have to deal with conflicts.

But you didn't fetch it (?), and you force-pushed the latest commit.

In general once a PR is open I think it's best to not rebase and force-push, only merge from main. Because AFAIK GitHub's UI won't show the previous history, only the rewrriten one, and that might confuse other people looking at the PR. The downside is that merging makes the history non-linear, but we always squash before merging, so I think it's a small price to pay for having an entire's PR history.


Anyway, these tests can be removed from the failing list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

got it. thanks. pushed a commit to remove those.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's good now

Copy link
Collaborator

@rcoh rcoh left a comment

Choose a reason for hiding this comment

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

Approved on the client side

@david-perez david-perez merged commit f76bc15 into smithy-lang:main Feb 3, 2022
@david-perez
Copy link
Contributor

@guymguym Thank you!

@guymguym guymguym deleted the s3d-streaming branch February 3, 2022 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
server Rust server SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants