baza.rb 0.9.10 → 0.9.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fcbc7506438df13060cabc32fb5d87bb684a10a63f045d3d204788751f8e8ab5
4
- data.tar.gz: 1e672c028f2b97bed37fedb335d9dd535a625295cbcd8592909ddf865d26b551
3
+ metadata.gz: 70695fd3879e61407e448c32960af00dd5fcf3df08014551073b4e6041a5cc6f
4
+ data.tar.gz: 6c407fbb83271e68b5da3eba246b35ece2326f63f66ca89d4609ac7ad7be4ce6
5
5
  SHA512:
6
- metadata.gz: d6300c6a5a7ee6fcd2de409901b42b3331166470348510721a3b5bbd667f69351de04cb52409b68a116cd22bea5aaa7a8c963c7167112467a3afb92796fa5aa5
7
- data.tar.gz: fc58aab87af51e458bc6a20b91693f83f8a32507c504efcabc214fbd6e9be6c4402325bb4154326a9d8def4faed26a8ecf450251540a00cb89d1f0774f7308a5
6
+ metadata.gz: 80f1abe9dccf135b5cd75d1389c52bb28423014cf588a1ea66738576e8808d104d967a69108f459e590ebee9b2772abca3a419db7c8412f73d0114244d5d3b4e
7
+ data.tar.gz: 8244c0a1d7db36a251380fb911df2bcebc2ac61a1f9aae52d0cb0ef852160c31761402e8164915665c80be651d685730063f0a680012120bdb57f4d52d0cc7f4
data/Gemfile CHANGED
@@ -23,7 +23,7 @@ gem 'rubocop-minitest', '~>0.38', require: false
23
23
  gem 'rubocop-performance', '~>1.23', require: false
24
24
  gem 'rubocop-rake', '~>0.7', require: false
25
25
  gem 'simplecov', '~>0.22', require: false
26
- gem 'simplecov-cobertura', '~>2.1', require: false
26
+ gem 'simplecov-cobertura', '~>3.0', require: false
27
27
  gem 'sinatra', '~>4.1', require: false
28
28
  gem 'wait_for', '~>0.1', require: false
29
29
  gem 'webmock', '~>3.24', require: false
data/Gemfile.lock CHANGED
@@ -36,7 +36,7 @@ GEM
36
36
  ellipsized (0.3.0)
37
37
  ethon (0.16.0)
38
38
  ffi (>= 1.15.0)
39
- factbase (0.13.0)
39
+ factbase (0.14.0)
40
40
  backtrace (~> 0.4)
41
41
  decoor (~> 0.0)
42
42
  ellipsized (~> 0.3)
@@ -65,7 +65,7 @@ GEM
65
65
  ffi (1.17.2-x86_64-linux-gnu)
66
66
  hashdiff (1.2.0)
67
67
  iri (0.11.2)
68
- json (2.12.2)
68
+ json (2.13.1)
69
69
  language_server-protocol (3.17.0.5)
70
70
  lint_roller (1.1.0)
71
71
  logger (1.7.0)
@@ -83,13 +83,13 @@ GEM
83
83
  net-http (0.6.0)
84
84
  uri
85
85
  nio4r (2.7.4)
86
- nokogiri (1.18.8-arm64-darwin)
86
+ nokogiri (1.18.9-arm64-darwin)
87
87
  racc (~> 1.4)
88
- nokogiri (1.18.8-x64-mingw-ucrt)
88
+ nokogiri (1.18.9-x64-mingw-ucrt)
89
89
  racc (~> 1.4)
90
- nokogiri (1.18.8-x86_64-darwin)
90
+ nokogiri (1.18.9-x86_64-darwin)
91
91
  racc (~> 1.4)
92
- nokogiri (1.18.8-x86_64-linux-gnu)
92
+ nokogiri (1.18.9-x86_64-linux-gnu)
93
93
  racc (~> 1.4)
94
94
  online (0.0.1)
95
95
  timeout (~> 0.4)
@@ -126,7 +126,7 @@ GEM
126
126
  regexp_parser (2.10.0)
127
127
  retries (0.0.5)
128
128
  rexml (3.4.1)
129
- rubocop (1.78.0)
129
+ rubocop (1.79.0)
130
130
  json (~> 2.3)
131
131
  language_server-protocol (~> 3.17.0.2)
132
132
  lint_roller (~> 1.1.0)
@@ -134,10 +134,11 @@ GEM
134
134
  parser (>= 3.3.0.2)
135
135
  rainbow (>= 2.2.2, < 4.0)
136
136
  regexp_parser (>= 2.9.3, < 3.0)
137
- rubocop-ast (>= 1.45.1, < 2.0)
137
+ rubocop-ast (>= 1.46.0, < 2.0)
138
138
  ruby-progressbar (~> 1.7)
139
+ tsort (>= 0.2.0)
139
140
  unicode-display_width (>= 2.4.0, < 4.0)
140
- rubocop-ast (1.45.1)
141
+ rubocop-ast (1.46.0)
141
142
  parser (>= 3.3.7.2)
142
143
  prism (~> 1.4)
143
144
  rubocop-minitest (0.38.1)
@@ -157,7 +158,7 @@ GEM
157
158
  docile (~> 1.1)
158
159
  simplecov-html (~> 0.11)
159
160
  simplecov_json_formatter (~> 0.1)
160
- simplecov-cobertura (2.1.0)
161
+ simplecov-cobertura (3.0.0)
161
162
  rexml
162
163
  simplecov (~> 0.19)
163
164
  simplecov-html (0.13.1)
@@ -172,6 +173,7 @@ GEM
172
173
  tago (0.1.0)
173
174
  tilt (2.6.1)
174
175
  timeout (0.4.3)
176
+ tsort (0.2.0)
175
177
  typhoeus (1.4.1)
176
178
  ethon (>= 0.9.0)
177
179
  unicode-display_width (3.1.4)
@@ -215,7 +217,7 @@ DEPENDENCIES
215
217
  rubocop-performance (~> 1.23)
216
218
  rubocop-rake (~> 0.7)
217
219
  simplecov (~> 0.22)
218
- simplecov-cobertura (~> 2.1)
220
+ simplecov-cobertura (~> 3.0)
219
221
  sinatra (~> 4.1)
220
222
  wait_for (~> 0.1)
221
223
  webmock (~> 3.24)
@@ -13,5 +13,5 @@
13
13
  # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
14
  # License:: MIT
15
15
  class BazaRb
16
- VERSION = '0.9.10'
16
+ VERSION = '0.9.12'
17
17
  end
data/lib/baza-rb.rb CHANGED
@@ -57,9 +57,10 @@ class BazaRb
57
57
  # @param [Boolean] ssl Whether to use SSL/HTTPS (default: true)
58
58
  # @param [Float] timeout Connection and request timeout in seconds (default: 30)
59
59
  # @param [Integer] retries Number of retries on connection failure (default: 3)
60
+ # @param [Integer] pause The factor on pause (<1 means faster, >1 means slower)
60
61
  # @param [Loog] loog The logging facility (default: Loog::NULL)
61
62
  # @param [Boolean] compress Whether to use GZIP compression for requests/responses (default: true)
62
- def initialize(host, port, token, ssl: true, timeout: 30, retries: 3, loog: Loog::NULL, compress: true)
63
+ def initialize(host, port, token, ssl: true, timeout: 30, retries: 5, pause: 1, loog: Loog::NULL, compress: true)
63
64
  @host = host
64
65
  @port = port
65
66
  @ssl = ssl
@@ -67,6 +68,7 @@ class BazaRb
67
68
  @timeout = timeout
68
69
  @loog = loog
69
70
  @retries = retries
71
+ @pause = pause
70
72
  @compress = compress
71
73
  end
72
74
 
@@ -644,19 +646,37 @@ class BazaRb
644
646
  with_retries(max_tries: @retries, rescue: TimedOut, &)
645
647
  end
646
648
 
647
- # Execute a block with retries on 429 and 500 status codes.
649
+ # Execute a block with retries on 429 status codes.
648
650
  #
649
651
  # @yield The block to execute with retries
650
652
  # @return [Object] The result of the block execution
651
653
  def retry_if_server_busy(&)
652
- allowed = [429, 500]
653
654
  attempt = 0
654
655
  loop do
655
656
  ret = yield
656
- if allowed.include?(ret.code) && attempt < 5
657
+ if ret.code == 429 && attempt < @retries
657
658
  attempt += 1
658
- seconds = 2**attempt
659
- @loog.info("Now, will sleep for #{seconds} and try again...")
659
+ seconds = @pause * (2**attempt)
660
+ @loog.info("Server seems to be busy, will sleep for #{seconds} (attempt no.#{attempt})...")
661
+ sleep(seconds)
662
+ next
663
+ end
664
+ return ret
665
+ end
666
+ end
667
+
668
+ # Execute a block with retries on 500 status codes.
669
+ #
670
+ # @yield The block to execute with retries
671
+ # @return [Object] The result of the block execution
672
+ def retry_if_server_failed(&)
673
+ attempt = 0
674
+ loop do
675
+ ret = yield
676
+ if ret.code >= 500 && attempt < @retries
677
+ attempt += 1
678
+ seconds = @pause * (2**attempt)
679
+ @loog.info("Server seems to be in trouble, will sleep for #{seconds} (attempt no.#{attempt})...")
660
680
  sleep(seconds)
661
681
  next
662
682
  end
@@ -721,13 +741,15 @@ class BazaRb
721
741
  def get(uri, allowed = [200])
722
742
  retry_it do
723
743
  checked(
724
- retry_if_server_busy do
725
- Typhoeus::Request.get(
726
- uri.to_s,
727
- headers:,
728
- connecttimeout: @timeout,
729
- timeout: @timeout
730
- )
744
+ retry_if_server_failed do
745
+ retry_if_server_busy do
746
+ Typhoeus::Request.get(
747
+ uri.to_s,
748
+ headers:,
749
+ connecttimeout: @timeout,
750
+ timeout: @timeout
751
+ )
752
+ end
731
753
  end,
732
754
  allowed
733
755
  )
@@ -744,13 +766,15 @@ class BazaRb
744
766
  def post(uri, params, allowed = [302])
745
767
  retry_it do
746
768
  checked(
747
- Typhoeus::Request.post(
748
- uri.to_s,
749
- body: params.merge('_csrf' => csrf),
750
- headers:,
751
- connecttimeout: @timeout,
752
- timeout: @timeout
753
- ),
769
+ retry_if_server_failed do
770
+ Typhoeus::Request.post(
771
+ uri.to_s,
772
+ body: params.merge('_csrf' => csrf),
773
+ headers:,
774
+ connecttimeout: @timeout,
775
+ timeout: @timeout
776
+ )
777
+ end,
754
778
  allowed
755
779
  )
756
780
  end
@@ -768,25 +792,31 @@ class BazaRb
768
792
  chunk = 0
769
793
  elapsed(@loog) do
770
794
  loop do
771
- request = Typhoeus::Request.new(
772
- uri.to_s,
773
- method: :get,
774
- headers: headers.merge(
775
- 'Accept' => '*',
776
- 'Accept-Encoding' => 'gzip',
777
- 'Range' => "bytes=#{File.size(file)}-"
778
- ),
779
- connecttimeout: @timeout,
780
- timeout: @timeout
781
- )
782
795
  slice = ''
783
- request.on_body do |data|
784
- slice += data
785
- end
786
- retry_it do
787
- request.run
796
+ ret = nil
797
+ retry_if_server_busy do
798
+ retry_if_server_failed do
799
+ slice = ''
800
+ request = Typhoeus::Request.new(
801
+ uri.to_s,
802
+ method: :get,
803
+ headers: headers.merge(
804
+ 'Accept' => '*',
805
+ 'Accept-Encoding' => 'gzip',
806
+ 'Range' => "bytes=#{File.size(file)}-"
807
+ ),
808
+ connecttimeout: @timeout,
809
+ timeout: @timeout
810
+ )
811
+ request.on_body do |data|
812
+ slice += data
813
+ end
814
+ retry_it do
815
+ request.run
816
+ end
817
+ ret = request.response
818
+ end
788
819
  end
789
- ret = request.response
790
820
  msg = [
791
821
  "GET #{uri.to_uri.path} #{ret.code}",
792
822
  "#{slice.bytesize} bytes",
@@ -860,10 +890,14 @@ class BazaRb
860
890
  ret =
861
891
  retry_it do
862
892
  checked(
863
- Typhoeus::Request.put(
864
- uri.to_s,
865
- params
866
- )
893
+ retry_if_server_failed do
894
+ retry_if_server_busy do
895
+ Typhoeus::Request.put(
896
+ uri.to_s,
897
+ params
898
+ )
899
+ end
900
+ end
867
901
  )
868
902
  end
869
903
  sent += params[:body].bytesize
data/test/test_baza-rb.rb CHANGED
@@ -354,18 +354,6 @@ class TestBazaRb < Minitest::Test
354
354
  end
355
355
  end
356
356
 
357
- def test_push_with_server_failure
358
- WebMock.disable_net_connect!
359
- stub_request(:put, 'https://example.org/push/foo')
360
- .to_return(status: 503, body: 'oops', headers: { 'X-Zerocracy-Failure': 'the failure' })
361
- .to_raise('why second time?')
362
- e = assert_raises(StandardError) { fake_baza.push('foo', 'data', []) }
363
- [
364
- 'Invalid response code #503',
365
- '"the failure"'
366
- ].each { |t| assert_includes(e.message, t, "Can't find '#{t}' in #{e.message.inspect}") }
367
- end
368
-
369
357
  def test_real_http
370
358
  WebMock.enable_net_connect!
371
359
  skip('We are offline') unless we_are_online?
@@ -705,6 +693,49 @@ class TestBazaRb < Minitest::Test
705
693
  assert_equal('testuser', fake_baza.whoami)
706
694
  end
707
695
 
696
+ def test_download_retries_on_busy_server
697
+ WebMock.disable_net_connect!
698
+ Dir.mktmpdir do |dir|
699
+ file = File.join(dir, 'download.txt')
700
+ attempts = 0
701
+ stub_request(:get, 'https://example.org:443/file')
702
+ .with(headers: { 'Range' => 'bytes=0-' })
703
+ .to_return do |_request|
704
+ attempts += 1
705
+ if attempts < 2
706
+ { status: 429, body: 'Too Many Requests', headers: {} }
707
+ else
708
+ { status: 200, body: 'success content', headers: {} }
709
+ end
710
+ end
711
+ baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false, timeout: 0.1, pause: 0)
712
+ baza.send(:download, baza.send(:home).append('file'), file)
713
+ assert_equal(2, attempts, 'Expected two HTTP calls due to 429 retries')
714
+ assert_equal('success content', File.read(file))
715
+ end
716
+ end
717
+
718
+ def test_upload_retries_on_busy_server
719
+ WebMock.disable_net_connect!
720
+ Dir.mktmpdir do |dir|
721
+ file = File.join(dir, 'upload.txt')
722
+ File.write(file, 'test content')
723
+ attempts = 0
724
+ stub_request(:put, 'https://example.org:443/file')
725
+ .to_return do |_request|
726
+ attempts += 1
727
+ if attempts < 2
728
+ { status: 429, body: 'Too Many Requests' }
729
+ else
730
+ { status: 200, body: 'OK' }
731
+ end
732
+ end
733
+ baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false, timeout: 0.1, pause: 0)
734
+ baza.send(:upload, baza.send(:home).append('file'), file)
735
+ assert_equal(2, attempts, 'Expected 2 HTTP calls due to 429 retries')
736
+ end
737
+ end
738
+
708
739
  def test_durable_load_from_sinatra
709
740
  WebMock.enable_net_connect!
710
741
  Dir.mktmpdir do |dir|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baza.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.10
4
+ version: 0.9.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko