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

Use a newtyped IndexSet to back the "set" shape #1446

Closed
wants to merge 24 commits into from

Conversation

hlbarber
Copy link
Contributor

@hlbarber hlbarber commented Jun 7, 2022

Motivation and Context

Description

  • Add a insertion ordered non-repeating collection Set<T> to aws-smithy-types
  • Integrate Set<T> into smithy codegen

Checklist

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

Sorry, something went wrong.

@hlbarber hlbarber changed the title Harryb/set semantics Use a newtyped IndexSet to back the smithy set shape Jun 7, 2022
@hlbarber hlbarber changed the title Use a newtyped IndexSet to back the smithy set shape Use a newtyped IndexSet to back the "set" shape Jun 7, 2022
@github-actions
Copy link

github-actions bot commented Jun 7, 2022

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 3.76% 36147.23 34835.76
Total requests 3.75% 3255191 3137532
Total errors NaN% 0 0
Total successes 3.75% 3255191 3137532
Average latency ms -2.13% 0.92 0.94
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms 11.03% 19.23 17.32
Stdev latency ms 7.27% 0.59 0.55
Transfer Mb 3.75% 338.38 326.15
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

github-actions bot commented Jun 8, 2022

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 15.20% 40651.54 35288.49
Total requests 15.20% 3660128 3177100
Total errors NaN% 0 0
Total successes 15.20% 3660128 3177100
Average latency ms -12.90% 0.81 0.93
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -22.81% 16.07 20.82
Stdev latency ms -14.29% 0.48 0.56
Transfer Mb 15.20% 380.47 330.26
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

@@ -864,7 +865,12 @@ private class ServerHttpBoundProtocolTraitImplGenerator(
rust("let mut seen_${symbolProvider.toMemberName(it.member)} = false;")
}
queryBindingsTargettingCollection.forEach {
rust("let mut ${symbolProvider.toMemberName(it.member)} = Vec::new();")
val collection = if (model.expectShape(it.member.target) is SetShape) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This PR introduces a ton of branches like this. Is there a way to reduce them?

Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah—you can change them to:

val collectionType = symbolProvider.toSymbol(model.expectShape(it.member.target))
val memberName = symbolProvider.toMemberName(it.member)
rustTemplate("let mut $memberName = #{collection}::new();, "Collection" to collectionType)

(or similar)

const val Type = "Set"
const val Namespace = "aws_smithy_types"

fun RuntimeType(runtimeConfig: RuntimeConfig): RuntimeType {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We've promoted this from a val to a function in order to accommodate the need for a dependency.

assert_eq!(test.otherMember, "hello");
assert_eq!(test.member.is_empty(), true);
""",
"Set" to RuntimeType.Set(TestRuntimeConfig)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These tests have been "modernized" (using TestWorkspace.testProject()) in order to allow for dependency injection here.

write("member: #T,", setSymbol)
write("otherMember: #T,", stringSymbol)
}
it.rustBlock("fn inner()") {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We cannot do this within unitTest because it takes a string rather than provide a writer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#1450 addresses this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed b8c70b8

@github-actions
Copy link

github-actions bot commented Jun 8, 2022

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.96% 33948.87 34983.82
Total requests -2.96% 3056402 3149701
Total errors NaN% 0 0
Total successes -2.96% 3056402 3149701
Average latency ms 3.19% 0.97 0.94
Minimum latency ms 0.00% 0.03 0.03
Maximum latency ms 30.38% 22.4 17.18
Stdev latency ms 9.43% 0.58 0.53
Transfer Mb -2.96% 317.71 327.41
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

@hlbarber hlbarber marked this pull request as ready for review June 8, 2022 19:50
@hlbarber hlbarber requested review from a team as code owners June 8, 2022 19:50
@github-actions
Copy link

github-actions bot commented Jun 8, 2022

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 -9.98% 57482.38 63858.24
Total requests -9.91% 5177971 5747689
Total errors NaN% 0 0
Total successes -9.91% 5177971 5747689
Average latency ms -7.35% 0.63 0.68
Minimum latency ms 0.00% 0.02 0.02
Maximum latency ms -8.58% 16.51 18.06
Stdev latency ms -34.02% 0.64 0.97
Transfer Mb -9.91% 538.25 597.48
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
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.

overall I love the direction! And thanks for modernizing some tests :-)

I think we can completely remove the differential behavior for Vec and Set with a couple of ideas I mentioned in a comment above:

  1. Use symbolProvider.toSymbol() instead of Vec to get the type of the collection
  2. Add a push method to Set

Thanks for addressing this extremely long standing issue!

(And hopefully someone already told you about "debug mode" codegen which makes tracking down where code is coming from much easier)

@@ -864,7 +865,12 @@ private class ServerHttpBoundProtocolTraitImplGenerator(
rust("let mut seen_${symbolProvider.toMemberName(it.member)} = false;")
}
queryBindingsTargettingCollection.forEach {
rust("let mut ${symbolProvider.toMemberName(it.member)} = Vec::new();")
val collection = if (model.expectShape(it.member.target) is SetShape) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah—you can change them to:

val collectionType = symbolProvider.toSymbol(model.expectShape(it.member.target))
val memberName = symbolProvider.toMemberName(it.member)
rustTemplate("let mut $memberName = #{collection}::new();, "Collection" to collectionType)

(or similar)

@@ -926,7 +932,12 @@ private class ServerHttpBoundProtocolTraitImplGenerator(
)
}
}
rust("${symbolProvider.toMemberName(it.member)}.push(v);")
val method = if (model.expectShape(it.member.target) is SetShape) {
"insert"
Copy link
Collaborator

Choose a reason for hiding this comment

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

since we own Set why don't we add a push method for convenience? you can make it #[doc(hidden)] if you want

Comment on lines +90 to +91
return RuntimeType(name = Type, namespace = Namespace, dependency = CargoDependency.SmithyTypes(runtimeConfig))
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

for slightly cleaner code:
CargoDependency.SmithyTypes(runtimeConfig).asType().member("aws_smithy_types::Set")

Comment on lines 301 to 305
var container = if (shape.isSetShape) {
RuntimeType.Set(runtimeConfig)
} else {
RuntimeType("Vec", dependency = null, namespace = "std::vec")
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

we don't need this—just use symbolProvider.toSymbol(shape)

Comment on lines -262 to -267
val builder = if (model.expectShape(shape.member.target).isStringShape) {
symbolBuilder(shape, RustType.HashSet(inner.rustType()))
} else {
// only strings get put into actual sets because floats are unhashable
symbolBuilder(shape, RustType.Vec(inner.rustType()))
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's a comment that justifies why this is OK—when this code was written, sets could contain floats but that was changed:

A set shape requires a single member named member, and the member MUST target either a string, blob, byte, short, integer, long, bigInteger, or bigDecimal shape. The targeted shape MUST NOT be marked with the streaming trait.

pub mod timeout;
pub mod tristate;

pub use crate::date_time::DateTime;
pub use crate::set::*;
Copy link
Collaborator

Choose a reason for hiding this comment

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

especially with pub use, lets enumerate these for clarity

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

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.

looking good so far!

Comment on lines 216 to 218
docs("Appends an item to `$memberName`.")
rust("///")
docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).")
Copy link
Collaborator

Choose a reason for hiding this comment

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

might as well have some custom docs that call out the deduplication

Comment on lines 316 to 318
if replaced {
return Err(#{JsonDeserialize}::custom("duplicate elements found while deserializing to a set"))
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we want to error here? or just deduplicate?

Copy link
Contributor Author

@hlbarber hlbarber Jun 14, 2022

Choose a reason for hiding this comment

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

The team had a little back and forth on this (semantics =? deserialization failure cases) and opened this issue.

smithy-lang/smithy#1266

Will no longer throw an error but perhaps log a warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +15 to +18
references = ["smithy-rs#1446"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "hlbarber"
Copy link
Collaborator

Choose a reason for hiding this comment

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

we'll need to call out the exact breaking change and provide upgrade instructions

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@github-actions
Copy link

A new generated diff is ready to view.

A new doc preview is ready to view.

@hlbarber
Copy link
Contributor Author

hlbarber commented Aug 2, 2022

Closing this due to smithy-lang/smithy#1278

@hlbarber hlbarber closed this Aug 2, 2022
@hlbarber hlbarber deleted the harryb/set-semantics branch August 2, 2022 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants