couch_potato 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e0a3143ad59fbb9f3391e381841412de37afda869b90c3b105b3efe41859fa2
4
- data.tar.gz: 452e6d3cc546b0d45feb5ea94ea81779400adf6474e22580e6637d15f58858bb
3
+ metadata.gz: fc65386f8f391b222c93733fbf83cb00050bc37b2fa1787be8d73e4847b2fa43
4
+ data.tar.gz: a2c6fe4017c646b3bceaa9baaa236044ffe286fd3380095296a602034511d817
5
5
  SHA512:
6
- metadata.gz: f517b4ecfaf2c57eceade400298c68ef2d189f1274709c95f7bd54d97721b9131b79430956e5c517cd2fbd3781149ff9fe54c4640eaea8e82b940e97c696fd04
7
- data.tar.gz: a668623b7cd70ab1acb86aff299f8729f8645625b560f3b45247447117c9ac69d5aa335d57ff9dacaa980cd021d2f01f5e21c0a88f5faa45d5add8045e016e21
6
+ metadata.gz: 5f7c933270982e090183aacdb7fdd52e76e2739476e7e4d87cbcad1239c62b4973f31ce62278f181c33612bc6c2dc8ee7abbc2ffca0bef4560b919b8a37359c8
7
+ data.tar.gz: 7f79c9a6b3c31f5f1fc0eea3f4a16da6e7cb6ace5a68232a9a127d7d056b5144d88714e12e128a64eba34a9377e073311408077958c14b818c0f4037853a59a5
data/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## Changes
2
2
 
3
+ # 1.11.0
4
+
5
+ - improve view_in_batches performance by switching to using startkey_docid over skip
6
+
3
7
  ### 1.10.1
4
8
 
5
9
  - support passing an empty array to CouchPotato::Database#load
@@ -65,12 +65,27 @@ module CouchPotato
65
65
  # to a given block in batches of the given size, making multiple
66
66
  # requests with according skip/limit params sent to CouchDB.
67
67
  def view_in_batches(spec, batch_size: default_batch_size)
68
+ rows = nil
68
69
  batch = 0
69
70
  loop do
70
- spec.view_parameters = spec.view_parameters.merge({ skip: batch * batch_size, limit: batch_size })
71
- results = view(spec)
72
- yield results
73
- break if results.size < batch_size
71
+ spec.view_parameters = spec
72
+ .view_parameters
73
+ .merge({limit: batch_size})
74
+ .merge(
75
+ if rows
76
+ {
77
+ startkey: rows&.last&.dig('key'),
78
+ startkey_docid: rows&.last&.dig('id'),
79
+ skip: 1
80
+ }
81
+ else
82
+ {}
83
+ end
84
+ )
85
+ result = raw_view(spec)
86
+ rows = result['rows']
87
+ yield process_view_results(result, spec)
88
+ break if rows.size < batch_size
74
89
 
75
90
  batch += 1
76
91
  end
@@ -198,27 +213,34 @@ module CouchPotato
198
213
 
199
214
  def view_without_caching(spec)
200
215
  ActiveSupport::Notifications.instrument('couch_potato.view', name: "#{spec.design_document}/#{spec.view_name}") do
201
- results = CouchPotato::View::ViewQuery.new(
202
- couchrest_database,
203
- spec.design_document,
204
- { spec.view_name => {
205
- map: spec.map_function,
206
- reduce: spec.reduce_function
207
- } },
208
- ({ spec.list_name => spec.list_function } unless spec.list_name.nil?),
209
- spec.lib,
210
- spec.language
211
- ).query_view!(spec.view_parameters)
212
- processed_results = spec.process_results results
213
- if processed_results.respond_to?(:database=)
214
- processed_results.database = self
215
- elsif processed_results.respond_to?(:each)
216
- processed_results.each do |document|
217
- document.database = self if document.respond_to?(:database=)
218
- end
216
+ process_view_results(raw_view(spec), spec)
217
+ end
218
+ end
219
+
220
+ def process_view_results(results, spec)
221
+ processed_results = spec.process_results results
222
+ if processed_results.respond_to?(:database=)
223
+ processed_results.database = self
224
+ elsif processed_results.respond_to?(:each)
225
+ processed_results.each do |document|
226
+ document.database = self if document.respond_to?(:database=)
219
227
  end
220
- processed_results
221
228
  end
229
+ processed_results
230
+ end
231
+
232
+ def raw_view(spec)
233
+ CouchPotato::View::ViewQuery.new(
234
+ couchrest_database,
235
+ spec.design_document,
236
+ { spec.view_name => {
237
+ map: spec.map_function,
238
+ reduce: spec.reduce_function
239
+ } },
240
+ ({ spec.list_name => spec.list_function } unless spec.list_name.nil?),
241
+ spec.lib,
242
+ spec.language
243
+ ).query_view!(spec.view_parameters)
222
244
  end
223
245
 
224
246
  def load_document_without_caching(id)
@@ -1,4 +1,4 @@
1
1
  module CouchPotato
2
- VERSION = '1.10.1'.freeze
2
+ VERSION = '1.11.0'.freeze
3
3
  RSPEC_VERSION = '4.0.2'.freeze
4
4
  end
@@ -430,11 +430,11 @@ describe CouchPotato::Database, '#view_in_batches' do
430
430
  let(:view_query) do
431
431
  instance_double(
432
432
  CouchPotato::View::ViewQuery,
433
- query_view!: { 'rows' => [result] }
433
+ query_view!: { 'rows' => [] }
434
434
  )
435
435
  end
436
- let(:result) { double('result') }
437
- let(:spec) { double('view spec', process_results: [result]).as_null_object }
436
+ let(:processed_result) { double(:processed_result) }
437
+ let(:spec) { double('view spec', process_results: processed_result).as_null_object }
438
438
  let(:couchrest_db) { double('couchrest db').as_null_object }
439
439
  let(:db) { CouchPotato::Database.new(couchrest_db) }
440
440
 
@@ -443,22 +443,41 @@ describe CouchPotato::Database, '#view_in_batches' do
443
443
  .to receive_messages(new: view_query)
444
444
  end
445
445
 
446
- it 'sets skip/limit for each batch' do
447
- allow(spec).to receive(:process_results).and_return([result, result], [result]) # run twice
446
+ it 'sets no skip/startkey/startkey_docid for the first batch' do
448
447
  allow(spec).to receive(:view_parameters) { { key: 'x' } }
449
448
 
450
449
  expect(spec).to receive(:view_parameters=)
451
- .with({key: 'x', skip: 0, limit: 2})
450
+ .with({key: 'x', limit: 2})
451
+
452
+ db.view_in_batches(spec, batch_size: 2) { |results| }
453
+ end
454
+
455
+ it 'sets skip/startkey/startkey_docid for each other batch' do
456
+ allow(spec).to receive(:view_parameters) { { key: 'x' } }
457
+ allow(view_query).to receive(:query_view!)
458
+ .and_return({'rows' => [{}, {'key' => 'k1', 'id' => 'id1'}]}, {'rows' => [{}]})
459
+ allow(spec).to receive(:view_parameters=)
460
+
452
461
  expect(spec).to receive(:view_parameters=)
453
- .with({key: 'x', skip: 2, limit: 2})
462
+ .with({key: 'x', limit: 2, startkey: 'k1', startkey_docid: 'id1', skip: 1})
454
463
 
455
464
  db.view_in_batches(spec, batch_size: 2) { |results| }
456
465
  end
457
466
 
467
+ it 'yields processed results to the block' do
468
+ allow(view_query).to receive(:query_view!)
469
+ .and_return({'rows' => [{'key' => 'k1', 'id' => 'id1'}]})
470
+ allow(spec).to receive(:view_parameters=)
471
+
472
+ expect { |x| db.view_in_batches(spec, batch_size: 2, &x) }.to yield_with_args(processed_result)
473
+ end
474
+
458
475
  it 'yields batches until running out of data' do
459
- allow(spec).to receive(:process_results).and_return([result, result], [result])
476
+ allow(view_query).to receive(:query_view!)
477
+ .and_return({'rows' => [{}, {}]}, {'rows' => [{}]})
478
+ allow(spec).to receive(:process_results).and_return([processed_result, processed_result], [processed_result])
460
479
 
461
- expect { |b| db.view_in_batches(spec, batch_size: 2, &b) }.to yield_successive_args([result, result], [result])
480
+ expect { |b| db.view_in_batches(spec, batch_size: 2, &b) }.to yield_successive_args([processed_result, processed_result], [processed_result])
462
481
  end
463
482
  end
464
483
 
data/spec/views_spec.rb CHANGED
@@ -405,4 +405,15 @@ describe 'views' do
405
405
  expect(@db.view(Build.timeline(stale: 'ok'))).to be_empty
406
406
  end
407
407
  end
408
+
409
+ describe 'view_in_batches' do
410
+ it 'yields docs in batches until all gone' do
411
+ build1 = Build.new(time: 1).tap {|b| @db.save!(b) }
412
+ build2 = Build.new(time: 2).tap {|b| @db.save!(b) }
413
+ build3 = Build.new(time: 3).tap {|b| @db.save!(b) }
414
+
415
+ expect {|block| @db.view_in_batches(Build.timeline, batch_size: 2, &block)}
416
+ .to yield_successive_args([build1, build2], [build3])
417
+ end
418
+ end
408
419
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couch_potato
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.1
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Lang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-07 00:00:00.000000000 Z
11
+ date: 2022-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel