Skip to content

Commit ebd2179

Browse files
author
Matt Muller
committed
New approach with code generated paginator functions
1 parent af2a1e0 commit ebd2179

23 files changed

Lines changed: 345 additions & 156 deletions

File tree

gems/smithy-client/lib/smithy-client.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
require_relative 'smithy-client/managed_file'
2020
require_relative 'smithy-client/networking_error'
2121
require_relative 'smithy-client/pageable_output'
22-
require_relative 'smithy-client/paginator'
2322
require_relative 'smithy-client/param_converter'
2423
require_relative 'smithy-client/param_validator'
2524
require_relative 'smithy-client/plugin'

gems/smithy-client/lib/smithy-client/pageable_output.rb

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,33 +51,34 @@ module Client
5151
# end
5252
#
5353
module PageableOutput
54-
def self.extended(base)
55-
base.instance_variable_set(:@last_page, nil)
56-
end
57-
5854
# @return [Paginator]
59-
attr_accessor :pager
55+
attr_accessor :paginator
6056

6157
# Returns `true` if there are no more results. Calling {#next_page}
6258
# when this method returns `false` will raise an error.
6359
# @return [Boolean]
6460
def last_page?
65-
@last_page = !@pager.truncated?(self) if @last_page.nil?
66-
!!@last_page
61+
return @last_page if @last_page
62+
63+
@last_page = !truncated?
6764
end
6865

6966
# Returns `true` if there are more results. Calling {#next_page} will
7067
# return the next response.
7168
# @return [Boolean]
7269
def next_page?
73-
!last_page?
70+
return @next_page if @next_page
71+
72+
@next_page = truncated?
7473
end
7574

76-
# @return [Output]
75+
# @param [Hash] params A hash of additional request params.
76+
# @return [Output] Returns the next page of results.
7777
def next_page(params = {})
7878
raise LastPageError, self if last_page?
7979

80-
next_response(params)
80+
params = next_page_params(params)
81+
context.client.send(context.operation_name, params)
8182
end
8283

8384
# Yields the current and each following output to the given block.
@@ -97,33 +98,30 @@ def each_page(&)
9798
# @return [Enumerable, nil] Returns a new Enumerable if no block is given.
9899
def each_item(&)
99100
output = self
100-
@pager.items(output).each(&)
101+
@paginator.items(output.data).each(&)
101102
until output.last_page?
102103
output = output.next_page
103-
@pager.items(output).each(&)
104+
@paginator.items(output.data).each(&)
104105
end
105106
end
106107

107108
private
108109

109-
# @param [Hash] params A hash of additional request params.
110-
# @return [Output] Returns the next page of results.
111-
def next_response(params)
112-
params = next_page_params(params)
113-
context.client.send(context.operation_name, params)
110+
def truncated?
111+
next_t = @paginator.next_tokens(data)
112+
!(next_t.empty? || next_t == @paginator.prev_tokens(context.params))
114113
end
115114

116115
# @param [Hash] params A hash of additional request params to
117116
# merge into the next page request.
118117
# @return [Hash] Returns the hash of request parameters for the
119118
# next page, merging any given params.
120119
def next_page_params(params)
120+
prev_tokens = @paginator.prev_tokens(context.params)
121121
# Remove all previous tokens from original params
122122
# Sometimes a token can be nil and merge would not include it.
123-
prev_tokens = @pager.prev_tokens(self)
124-
params_without_tokens = context[:original_params].reject { |k, _v| prev_tokens.include?(k) }
125-
params_without_tokens.merge!(@pager.next_tokens(self).merge(params))
126-
params_without_tokens
123+
new_params = context.params.except(*prev_tokens)
124+
new_params.merge!(@paginator.next_tokens(data).merge(params))
127125
end
128126
end
129127
end

gems/smithy-client/lib/smithy-client/paginator.rb

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

gems/smithy-client/lib/smithy-client/plugins/pageable_output.rb

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,21 @@ class PageableOutput < Plugin
88
# @api private
99
class Handler < Client::Handler
1010
def call(context)
11-
context[:original_params] = context.params
1211
output = @handler.call(context)
1312
output.extend(Client::PageableOutput)
14-
trait = paginated_trait(context)
15-
output.pager = Paginator.new(
16-
input_token: trait['inputToken'],
17-
output_token: trait['outputToken'],
18-
items: trait['items'],
19-
page_size: trait['pageSize']
20-
)
13+
output.paginator = context.operation[:paginator] || NullPaginator.new
2114
output
2215
end
2316

24-
private
17+
# @api private
18+
class NullPaginator
19+
def next_tokens(_data)
20+
{}
21+
end
2522

26-
def paginated_trait(context)
27-
service = context.config.service
28-
operation = context.operation
29-
service
30-
.traits.fetch('smithy.api#paginated', {})
31-
.merge(operation.traits.fetch('smithy.api#paginated', {}))
23+
def prev_tokens(_params)
24+
{}
25+
end
3226
end
3327
end
3428

gems/smithy-schema/lib/smithy-schema/shapes.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,25 @@ class Shape
99
def initialize(options = {})
1010
@id = options[:id]
1111
@traits = options[:traits] || {}
12+
@metadata = {}
1213
end
1314

1415
# @return [String, nil] Absolute shape ID from model
1516
attr_accessor :id
1617

1718
# @return [Hash<String, Object>]
1819
attr_accessor :traits
20+
21+
# @return [Hash<Object, Object>]
22+
def [](key)
23+
@metadata[key]
24+
end
25+
26+
# @param [Object] key
27+
# @param [Object] value
28+
def []=(key, value)
29+
@metadata[key] = value
30+
end
1931
end
2032

2133
# Represents an aggregate shape that has members.

gems/smithy-schema/sig/smithy-schema/shapes.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ module Smithy
66

77
attr_accessor id: String?
88
attr_accessor traits: Hash[String, untyped]
9+
def []: (untyped) -> untyped
10+
def []=: (untyped, untyped) -> void
911
end
1012

1113
class Structure < Shape

gems/smithy-schema/spec/smithy-schema/shapes_spec.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ module Shapes
2626
subject = Shape.new(traits: { 'trait' => 'value' })
2727
expect(subject.traits).to eq({ 'trait' => 'value' })
2828
end
29+
30+
it 'can get and set metadata' do
31+
subject = Shape.new
32+
subject[:foo] = 'bar'
33+
expect(subject[:foo]).to eq('bar')
34+
end
2935
end
3036
end
3137

gems/smithy/lib/smithy/generators/client.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def source_files
4949
e.yield "lib/#{@gem_name}/errors.rb", Views::Client::Errors.new(@plan).render
5050
e.yield "lib/#{@gem_name}/endpoint_parameters.rb", Views::Client::EndpointParameters.new(@plan).render
5151
e.yield "lib/#{@gem_name}/endpoint_provider.rb", Views::Client::EndpointProvider.new(@plan).render
52+
e.yield "lib/#{@gem_name}/paginators.rb", Views::Client::Paginators.new(@plan).render
5253
code_generated_plugins.each { |path, plugin| e.yield path, plugin.source }
5354
e.yield "lib/#{@gem_name}/types.rb", Views::Client::Types.new(@plan).render
5455
e.yield "lib/#{@gem_name}/schema.rb", Views::Client::Schema.new(@plan).render
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# frozen_string_literal: true
2+
3+
# This is generated code!
4+
5+
module <%= module_name %>
6+
# @api private
7+
module Paginators
8+
9+
<% paginators.each do |paginator| -%>
10+
# @api private
11+
class <%= paginator.name %>
12+
def next_tokens(data)
13+
<% paginator.next_tokens_code.each do |line| -%>
14+
<%= line %>
15+
<% end -%>
16+
end
17+
18+
def prev_tokens(params)
19+
<% paginator.prev_tokens_code.each do |line| -%>
20+
<%= line %>
21+
<% end -%>
22+
end
23+
<%- if paginator.items? -%>
24+
25+
def items(data)
26+
<% paginator.items_code.each do |line| -%>
27+
<%= line %>
28+
<% end -%>
29+
end
30+
<% end -%>
31+
end
32+
33+
<% end -%>
34+
end
35+
end

gems/smithy/lib/smithy/templates/client/schema.erb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ module <%= module_name %>
2626
SERVICE = ServiceShape.new do |service|
2727
service.id = "<%= service_shape.id %>"
2828
service.name = "<%= service_shape.name %>"
29+
<% if service_shape.version? -%>
2930
service.version = "<%= service_shape.version %>"
31+
<% end -%>
3032
service.traits = <%= service_shape.traits %>
3133
<% operation_shapes.each do |shape| -%>
32-
service.add_operation(:<%= shape.to_underscore %>, OperationShape.new do |operation|
34+
service.add_operation(:<%= shape.symbol_name %>, OperationShape.new do |operation|
3335
operation.id = "<%= shape.id %>"
3436
operation.name = "<%= shape.name %>"
3537
operation.input = <%= shape.input %>
@@ -38,6 +40,9 @@ module <%= module_name %>
3840
<% shape.errors.each do |err| -%>
3941
operation.errors << <%= err %>
4042
<% end -%>
43+
<% if shape.paginated? -%>
44+
operation[:paginator] = <%= shape.paginator %>
45+
<% end %>
4146
end)
4247
<% end -%>
4348
end

0 commit comments

Comments
 (0)