-
Notifications
You must be signed in to change notification settings - Fork 6
Behavior Traits
This wiki contains a mapping between Smithy Behavior traits and generated Ruby code.
Defines the input member of an operation that is used by the server to identify and discard replayed requests. Only a single member of the input of an operation can be targeted by the @idempotencyToken
trait; only top-level structure members of the input of an operation are considered.
If a member with this trait is not provided, a token is automatically generated in the param builder. This is done so that any middleware will have access to a client token if none was provided.
structure MyOperationInput {
@idempotencyToken
clientToken: String,
}
The generated code is:
# params.rb
require 'securerandom'
class MyOperationInput
def self.build(params, context:)
Hearth::Validator.validate_types!(params, ::Hash, Types::MyOperationInput, context: context)
type = Types::MyOperationInput.new
Hearth::Validator.validate_unknown!(type, params, context: context) if params.is_a?(Hash)
type.client_token = params[:client_token] || ::SecureRandom.uuid
type
end
end
See Smithy Documentation for more details.
Indicates that the intended effect on the server of multiple identical requests with an operation is the same as the effect for a single such request. This trait does not influence code generation.
@idempotent
operation DeleteSomething {
input: DeleteSomethingInput
output: DeleteSomethingOutput
}
See Smithy Documentation for more details.
Indicates that an operation is effectively read-only. In Smithy, a GET
operation is read only.
This trait does not influence code generation.
@readonly
operation GetSomething {
input: GetSomethingInput
output: GetSomethingOutput
}
See Smithy Documentation for more details.
Indicates that an error MAY be retried by the client. Hearth::ApiError
defines retryable?
and throttling?
methods that return false by default. Errors marked with this trait will override the retryable?
method to return true.
This trait also supports a throttling
property, and if it is set to true, the throttling?
method will similarly be overridden.
@error("server")
@retryable
@httpError(503)
structure ServiceUnavailableError {}
@error("client")
@retryable(throttling: true)
@httpError(429)
structure ThrottlingError {}
The generated code is:
# errors.rb
class ServiceUnavailableError < ApiServerError
...
def retryable?
true
end
end
class ThrottlingError < ApiClientError
...
def retryable?
true
end
def throttling?
true
end
end
If the service returns an error, the retry middleware will call these two methods to determine if the error can be retried and determine whether or not it needs to apply backoff.
begin
output = @app.call(input, context)
raise output.error if output.error
rescue ApiError => e
return output if !e.retryable? || attempt >= @max_attempts
Kernel.sleep(backoff_with_jitter(attempt)) if e.throttling?
attempt += 1
retry
rescue Hearth::HTTP::NetworkingError => e
...
end
See Smithy Documentation for more details.
The @paginated
trait indicates that an operation intentionally limits the number of results returned in a single response and that multiple invocations might be necessary to retrieve all results. Each paginated operation will have a pagination class that automatically iterates response pages by using the response’s output token as the next input token.
See Paginators section and Smithy Documentation.
Indicates that an operation supports compressing requests from clients to services. Operation input members must not have both the @streaming
trait and @requiresLength
trait applied. This avoids the client reading and compressing the entire stream for the length of the compressed data to set the Content-Length
header.
Currently supported compression algorithms are: "gzip".
@requestCompression(
encodings: ["gzip"]
)
@http(method: "POST", uri: "/compress_operation")
operation MyCompressionOperation {
input: MyCompressionInput,
}
@input
structure MyCompressionInput {
@httpPayload
data: String
}
// streaming operation
@requestCompression(
encodings: ["gzip"]
)
@http(method: "POST", uri: "/streaming_compress_operation")
operation MyStreamingCompressionOperation {
input: MyStreamingCompressionOperationInput,
}
@input
structure MyStreamingCompressionOperationInput {
@required
@httpPayload
body: StreamingData
}
@streaming
blob StreamingData
The generated code is:
# builders.rb
class MyCompressionOperation
def self.build(http_req, input:)
http_req.body = StringIO.new(input[:data] || '')
end
end
# streaming operation
class MyStreamingCompressionOperation
def self.build(http_req, input:)
http_req.body = input[:body]
http_req.headers['Transfer-Encoding'] = 'chunked'
http_req.headers['Content-Type'] = 'application/octet-stream'
end
end
See Smithy Documentation for more details.