hoodoo 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjU2MjRlMTgwYjU3ZDdhOTBhZjk4M2E5NGEwZjk5Mjg4MDM0YjMyMw==
4
+ Y2FmMmNkOGIxNmI3Yjc3Njk2ZGU4MmJlMzVkZDkyYWQ2ZGI2NGNiNQ==
5
5
  data.tar.gz: !binary |-
6
- YWFhZjNkZGJkNDMyZDI1NmE4NDk0NGQyMzAxNGFkMDZlMWU0NzRkMw==
6
+ YWNkMjFhNmMwODQ2OGYxYjZmNDI1ZGIxZGJmNzg3YjQyY2I5ZDMxYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDBiYjhmNDc5OTQ2ODAyNjI5NzU3YzY0YjE4MmQzYTRiMjRkY2NmYjdkZDJl
10
- N2UxYThkMDhiMzBjMmQ4YWQ1YjcyMDhlMjM2ZDVjNjhiNGJhMTg4ZjgzZTg1
11
- MDA0NWQ1OWZmMWM0MzhlNDkzZmNjODM4ZTdkOTUxMTQzYmFmNGY=
9
+ ZWJjN2JjMjA3Zjc1YTRmMzYwN2ZkODYyMzE4M2I2N2VkOTg4M2I1MDBjMDhj
10
+ ZGE3N2RhNWZlOGMwMDQ2MWVmNzNhMzQ3MWEwZTRiZDhjMjBkMDNjNDdhZjdh
11
+ ZjYxOGUwYTk1NDFlYTJmY2VhNGYxYWI5ODk5YzdmNDNkOThjYTE=
12
12
  data.tar.gz: !binary |-
13
- Y2UyY2ZhMDM1YTRlOTg5ODlmNzYwZDMyNGQyMTRiNjY1NmY3ZDdhYjAwN2Y1
14
- NmQxNDQ0NmQ1ZDUxZDA4YzgzZGI1YjdkODY4YTViZjc4MWMwNzVlZmNhM2E4
15
- MmY3MDlmZTFhZTBhZTAxYWVkODQ4NWFmYTJkOGQwOWMzNDIzMTE=
13
+ MmQzNzQxZWI0OTQ2YjI2Nzg1ODAxMzA0ODVlNmM0ODRmMTE2YTY0YmEwYzA2
14
+ YTdjMzZkMTY4NWRlNjlmMzdhNTc1NDdiYWM4OTQ1YjNkNzQzNjYzZTlmNDFl
15
+ Nzc3Mzk5ZmFhMDIxOTk0NmY2MzIyMTc2MGQ2YjFlYWQ5MDQxMGQ=
data/lib/hoodoo/client.rb CHANGED
@@ -10,6 +10,7 @@
10
10
  require 'hoodoo/client/headers'
11
11
 
12
12
  require 'hoodoo/client/augmented_base'
13
+ require 'hoodoo/client/paginated_enumeration'
13
14
  require 'hoodoo/client/augmented_hash'
14
15
  require 'hoodoo/client/augmented_array'
15
16
 
@@ -17,6 +17,7 @@ module Hoodoo
17
17
  #
18
18
  class AugmentedArray < ::Array
19
19
  include Hoodoo::Client::AugmentedBase
20
+ include Hoodoo::Client::PaginatedEnumeration
20
21
 
21
22
  # For lists, the (optional) total size of the data set, of which
22
23
  # the contents of this Array will often only represent a single
@@ -314,6 +314,35 @@ module Hoodoo
314
314
  end
315
315
  end
316
316
 
317
+ # Set the +augmented_array+'s +next_page_proc+ attribute to a Proc that
318
+ # will call the list endpoint to retrieve the next batch of of Resources
319
+ # using the same query parameters.
320
+ #
321
+ # +augmented_array+:: The Hoodoo::Client::AugmentedArray instance
322
+ # containing the initial set of Resources to
323
+ # be enumerated through.
324
+ #
325
+ # +query_hash+:: The query parameters to be used for this
326
+ # enumeration. See the constructor for more.
327
+ #
328
+ # Returns the +augmented_array+ passed in, with the +next_page_proc+
329
+ # value set.
330
+ #
331
+ def inject_enumeration_state ( augmented_array, query_hash )
332
+
333
+ endpoint = self
334
+ query_hash = query_hash.nil? ? {} : query_hash.dup
335
+ batch_size = [ 1, augmented_array.size ].max
336
+ augmented_array.next_page_proc = Proc.new do
337
+ query_hash[ :offset ] = ( query_hash[ :offset ] || 0 ) + batch_size
338
+ endpoint.list( query_hash )
339
+ end
340
+
341
+ return augmented_array
342
+
343
+ end
344
+
345
+
317
346
  public
318
347
 
319
348
  # Obtain a list of resource instance representations.
@@ -337,6 +366,9 @@ module Hoodoo
337
366
  # satisfying the list conditions were found. The array contents
338
367
  # are undefined in the case of errors.
339
368
  #
369
+ # Call Hoodoo::Client::PaginatedEnumeration#enumerate_all to enumerate
370
+ # over the list of resource instances with automatic pagination.
371
+ #
340
372
  def list( query_hash = nil )
341
373
  raise "Subclasses must implement Hoodoo::Client::Endpoint\#list"
342
374
  end
@@ -50,7 +50,7 @@ module Hoodoo
50
50
  d.action = :list
51
51
  d.query_hash = query_hash
52
52
 
53
- return do_http( d )
53
+ return inject_enumeration_state( do_http( d ), query_hash )
54
54
  end
55
55
 
56
56
  # See Hoodoo::Client::Endpoint#show.
@@ -0,0 +1,94 @@
1
+ ########################################################################
2
+ # File:: paginated_enumeration.rb
3
+ # (C):: Loyalty New Zealand 2016
4
+ #
5
+ # Purpose:: A module that adds support for enumeration over paginated
6
+ # resources.
7
+ # ----------------------------------------------------------------------
8
+ # 29-Sep-2016 (DJO): Created.
9
+ ########################################################################
10
+
11
+ module Hoodoo
12
+ class Client # Just used as a namespace here
13
+
14
+ # Ruby mixin providing an enumeration mechanism, allowing the
15
+ # caller to iterate over all the resource instances in the list,
16
+ # automatically performing the necessary pagination behind the scenes.
17
+ #
18
+ module PaginatedEnumeration
19
+
20
+ # Proc called by enumerate_all to provide the next 'page' of values
21
+ # to be enumerated through. Returns an Hoodoo::Client::AugmentedArray.
22
+ #
23
+ attr_accessor :next_page_proc
24
+
25
+ # Yields each resource instance, automatically paginating
26
+ # through the entire set of resources.
27
+ #
28
+ # Provide a block to process each resource instance. For example:
29
+ #
30
+ # results = members.list(:search => { :surname => 'Smith' } ).enumerate_all do | member |
31
+ # if member.platform_errors.has_errors?
32
+ # .. deal with error ...
33
+ # break
34
+ # else
35
+ # .. process member ...
36
+ # end
37
+ # end
38
+ #
39
+ # Each iteration yields a Hoodoo::Client::AugmentedHash representation of
40
+ # the requested resource instance. The caller must check for errors on
41
+ # the value yielded with each iteration, as per the example above.
42
+ #
43
+ def enumerate_all
44
+
45
+ raise "Must provide a block to enumerate_all" unless block_given?
46
+
47
+ # The first set of results is in 'this' AugmentedArray
48
+ results = self
49
+
50
+ loop do
51
+
52
+ if results.size > 0
53
+
54
+ if results.platform_errors.has_errors?
55
+ raise "Hoodoo::Client:: PaginatedEnumeration#enumerate_all: Unexpected internal state combination of results set and results error indication"
56
+ end
57
+
58
+ # Yield a resource at a time to the caller
59
+ #
60
+ # Note: An inter-resource call in a single service returns each
61
+ # resource as a Hash, which must be converted to AugmentedHash
62
+ results.each do | result |
63
+ yield to_augmented_hash(result)
64
+ end
65
+ results = next_page_proc.call()
66
+ else
67
+ # Return errors in an (empty) AugmentedHash
68
+ if results.platform_errors.has_errors?
69
+ yield copy_hash_errors_and_options( Hoodoo::Client::AugmentedHash.new, results )
70
+ end
71
+ break
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ private
79
+
80
+ # Convert a Hash to an AugmentedHash
81
+ def to_augmented_hash( src )
82
+ src.is_a?( Hoodoo::Client::AugmentedHash ) ? src : Hoodoo::Client::AugmentedHash[ src ]
83
+ end
84
+
85
+ # Copy the platform_errors and response_options from src -> dest
86
+ def copy_hash_errors_and_options( dest, src )
87
+ dest.set_platform_errors( src.platform_errors )
88
+ dest.response_options = src.response_options.dup if src.response_options
89
+ dest
90
+ end
91
+
92
+ end
93
+ end
94
+ end
@@ -53,7 +53,7 @@ module Hoodoo; module Services
53
53
  # See Hoodoo::Client::Endpoint#list.
54
54
  #
55
55
  def list( query_hash = nil )
56
- return @middleware.inter_resource_local(
56
+ result = @middleware.inter_resource_local(
57
57
  :source_interaction => self.interaction(),
58
58
  :discovery_result => @discovery_result,
59
59
  :endpoint => self,
@@ -62,6 +62,7 @@ module Hoodoo; module Services
62
62
 
63
63
  :query_hash => query_hash
64
64
  )
65
+ return inject_enumeration_state( result, query_hash )
65
66
  end
66
67
 
67
68
  # See Hoodoo::Client::Endpoint#show.
@@ -71,7 +71,7 @@ module Hoodoo
71
71
  def list( query_hash = nil )
72
72
  result = preprocess( :list )
73
73
  result = @wrapped_endpoint.list( query_hash ) if result.nil?
74
- return postprocess( result )
74
+ return inject_enumeration_state( postprocess( result ), query_hash )
75
75
  end
76
76
 
77
77
  # See Hoodoo::Client::Endpoint#show.
@@ -12,6 +12,6 @@ module Hoodoo
12
12
  # The Hoodoo gem version. If this changes, ensure that the date in
13
13
  # "hoodoo.gemspec" is correct and run "bundle install" (or "update").
14
14
  #
15
- VERSION = '1.10.0'
15
+ VERSION = '1.11.0'
16
16
 
17
17
  end
@@ -927,9 +927,21 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
927
927
  # history entries
928
928
  #
929
929
  it 'updates work' do
930
- values = ( '1'..'9' ).to_a
930
+ values = ( '1'..'5' ).to_a
931
931
  threads = []
932
932
 
933
+ # The loop below creates a Thread for each 'value', and each Thread
934
+ # consumes a db connection, so we have to check that the pool is big enough
935
+ # to ensure that each thread gets a connection.
936
+ #
937
+ # A better solution would be to temporarily create a connection pool with
938
+ # more connections in it, but attempts to do that broke other parts of this
939
+ # spec :-(
940
+ #
941
+ expect( ActiveRecord::Base.connection_pool.size ).to be >= values.size
942
+ # Reclaim old, unused connections
943
+ ActiveRecord::Base.connection_pool.reap()
944
+
933
945
  @uuids.each do | uuid |
934
946
  values.each do | value |
935
947
  threads << Thread.new do
@@ -946,9 +958,9 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
946
958
  end
947
959
  end
948
960
  end
961
+ threads.each { | thread | thread.join() }
949
962
  end
950
963
 
951
- threads.each { | thread | thread.join() }
952
964
 
953
965
  @uuids.each do | uuid |
954
966
  contemporary = RSpecModelManualDateTest.manually_dated_contemporary.where( :uuid => uuid ).to_a
@@ -32,7 +32,7 @@ describe Hoodoo::Client::Endpoint::HTTP do
32
32
  it 'should successfuly connect with valid certificate chain' do
33
33
  endpoint = connect_to_real_https_endpoint('127.0.0.1', 'spec/files/ca/ca-cert.pem')
34
34
  response = endpoint.list()
35
- expect(response["message"]).to eq("This data is a secret")
35
+ expect(response[0]["message"]).to eq("This data is a secret")
36
36
  end
37
37
 
38
38
  it "should fail when certificate doesn't match the hostname" do
@@ -51,7 +51,8 @@ describe Hoodoo::Client::Endpoint::HTTP do
51
51
 
52
52
  class SslSelfSignedApp
53
53
  def call(env)
54
- return [200, {'Content-Type' => 'application/json'}, ['{"message": "This data is a secret"}'] ]
54
+ # Note: Respond to 'list' calls with correct Hoodoo semantics
55
+ return [200, {'Content-Type' => 'application/json'}, ['{ "_data" : [ { "message": "This data is a secret" } ] }'] ]
55
56
  end
56
57
  end
57
58
 
@@ -0,0 +1,434 @@
1
+ require 'securerandom'
2
+ require 'spec_helper.rb'
3
+
4
+ #
5
+ # These tests define the following Services.
6
+ #
7
+ # Clients can call into any of them to invoke the different calling semantics
8
+ # between them.
9
+ #
10
+ #
11
+ # ┌──────────────────────────────────────────────┐ ┌──────────────────────────┐
12
+ # │ │ │ │
13
+ # │ RSpecNumberService │ │ RSpecRemoteNumberService │
14
+ # │ │ │ │
15
+ # │ │ │ │
16
+ # │ ┌──────────────┐ ┌────────────────┐│ │ ┌───────────────────┐ │
17
+ # │ │ │ inter │ ││ │ │ │ │
18
+ # │ │ RSpecNumber │◀resource ─│RSpecEvenNumber ││ │ │ RSpecOddNumber │ │
19
+ # │ │ │ local │ ││ │ │ │ │
20
+ # │ └──────────────┘ └────────────────┘│ │ └───────────────────┘ │
21
+ # │ ▲ │ │ │ │
22
+ # │ │ inter │ │ │ │
23
+ # │ └───────────────────────────resource ┼─┼────────────┘ │
24
+ # │ remote │ │ │
25
+ # └──────────────────────────────────────────────┘ └──────────────────────────┘
26
+ #
27
+ # To start the services in your specs do:
28
+ #
29
+ # spec_helper_start_svc_app_in_thread_for( RSpecNumberService )
30
+ # spec_helper_start_svc_app_in_thread_for( RSpecRemoteNumberService)
31
+ #
32
+
33
+ ################################################################################
34
+ #
35
+ # Create a 'RSpecNumber' Resource with the following properties:
36
+ #
37
+ # - manages 'Number' resources ie: { 'number': 3 }, for numbers between 0 & 999
38
+ # - provides a public 'list' endpoint (no session needed)
39
+ # - pagination
40
+ # - will generate an error when asked to retrieve any 'Number' resource with a
41
+ # number value >= 500 && filter_data['force_error'] is set (to anything)
42
+ #
43
+ class RSpecNumberImplementation < Hoodoo::Services::Implementation
44
+
45
+ public
46
+
47
+ # Number resources are all in this range
48
+ NUMBER_RANGE = 0..999
49
+
50
+ # Number resources that generate errors are all in this range
51
+ ERROR_RANGE = 500..999
52
+
53
+ def list( context )
54
+ request = context.request
55
+
56
+ resources = []
57
+ implode = false
58
+ 0.upto( request.list.limit - 1 ) do |i|
59
+ num = request.list.offset + i
60
+ implode = implode || ERROR_RANGE.include?( num )
61
+ if NUMBER_RANGE.include?( num )
62
+ resources << { 'number' => num }
63
+ else
64
+ break
65
+ end
66
+ end
67
+
68
+ context.response.set_resources( resources, resources.count )
69
+ if implode && request.list.filter_data[ 'force_error' ]
70
+ context.response.add_error( 'platform.malformed' )
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ #
77
+ # Interface for our implementation
78
+ #
79
+ class RSpecNumberInterface < Hoodoo::Services::Interface
80
+ interface :RSpecNumber do
81
+ endpoint :numbers, RSpecNumberImplementation
82
+ to_list do
83
+ filter :force_error
84
+ end
85
+ public_actions :list
86
+ end
87
+ end
88
+
89
+
90
+ ################################################################################
91
+ #
92
+ # Create a 'RSpecEvenNumber' Resource with the following properties:
93
+ #
94
+ # - Calls RSpecNumber via the 'inter_resource_local' calling mechanism
95
+ # - Only returns 'even' numbers, 0, 2, 4... for numbers between 0 & 999
96
+ # - provides a public 'list' endpoint (no session needed)
97
+ #
98
+ # See RSpecNumberImplementation for error handling etc
99
+ #
100
+ class RSpecEvenNumberImplementation < Hoodoo::Services::Implementation
101
+
102
+ public
103
+
104
+ def list( context )
105
+ request = context.request
106
+ endpoint = context.resource( :RSpecNumber, 1 )
107
+ resources = []
108
+ limit = request.list.limit ? request.list.limit : 50
109
+ offset = request.list.offset ? request.list.offset : 0
110
+
111
+ # We always iterate through every Number resource - yeah its dumb
112
+ endpoint.list( { :filter => request.list.filter_data } ).enumerate_all do | number_res |
113
+
114
+ if number_res.platform_errors.has_errors?
115
+ context.response.add_errors( number_res.platform_errors )
116
+ break
117
+ end
118
+
119
+ number = number_res['number']
120
+
121
+ # Number in the correct range & is 'even'
122
+ resources << number_res if number >= ( offset * 2 ) && number.even?
123
+ break if resources.size >= limit
124
+
125
+ end
126
+
127
+ context.response.set_resources( resources, resources.count )
128
+ end
129
+
130
+ end
131
+
132
+ #
133
+ # Interface for our implementation
134
+ #
135
+ class RSpecEvenNumberInterface < Hoodoo::Services::Interface
136
+ interface :RSpecEvenNumber do
137
+ endpoint :even_numbers, RSpecEvenNumberImplementation
138
+ to_list do
139
+ filter :force_error
140
+ end
141
+ public_actions :list
142
+ end
143
+ end
144
+
145
+ ################################################################################
146
+ #
147
+ # Define our service, that implements both resources
148
+ #
149
+ class RSpecNumberService < Hoodoo::Services::Service
150
+ comprised_of RSpecNumberInterface,
151
+ RSpecEvenNumberInterface
152
+ end
153
+
154
+
155
+ ################################################################################
156
+ #
157
+ # Create a 'RSpecOddNumber' Resource with the following properties:
158
+ #
159
+ # - Calls RSpecNumber via the 'inter_resource_remote' calling mechanism
160
+ # - Only returns 'odd' numbers, 1, 3, 5 ... for numbers between 0 & 999
161
+ # - provides a public 'list' endpoint (no session needed)
162
+ #
163
+ # See RSpecNumberImplementation for error handling etc
164
+ #
165
+ class RSpecOddNumberImplementation < Hoodoo::Services::Implementation
166
+
167
+ public
168
+
169
+ def list( context )
170
+ request = context.request
171
+ endpoint = context.resource( :RSpecNumber, 1 )
172
+ resources = []
173
+ limit = request.list.limit ? request.list.limit : 50
174
+ offset = request.list.offset ? request.list.offset : 0
175
+
176
+ # We always iterate through every Number resource - yeah its dumb
177
+ endpoint.list( { :filter => request.list.filter_data } ).enumerate_all do | number_res |
178
+
179
+ if number_res.platform_errors.has_errors?
180
+ context.response.add_errors( number_res.platform_errors )
181
+ break
182
+ end
183
+
184
+ number = number_res['number']
185
+
186
+ # Number in the correct range & is 'odd'
187
+ resources << number_res if number >= ( offset * 2 ) && number.odd?
188
+ break if resources.size >= limit
189
+
190
+ end
191
+
192
+ context.response.set_resources( resources, resources.count )
193
+ end
194
+
195
+ end
196
+
197
+ #
198
+ # Interface for our implementation
199
+ #
200
+ class RSpecOddNumberInterface < Hoodoo::Services::Interface
201
+ interface :RSpecOddNumber do
202
+ endpoint :odd_numbers, RSpecOddNumberImplementation
203
+ to_list do
204
+ filter :force_error
205
+ end
206
+ public_actions :list
207
+ end
208
+ end
209
+
210
+ ################################################################################
211
+ #
212
+ # Define our service, that implements both resources
213
+ #
214
+ class RSpecRemoteNumberService < Hoodoo::Services::Service
215
+ comprised_of RSpecOddNumberInterface
216
+ end
217
+
218
+
219
+
220
+ ##############################################################################
221
+ # Tests
222
+ ##############################################################################
223
+
224
+ describe Hoodoo::Client do
225
+
226
+ before :all do
227
+
228
+ # Start our services in background threads
229
+ spec_helper_start_svc_app_in_thread_for( RSpecNumberService )
230
+ spec_helper_start_svc_app_in_thread_for( RSpecRemoteNumberService )
231
+
232
+ end
233
+
234
+ before :each do
235
+
236
+ @client = Hoodoo::Client.new({
237
+ drb_port: URI.parse( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri() ).port,
238
+ auto_session: false
239
+ })
240
+
241
+ end
242
+
243
+ context 'happy path behaviour' do
244
+
245
+ let( :resources ) { [
246
+ {
247
+ endpoint: @client.resource( :RSpecNumber, 1 ),
248
+ data: (0..999).to_a
249
+ },
250
+ {
251
+ endpoint: @client.resource( :RSpecEvenNumber, 1 ),
252
+ data: (0..999).step(2).to_a
253
+ },
254
+ {
255
+ endpoint: @client.resource( :RSpecOddNumber, 1 ),
256
+ data: (1..999).step(2).to_a
257
+ },
258
+ ] }
259
+
260
+ it 'returns every single result with the correct value' do
261
+
262
+ resources.each do | resource |
263
+ numbers = []
264
+
265
+ resource[ :endpoint ].list.enumerate_all do | result |
266
+ expect( result.platform_errors.errors ).to eq( [] )
267
+ break if result.platform_errors.has_errors?
268
+ numbers << result[ 'number' ]
269
+ end
270
+
271
+ expect( numbers ).to eq( resource[ :data ] )
272
+ end
273
+
274
+ end
275
+
276
+ context 'different "limit" sizes' do
277
+
278
+ let(:limits) {
279
+ # Note: Smaller limits will make the tests very slow
280
+ [ 250, 500, 750, 999, 1000, 1001 ]
281
+ }
282
+
283
+ it 'enumerates correctly with different batch sizes' do
284
+
285
+ resources.each do | resource |
286
+ limits.each do | limit |
287
+ numbers = []
288
+
289
+ resource[ :endpoint ].list( { 'limit' => limit } ).enumerate_all do | result |
290
+ expect( result.platform_errors.errors ).to eq( [] )
291
+ break if result.platform_errors.has_errors?
292
+ numbers << result[ 'number' ]
293
+ end
294
+
295
+ expect( numbers ).to eq( resource[ :data ] )
296
+ end
297
+ end
298
+
299
+ end
300
+
301
+ end
302
+
303
+ end
304
+
305
+ context 'error handling behaviour' do
306
+
307
+ let( :resources ) { [
308
+ {
309
+ endpoint: @client.resource( :RSpecNumber, 1 ),
310
+ expected_results: [
311
+ {
312
+ limit: 10,
313
+ data: ( 0..499 ).to_a,
314
+ },
315
+ {
316
+ limit: 250,
317
+ data: ( 0..499 ).to_a,
318
+ },
319
+ {
320
+ limit: 499,
321
+ data: ( 0..498 ).to_a,
322
+ },
323
+ {
324
+ limit: 500,
325
+ data: ( 0..499 ).to_a,
326
+ },
327
+ {
328
+ limit: 501,
329
+ data: [],
330
+ },
331
+ ]
332
+ },
333
+ {
334
+ endpoint: @client.resource( :RSpecEvenNumber, 1 ),
335
+ expected_results: [
336
+ {
337
+ limit: 10,
338
+ data: ( 0..498 ).step(2).to_a
339
+ },
340
+ {
341
+ limit: 249,
342
+ data: ( 0..496 ).step(2).to_a
343
+ },
344
+ {
345
+ limit: 250,
346
+ data: ( 0..498 ).step(2).to_a
347
+ },
348
+ {
349
+ limit: 251,
350
+ data: []
351
+ },
352
+ ]
353
+ },
354
+ {
355
+ endpoint: @client.resource( :RSpecOddNumber, 1 ),
356
+ expected_results: [
357
+ {
358
+ limit: 10,
359
+ data: ( 1..499 ).step(2).to_a
360
+ },
361
+ {
362
+ limit: 249,
363
+ data: ( 1..497 ).step(2).to_a
364
+ },
365
+ {
366
+ limit: 250,
367
+ data: ( 1..499 ).step(2).to_a
368
+ },
369
+ {
370
+ limit: 251,
371
+ data: []
372
+ },
373
+ ]
374
+ },
375
+ ] }
376
+
377
+ it 'returns values until an error occurs in the "list" call' do
378
+
379
+ resources.each do | resource |
380
+ resource[ :expected_results ].each do | expected |
381
+
382
+ numbers = []
383
+ errors = 0
384
+ query_hash = {
385
+ 'limit' => expected[ :limit ],
386
+ 'filter' => {
387
+ 'force_error' => 'true'
388
+ }
389
+ }
390
+
391
+ resource[ :endpoint ].list( query_hash ).enumerate_all do | result |
392
+ numbers << result[ 'number' ] if result.has_key? 'number'
393
+ errors += 1 if result.platform_errors.has_errors?
394
+ end
395
+
396
+ # The number of valid resources that you recieve is dependent on
397
+ # the 'limit' size that is passed through on the 'list' call
398
+ #
399
+ # Thats because the system will enumerate through an entire batch of
400
+ # resources (of size limit), OR return an error.
401
+ #
402
+ # So the underlying service retrieves 50 valid resources and returns
403
+ # then the caller will enumerate through those 50. On the other hand if
404
+ # the service reads 50 resources, and then detects an error on the 51st
405
+ # then 0 resources are retuned, only an error!
406
+ #
407
+ expect( numbers ).to eq( expected[ :data ] )
408
+ # Check that an error is returned
409
+ expect( errors ).to eq( 1 )
410
+ end
411
+ end
412
+
413
+ end
414
+
415
+
416
+ it 'raises an exception if no block supplied' do
417
+
418
+ endpoints = [
419
+ @client.resource( :RSpecNumber, 1 ),
420
+ @client.resource( :RSpecEvenNumber, 1 ),
421
+ @client.resource( :RSpecOddNumber, 1 ),
422
+ ]
423
+
424
+ endpoints.each do | endpoint |
425
+ expect {
426
+ endpoint.list.enumerate_all
427
+ }.to raise_exception( RuntimeError, 'Must provide a block to enumerate_all' )
428
+ end
429
+
430
+ end
431
+
432
+ end
433
+
434
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoodoo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loyalty New Zealand
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-23 00:00:00.000000000 Z
11
+ date: 2016-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kgio
@@ -285,6 +285,7 @@ files:
285
285
  - lib/hoodoo/client/endpoint/endpoints/http_based.rb
286
286
  - lib/hoodoo/client/endpoint/endpoints/not_found.rb
287
287
  - lib/hoodoo/client/headers.rb
288
+ - lib/hoodoo/client/paginated_enumeration.rb
288
289
  - lib/hoodoo/communicators.rb
289
290
  - lib/hoodoo/communicators/fast.rb
290
291
  - lib/hoodoo/communicators/pool.rb
@@ -395,6 +396,7 @@ files:
395
396
  - spec/client/endpoint/endpoints/http_spec.rb
396
397
  - spec/client/endpoint/endpoints/not_found_spec.rb
397
398
  - spec/client/headers_spec.rb
399
+ - spec/client/paginated_enumeration_spec.rb
398
400
  - spec/communicators/fast_spec.rb
399
401
  - spec/communicators/pool_spec.rb
400
402
  - spec/communicators/slow_spec.rb
@@ -528,6 +530,7 @@ test_files:
528
530
  - spec/client/endpoint/endpoints/http_spec.rb
529
531
  - spec/client/endpoint/endpoints/not_found_spec.rb
530
532
  - spec/client/headers_spec.rb
533
+ - spec/client/paginated_enumeration_spec.rb
531
534
  - spec/communicators/fast_spec.rb
532
535
  - spec/communicators/pool_spec.rb
533
536
  - spec/communicators/slow_spec.rb