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

Unknown enum variants removed from server #1398

Merged
merged 9 commits into from
May 23, 2022
Merged

Unknown enum variants removed from server #1398

merged 9 commits into from
May 23, 2022

Conversation

82marbag
Copy link
Contributor

@82marbag 82marbag commented May 18, 2022

The server must have the most up to date variants and the unknown enum
variant should not be used. Clients are generated with it because they
might not have the most recent model and the server might return
an unknown variant to them.

Closes #1187

Signed-off-by: Daniele Ahmed [email protected]

Motivation and Context

Closes #1187

Description

  • Remove unknown in server
  • Implement TryFrom and the relevant Errors for enums
  • Refactor the code to use the server/client generators
  • Added and refactored tests

Testing

./gradlew :codegen-server-test:test

Checklist

  • I have updated CHANGELOG.next.toml if I made changes to the smithy-rs codegen or runtime crates
  • I have updated CHANGELOG.next.toml if I made changes to the AWS SDK, generated SDK code, or SDK runtime crates

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

@82marbag 82marbag requested review from a team as code owners May 18, 2022 13:21
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec 1.01% 81774.22 80952.92
Total requests 1.07% 7366691 7288801
Total errors NaN% 0 0
Total successes 1.07% 7366691 7288801
Average latency ms -2.44% 0.8 0.82
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -4.76% 24.42 25.64
Stdev latency ms -5.63% 1.34 1.42
Transfer Mb 1.07% 765.77 757.67
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

Comment on lines 14 to 18
[[smithy-rs]]
message = "Remove Unknown variant from enums in server"
references = ["smithy-rs#1187"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "82marbag"
Copy link
Contributor

Choose a reason for hiding this comment

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

We do not publish CHANGELOG entries for server only changes. If this PR does not change how the client SDK is generated, this should go away.

Comment on lines +158 to +161
if (mode == CodegenMode.Client) {
docs("$UnknownVariant contains new variants that have been added since this code was generated.")
write("$UnknownVariant(String)")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't this be abstracted completely inside the ServerEnumGenerator rather than having an if guard here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I understand. They are here because the client generates the same code as the server, plus some more. The one where the server is generating actual different code is in the server only. But not to copy/paste code around, I generate the common code in the client and the additional code in the client. Moving to ServerEnumGenerator would mean to copy the same code there anyway. I am open for suggestions

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec 0.68% 61969.57 61552.21
Total requests 0.62% 5579718 5545530
Total errors NaN% 0 0
Total successes 0.62% 5579718 5545530
Average latency ms 4.29% 0.73 0.7
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms 14.96% 24.52 21.33
Stdev latency ms 7.69% 0.98 0.91
Transfer Mb 0.62% 580.01 576.46
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec 2.91% 36256.88 35232.7
Total requests 2.94% 3265061 3171704
Total errors NaN% 0 0
Total successes 2.94% 3265061 3171704
Average latency ms 0.00% 0.92 0.92
Minimum latency ms 0.00% 0.03 0.03
Maximum latency ms -31.47% 16.9 24.66
Stdev latency ms 17.65% 0.6 0.51
Transfer Mb 2.94% 339.4 329.7
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@@ -184,7 +184,7 @@ class ServerCodegenVisitor(context: PluginContext, private val codegenDecorator:
logger.info("[rust-server-codegen] Generating an enum $shape")
shape.getTrait<EnumTrait>()?.also { enum ->
rustCrate.useShapeWriter(shape) { writer ->
EnumGenerator(model, symbolProvider, writer, shape, enum).render()
ServerEnumGenerator(model, symbolProvider, writer, shape, enum, codegenContext.mode, codegenContext.runtimeConfig).render()
Copy link
Contributor

Choose a reason for hiding this comment

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

In these cases where the number of params grows, instead of plucking everything out of codegenContext, just pass codegenContext and have the generator pull out the things it needs: model, symbolProvider, runtimeConfig etc...

Comment on lines 44 to 93
writer.rustBlock("impl #T<$errorStruct> for #T", RuntimeType.From, ServerRuntimeType.RequestRejection(runtimeConfig)) {
writer.rustBlock("fn from(e: $errorStruct) -> Self") {
write("Self::EnumVariantNotFound(Box::new(e))")
}
}
writer.rustBlock("impl From<$errorStruct> for #T", RuntimeType.jsonDeserialize(runtimeConfig)) {
writer.rustBlock("fn from(e: $errorStruct) -> Self") {
write("""Self::custom(format!("unknown variant {}", e))""")
}
}
writer.rustBlock("impl std::error::Error for $errorStruct") {}
writer.rustBlock("impl std::fmt::Display for $errorStruct") {
writer.rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") {
write("self.0.fmt(f)")
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Elaborating on the "strive to write as much uninterrupted Rust as possible", this code is fine, but notice it's exactly the same as:

Suggested change
writer.rustBlock("impl #T<$errorStruct> for #T", RuntimeType.From, ServerRuntimeType.RequestRejection(runtimeConfig)) {
writer.rustBlock("fn from(e: $errorStruct) -> Self") {
write("Self::EnumVariantNotFound(Box::new(e))")
}
}
writer.rustBlock("impl From<$errorStruct> for #T", RuntimeType.jsonDeserialize(runtimeConfig)) {
writer.rustBlock("fn from(e: $errorStruct) -> Self") {
write("""Self::custom(format!("unknown variant {}", e))""")
}
}
writer.rustBlock("impl std::error::Error for $errorStruct") {}
writer.rustBlock("impl std::fmt::Display for $errorStruct") {
writer.rustBlock("fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result") {
write("self.0.fmt(f)")
}
}
}
writer.rustTemplate(
"""
impl #{From}<$errorStruct> for #{RequestRejection} {
fn from(e: $errorStruct) -> Self {
Self::EnumVariantNotFound(Box::new(e))
}
}
impl #{From}<$errorStruct> for #{JsonDeserialize} {
fn from(e: $errorStruct) -> Self {
Self::custom(format!("unknown variant {}", e))
}
}
impl #{StdError} for $errorStruct { }
impl std::fmt::Display for $errorStruct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
""",
"From" to RuntimeType.From,
"StdError" to RuntimeType.StdError,
"RequestRejection" to ServerRuntimeType.RequestRejection(runtimeConfig),
"JsonDeserialize" to RuntimeType.jsonDeserialize(runtimeConfig),
)

which reads much nicer.

(Bonus points: we should also have a RuntimeType.Display and use it everywhere in the codebase where we've used RuntimeType.stdfmt.member("Display") or written out Display manually).

The writer.*block methods are useful when you have to loop over a collection, when you want to insert blocks conditionally, or when you need to put conditionals based on Kotlin variables inside your Rust blocks. For example, above was a good use of rustBlock, because you needed to iterate over sortedMembers.

Daniele Ahmed added 2 commits May 20, 2022 09:39
The server must have the most up to date variants and the unknown enum
variant should not be used. Clients are generated with it because they
might not have the most recent model and the server might return
an unknown variant to them.

Closes #1187

Signed-off-by: Daniele Ahmed <[email protected]>
Signed-off-by: Daniele Ahmed <[email protected]>
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec -22.34% 38001.24 48932.66
Total requests -22.34% 3420670 4404657
Total errors NaN% 0 0
Total successes -22.34% 3420670 4404657
Average latency ms 22.86% 0.86 0.7
Minimum latency ms 50.00% 0.03 0.02
Maximum latency ms 1.27% 16.8 16.59
Stdev latency ms -18.03% 0.5 0.61
Transfer Mb -22.34% 355.58 457.87
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

Daniele Ahmed added 2 commits May 20, 2022 11:13
Signed-off-by: Daniele Ahmed <[email protected]>
Signed-off-by: Daniele Ahmed <[email protected]>
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec -4.94% 38488.32 40486.39
Total requests -4.92% 3465117 3644397
Total errors NaN% 0 0
Total successes -4.92% 3465117 3644397
Average latency ms 4.94% 0.85 0.81
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -2.98% 16.94 17.46
Stdev latency ms 0.00% 0.49 0.49
Transfer Mb -4.92% 360.2 378.84
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

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.

An empty rust-runtime/.attach_pid18283 file crept into the patchset.

@david-perez david-perez mentioned this pull request May 20, 2022
23 tasks
82marbag and others added 2 commits May 20, 2022 18:46
Signed-off-by: Daniele Ahmed <[email protected]>
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec 5.30% 80440.91 76395.37
Total requests 5.20% 7240722 6882988
Total errors NaN% 0 0
Total successes 5.20% 7240722 6882988
Average latency ms 5.56% 0.95 0.9
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms 9.54% 22.84 20.85
Stdev latency ms 7.24% 1.63 1.52
Transfer Mb 5.20% 752.68 715.49
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@david-perez david-perez added the server Rust server SDK label May 20, 2022
@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec -7.26% 62651.57 67559
Total requests -7.23% 5642360 6081810
Total errors NaN% 0 0
Total successes -7.23% 5642360 6081810
Average latency ms -18.42% 0.62 0.76
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -7.17% 17.48 18.83
Stdev latency ms -33.91% 0.76 1.15
Transfer Mb -7.23% 586.53 632.21
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec -0.70% 88147.79 88768.83
Total requests -0.67% 7940372 7993759
Total errors NaN% 0 0
Total successes -0.67% 7940372 7993759
Average latency ms 0.84% 1.2 1.19
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms 0.64% 28.18 28
Stdev latency ms 0.46% 2.18 2.17
Transfer Mb -0.67% 825.41 830.96
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

Rust Wrk benchmark report:

Duration: 90 sec, Connections: 32, Threads: 2

Measurement Deviation Current Old
Requests/sec -1.00% 85990.83 86861.7
Total requests -1.00% 7747571 7825445
Total errors NaN% 0 0
Total successes -1.00% 7747571 7825445
Average latency ms -0.83% 1.19 1.2
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -13.97% 24.45 28.42
Stdev latency ms -0.46% 2.16 2.17
Transfer Mb -1.00% 805.36 813.46
Connect errors NaN% 0 0
Read errors NaN% 0 0
Write errors NaN% 0 0
Status errors (not 2xx/3xx) NaN% 0 0
Timeout errors NaN% 0 0

@crisidev crisidev merged commit 35989d2 into main May 23, 2022
@crisidev crisidev deleted the 1187 branch May 23, 2022 19:16
david-perez added a commit that referenced this pull request Jun 22, 2022
XML deserialization of enums is currently broken.

This commit should have been done as part of #1398, but we only tested
that patch using the restJson1 protocol.

The converter from the unknown enum variant error into
`aws_smithy_json::deserialize::Error` has been removed from
`ServerEnumGenerator`, since it's protocol-specific logic. We instead
use `map_err` in the protocol-specific parsers before bubbling up using
`?`.

Fixes #1477.
david-perez added a commit that referenced this pull request Aug 12, 2022
…1485)

XML deserialization of enums is currently broken.

This commit should have been done as part of #1398, but we only tested
that patch using the restJson1 protocol.

The converter from the unknown enum variant error into
`aws_smithy_json::deserialize::Error` has been removed from
`ServerEnumGenerator`, since it's protocol-specific logic. We instead
use `map_err` in the protocol-specific parsers before bubbling up using
`?`.

Fixes #1477.
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.

Server enums should not have Unknown variants
4 participants