Skip to content

Commit 64144f4

Browse files
authored
Enable event stream operations with RPC bound protocols in client SDKs (#4036)
## Motivation and Context Addresses aws-sdk-rust#213 and aws-sdk-rust#1188. ## Description This PR consolidates the changes from the previous sub-PRs: - #4004 - #4015 - #4023 Together, this PR enables event stream operations with RPC bound protocols, including `SubscribeToShard` in Kinesis and `StartLiveTail` in CloudWatchLogs in the Rust SDK. ## Testing (consolidated bullets from the previous sub-PRs) - Added a service integration test for cloudwatchlogs - Added client SDK codegen tests in `ClientEventStreamUnmarshallerGeneratorTest` to reverify initial-response message handling - Added client SDK codegen tests in `ClientEventStreamMarshallerGeneratorTest` to verify initial-request message handling - Added `DisableStalledStreamProtectionTest` - Confirmed a successful run in the release pipeline ## Checklist <!--- If a checkbox below is not applicable, then please DELETE it rather than leaving it unchecked --> - [x] For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the `.changelog` directory, specifying "client," "server," or both in the `applies_to` key. - [x] For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the `.changelog` directory, specifying "aws-sdk-rust" in the `applies_to` key. ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent 357415f commit 64144f4

File tree

54 files changed

+14452
-458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+14452
-458
lines changed

.changelog/1740420128.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
applies_to:
3+
- aws-sdk-rust
4+
authors:
5+
- ysaito1001
6+
references:
7+
- aws-sdk-rust#213
8+
- aws-sdk-rust#1188
9+
breaking: false
10+
new_feature: true
11+
bug_fix: false
12+
---
13+
Adds support for event stream operations with non-REST protocols such as AWS JSON. This update enables operations, including `SubscribeToShard` in Kinesis and `StartLiveTail` in CloudWatchLogs in the Rust SDK.

.changelog/1740421036.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
applies_to:
3+
- client
4+
authors:
5+
- ysaito1001
6+
references:
7+
- smithy-rs#121
8+
breaking: false
9+
new_feature: true
10+
bug_fix: false
11+
---
12+
Adds support for event stream operations with non-REST protocols such as RPC v2 CBOR.

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsCodegenDecorator.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import software.amazon.smithy.rust.codegen.client.smithy.customizations.DocsRsMe
99
import software.amazon.smithy.rust.codegen.client.smithy.customizations.DocsRsMetadataSettings
1010
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
1111
import software.amazon.smithy.rust.codegen.client.smithy.customize.CombinedClientCodegenDecorator
12+
import software.amazon.smithy.rustsdk.customize.AwsDisableStalledStreamProtection
1213
import software.amazon.smithy.rustsdk.customize.DisabledAuthDecorator
1314
import software.amazon.smithy.rustsdk.customize.IsTruncatedPaginatorDecorator
1415
import software.amazon.smithy.rustsdk.customize.RemoveDefaultsDecorator
@@ -18,7 +19,6 @@ import software.amazon.smithy.rustsdk.customize.applyExceptFor
1819
import software.amazon.smithy.rustsdk.customize.dsql.DsqlDecorator
1920
import software.amazon.smithy.rustsdk.customize.ec2.Ec2Decorator
2021
import software.amazon.smithy.rustsdk.customize.glacier.GlacierDecorator
21-
import software.amazon.smithy.rustsdk.customize.lambda.LambdaDecorator
2222
import software.amazon.smithy.rustsdk.customize.onlyApplyTo
2323
import software.amazon.smithy.rustsdk.customize.rds.RdsDecorator
2424
import software.amazon.smithy.rustsdk.customize.route53.Route53Decorator
@@ -30,7 +30,6 @@ import software.amazon.smithy.rustsdk.customize.s3control.S3ControlDecorator
3030
import software.amazon.smithy.rustsdk.customize.sso.SSODecorator
3131
import software.amazon.smithy.rustsdk.customize.sts.STSDecorator
3232
import software.amazon.smithy.rustsdk.customize.timestream.TimestreamDecorator
33-
import software.amazon.smithy.rustsdk.customize.transcribestreaming.TranscribeStreamingDecorator
3433
import software.amazon.smithy.rustsdk.endpoints.AwsEndpointsStdLib
3534
import software.amazon.smithy.rustsdk.endpoints.OperationInputTestDecorator
3635
import software.amazon.smithy.rustsdk.endpoints.RequireEndpointRules
@@ -67,6 +66,7 @@ val DECORATORS: List<ClientCodegenDecorator> =
6766
ServiceEnvConfigDecorator(),
6867
HttpRequestCompressionDecorator(),
6968
DisablePayloadSigningDecorator(),
69+
AwsDisableStalledStreamProtection(),
7070
// TODO(https://github.com/smithy-lang/smithy-rs/issues/3863): Comment in once the issue has been resolved
7171
// SmokeTestsDecorator(),
7272
),
@@ -80,7 +80,6 @@ val DECORATORS: List<ClientCodegenDecorator> =
8080
DsqlDecorator().onlyApplyTo("com.amazonaws.dsql#DSQL"),
8181
Ec2Decorator().onlyApplyTo("com.amazonaws.ec2#AmazonEC2"),
8282
GlacierDecorator().onlyApplyTo("com.amazonaws.glacier#Glacier"),
83-
LambdaDecorator().onlyApplyTo("com.amazonaws.lambda#AWSGirApiService"),
8483
RdsDecorator().onlyApplyTo("com.amazonaws.rds#AmazonRDSv19"),
8584
Route53Decorator().onlyApplyTo("com.amazonaws.route53#AWSDnsV20130401"),
8685
"com.amazonaws.s3#AmazonS3".applyDecorators(
@@ -95,7 +94,6 @@ val DECORATORS: List<ClientCodegenDecorator> =
9594
SSODecorator().onlyApplyTo("com.amazonaws.sso#SWBPortalService"),
9695
TimestreamDecorator().onlyApplyTo("com.amazonaws.timestreamwrite#Timestream_20181101"),
9796
TimestreamDecorator().onlyApplyTo("com.amazonaws.timestreamquery#Timestream_20181101"),
98-
TranscribeStreamingDecorator().onlyApplyTo("com.amazonaws.transcribestreaming#Transcribe"),
9997
// Only build docs-rs for linux to reduce load on docs.rs
10098
listOf(
10199
DocsRsMetadataDecorator(

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/IntegrationTestDependencies.kt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency.Compani
3434
import software.amazon.smithy.rust.codegen.core.rustlang.DependencyScope
3535
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
3636
import software.amazon.smithy.rust.codegen.core.rustlang.writable
37+
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
3738
import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsCustomization
3839
import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsSection
3940
import software.amazon.smithy.rust.codegen.core.testutil.testDependenciesOnly
41+
import software.amazon.smithy.rust.codegen.core.util.hasEventStreamOperations
4042
import software.amazon.smithy.rustsdk.AwsCargoDependency.awsConfig
4143
import software.amazon.smithy.rustsdk.AwsCargoDependency.awsRuntime
4244
import java.nio.file.Files
@@ -76,29 +78,31 @@ class IntegrationTestDecorator : ClientCodegenDecorator {
7678
}
7779

7880
class IntegrationTestDependencies(
79-
private val codegenContext: ClientCodegenContext,
81+
codegenContext: ClientCodegenContext,
8082
private val moduleName: String,
8183
private val hasTests: Boolean,
8284
private val hasBenches: Boolean,
8385
) : LibRsCustomization() {
8486
private val runtimeConfig = codegenContext.runtimeConfig
87+
private val serviceShape = codegenContext.serviceShape
88+
private val model = codegenContext.model
8589

8690
override fun section(section: LibRsSection) =
8791
when (section) {
8892
is LibRsSection.Body ->
8993
testDependenciesOnly {
9094
if (hasTests) {
9195
val smithyAsync =
92-
CargoDependency.smithyAsync(codegenContext.runtimeConfig)
96+
CargoDependency.smithyAsync(runtimeConfig)
9397
.copy(features = setOf("test-util"), scope = DependencyScope.Dev)
9498
val smithyTypes =
95-
CargoDependency.smithyTypes(codegenContext.runtimeConfig)
99+
CargoDependency.smithyTypes(runtimeConfig)
96100
.copy(features = setOf("test-util"), scope = DependencyScope.Dev)
97101
addDependency(awsRuntime(runtimeConfig).toDevDependency().withFeature("test-util"))
98-
addDependency(FuturesUtil)
102+
addDependency(FuturesUtil.toDevDependency())
99103
addDependency(SerdeJson)
100104
addDependency(smithyAsync)
101-
addDependency(smithyProtocolTestHelpers(codegenContext.runtimeConfig))
105+
addDependency(smithyProtocolTestHelpers(runtimeConfig))
102106
addDependency(smithyRuntime(runtimeConfig).copy(features = setOf("test-util", "wire-mock"), scope = DependencyScope.Dev))
103107
addDependency(smithyRuntimeApiTestUtil(runtimeConfig))
104108
addDependency(smithyTypes)
@@ -109,6 +113,12 @@ class IntegrationTestDependencies(
109113
if (hasBenches) {
110114
addDependency(Criterion)
111115
}
116+
if (serviceShape.hasEventStreamOperations(model)) {
117+
addDependency(
118+
CargoDependency.smithyEventStream(runtimeConfig)
119+
.copy(features = setOf("test-util"), scope = DependencyScope.Dev),
120+
)
121+
}
112122
for (serviceSpecific in serviceSpecificCustomizations()) {
113123
serviceSpecific.section(section)(this)
114124
}
@@ -120,7 +130,7 @@ class IntegrationTestDependencies(
120130
private fun serviceSpecificCustomizations(): List<LibRsCustomization> =
121131
when (moduleName) {
122132
"transcribestreaming" -> listOf(TranscribeTestDependencies())
123-
"s3" -> listOf(S3TestDependencies(codegenContext))
133+
"s3" -> listOf(S3TestDependencies(runtimeConfig))
124134
"dynamodb" -> listOf(DynamoDbTestDependencies())
125135
else -> emptyList()
126136
}
@@ -142,11 +152,11 @@ class DynamoDbTestDependencies : LibRsCustomization() {
142152
}
143153
}
144154

145-
class S3TestDependencies(private val codegenContext: ClientCodegenContext) : LibRsCustomization() {
155+
class S3TestDependencies(private val runtimeConfig: RuntimeConfig) : LibRsCustomization() {
146156
override fun section(section: LibRsSection): Writable =
147157
writable {
148-
addDependency(awsConfig(codegenContext.runtimeConfig).toDevDependency().withFeature("behavior-version-latest"))
149-
addDependency(smithyExperimental(codegenContext.runtimeConfig).toDevDependency())
158+
addDependency(awsConfig(runtimeConfig).toDevDependency().withFeature("behavior-version-latest"))
159+
addDependency(smithyExperimental(runtimeConfig).toDevDependency())
150160
addDependency(AsyncStd)
151161
addDependency(BytesUtils.toDevDependency())
152162
addDependency(FastRand.toDevDependency())

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/lambda/LambdaDecorator.kt renamed to aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/AwsDisableStalledStreamProtection.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package software.amazon.smithy.rustsdk.customize.lambda
6+
package software.amazon.smithy.rustsdk.customize
77

88
import software.amazon.smithy.model.Model
99
import software.amazon.smithy.model.shapes.OperationShape
@@ -12,22 +12,31 @@ import software.amazon.smithy.model.shapes.ShapeId
1212
import software.amazon.smithy.model.transform.ModelTransformer
1313
import software.amazon.smithy.rust.codegen.client.smithy.ClientRustSettings
1414
import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator
15-
import software.amazon.smithy.rust.codegen.client.smithy.traits.IncompatibleWithStalledStreamProtectionTrait
15+
import software.amazon.smithy.rust.codegen.client.smithy.transformers.DisableStalledStreamProtection
1616
import software.amazon.smithy.rust.codegen.core.util.letIf
1717
import java.util.logging.Logger
1818

1919
/**
20-
* Top level decorator for Lambda
20+
* Disables stalled stream protection for specific operations.
21+
*
22+
* While a generic client-level decorator, `DisableStalledStreamProtection`, exists to handle this
23+
* at the model level, certain cases require operation-specific removal criteria that cannot be
24+
* generalized. (If we can fully generate the criteria, this class can be removed.)
25+
*
26+
* This class serves as a centralized solution for disabling stalled stream protection in such cases,
27+
* preventing the need for service-specific decorators solely for this purpose.
2128
*/
22-
class LambdaDecorator : ClientCodegenDecorator {
29+
class AwsDisableStalledStreamProtection : ClientCodegenDecorator {
30+
// These long-running operations may have times with no data transfer,
31+
// violating stalled stream protection.
2332
private val operationsIncompatibleWithStalledStreamProtection =
2433
setOf(
2534
ShapeId.from("com.amazonaws.lambda#Invoke"),
2635
ShapeId.from("com.amazonaws.lambda#InvokeAsync"),
27-
ShapeId.from("com.amazonaws.lambda#InvokeWithResponseStream"),
36+
ShapeId.from("com.amazonaws.s3#CopyObject"),
2837
)
2938

30-
override val name: String = "Lambda"
39+
override val name: String = "AwsDisableStalledStreamProtection"
3140
override val order: Byte = 0
3241
private val logger = Logger.getLogger(javaClass.name)
3342

@@ -37,9 +46,9 @@ class LambdaDecorator : ClientCodegenDecorator {
3746
settings: ClientRustSettings,
3847
): Model =
3948
ModelTransformer.create().mapShapes(model) { shape ->
40-
shape.letIf(shape.id in operationsIncompatibleWithStalledStreamProtection) {
49+
shape.letIf(operationsIncompatibleWithStalledStreamProtection.contains(shape.id)) {
4150
logger.info("Adding IncompatibleWithStalledStreamProtection trait to $it")
42-
(it as OperationShape).toBuilder().addTrait(IncompatibleWithStalledStreamProtectionTrait()).build()
51+
(DisableStalledStreamProtection::transformOperation)((it as OperationShape))
4352
}
4453
}
4554
}

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationCus
2727
import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationGenerator
2828
import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationSection
2929
import software.amazon.smithy.rust.codegen.client.smithy.protocols.ClientRestXmlFactory
30-
import software.amazon.smithy.rust.codegen.client.smithy.traits.IncompatibleWithStalledStreamProtectionTrait
3130
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
3231
import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate
3332
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
@@ -61,10 +60,6 @@ class S3Decorator : ClientCodegenDecorator {
6160
// API returns ListAllMyDirectoryBucketsResult instead of ListDirectoryBucketsOutput
6261
ShapeId.from("com.amazonaws.s3#ListDirectoryBucketsOutput"),
6362
)
64-
private val operationsIncompatibleWithStalledStreamProtection =
65-
setOf(
66-
ShapeId.from("com.amazonaws.s3#CopyObject"),
67-
)
6863

6964
override fun protocols(
7065
serviceId: ShapeId,
@@ -87,9 +82,6 @@ class S3Decorator : ClientCodegenDecorator {
8782
shape.letIf(isInInvalidXmlRootAllowList(shape)) {
8883
logger.info("Adding AllowInvalidXmlRoot trait to $it")
8984
(it as StructureShape).toBuilder().addTrait(AllowInvalidXmlRoot()).build()
90-
}.letIf(operationsIncompatibleWithStalledStreamProtection.contains(shape.id)) {
91-
logger.info("Adding IncompatibleWithStalledStreamProtection trait to $it")
92-
(it as OperationShape).toBuilder().addTrait(IncompatibleWithStalledStreamProtectionTrait()).build()
9385
}
9486
}
9587
// the model has the bucket in the path

aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/transcribestreaming/TranscribeStreamingDecorator.kt

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)