fbe 0.6.0 → 0.7.1
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 +4 -4
 - data/Gemfile +1 -0
 - data/Gemfile.lock +10 -8
 - data/Rakefile +0 -2
 - data/lib/fbe/conclude.rb +13 -14
 - data/lib/fbe/iterate.rb +12 -8
 - data/lib/fbe/octo.rb +9 -9
 - data/lib/fbe.rb +1 -1
 - data/test/fbe/test_conclude.rb +32 -0
 - data/test/fbe/test_octo.rb +63 -28
 - data/test/test__helper.rb +2 -0
 - metadata +2 -4
 - data/lib/fbe/middleware/quota.rb +0 -64
 - data/test/fbe/middleware/test_quota.rb +0 -66
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: e1ce252b4d0093ff1f94e319d2c65502e134dad520398ca018fad1820b9dac78
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: f0039a70dcd2533e2acd36f80b7ef3ac68441f1f68611b38ee07d9c67449ddf3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 25191aefeccb723456f4de449c6f042ce628c895fc7f2e941f5e63e0685bfb2bccf550e04c288ff28e288acf8a4c0b57f3402b2826cae5ccb5da549c977f1ffe
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 6362777ada12c805d463db462afbfbf5bab5d20b897565b798c2ede567d097f3250622d1a67656731e94f0ac8fc37fb604ace94c150e51e47c2a83ec14f4be60
         
     | 
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -17,5 +17,6 @@ gem 'rubocop-performance', '>0', require: false 
     | 
|
| 
       17 
17 
     | 
    
         
             
            gem 'rubocop-rake', '>0', require: false
         
     | 
| 
       18 
18 
     | 
    
         
             
            gem 'simplecov', '~>0.22', require: false
         
     | 
| 
       19 
19 
     | 
    
         
             
            gem 'simplecov-cobertura', '~>2.1', require: false
         
     | 
| 
      
 20 
     | 
    
         
            +
            gem 'veils', '>0', require: false
         
     | 
| 
       20 
21 
     | 
    
         
             
            gem 'webmock', '~>3.25', require: false
         
     | 
| 
       21 
22 
     | 
    
         
             
            gem 'yard', '~>0.9', require: false
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    | 
         @@ -70,7 +70,7 @@ GEM 
     | 
|
| 
       70 
70 
     | 
    
         
             
                  tago (> 0)
         
     | 
| 
       71 
71 
     | 
    
         
             
                ethon (0.16.0)
         
     | 
| 
       72 
72 
     | 
    
         
             
                  ffi (>= 1.15.0)
         
     | 
| 
       73 
     | 
    
         
            -
                factbase (0. 
     | 
| 
      
 73 
     | 
    
         
            +
                factbase (0.10.0)
         
     | 
| 
       74 
74 
     | 
    
         
             
                  backtrace (~> 0.4)
         
     | 
| 
       75 
75 
     | 
    
         
             
                  decoor (~> 0.0)
         
     | 
| 
       76 
76 
     | 
    
         
             
                  json (~> 2.7)
         
     | 
| 
         @@ -92,14 +92,14 @@ GEM 
     | 
|
| 
       92 
92 
     | 
    
         
             
                  net-http (>= 0.5.0)
         
     | 
| 
       93 
93 
     | 
    
         
             
                faraday-retry (2.3.1)
         
     | 
| 
       94 
94 
     | 
    
         
             
                  faraday (~> 2.0)
         
     | 
| 
       95 
     | 
    
         
            -
                ffi (1.17. 
     | 
| 
       96 
     | 
    
         
            -
                ffi (1.17. 
     | 
| 
       97 
     | 
    
         
            -
                ffi (1.17. 
     | 
| 
       98 
     | 
    
         
            -
                ffi (1.17. 
     | 
| 
       99 
     | 
    
         
            -
                fiber-storage (1.0. 
     | 
| 
      
 95 
     | 
    
         
            +
                ffi (1.17.2-arm64-darwin)
         
     | 
| 
      
 96 
     | 
    
         
            +
                ffi (1.17.2-x64-mingw-ucrt)
         
     | 
| 
      
 97 
     | 
    
         
            +
                ffi (1.17.2-x86_64-darwin)
         
     | 
| 
      
 98 
     | 
    
         
            +
                ffi (1.17.2-x86_64-linux-gnu)
         
     | 
| 
      
 99 
     | 
    
         
            +
                fiber-storage (1.0.1)
         
     | 
| 
       100 
100 
     | 
    
         
             
                gli (2.22.2)
         
     | 
| 
       101 
101 
     | 
    
         
             
                  ostruct
         
     | 
| 
       102 
     | 
    
         
            -
                graphql (2.5. 
     | 
| 
      
 102 
     | 
    
         
            +
                graphql (2.5.3)
         
     | 
| 
       103 
103 
     | 
    
         
             
                  base64
         
     | 
| 
       104 
104 
     | 
    
         
             
                  fiber-storage
         
     | 
| 
       105 
105 
     | 
    
         
             
                  logger
         
     | 
| 
         @@ -158,7 +158,7 @@ GEM 
     | 
|
| 
       158 
158 
     | 
    
         
             
                os (1.1.4)
         
     | 
| 
       159 
159 
     | 
    
         
             
                ostruct (0.6.1)
         
     | 
| 
       160 
160 
     | 
    
         
             
                others (0.0.3)
         
     | 
| 
       161 
     | 
    
         
            -
                parallel (1. 
     | 
| 
      
 161 
     | 
    
         
            +
                parallel (1.27.0)
         
     | 
| 
       162 
162 
     | 
    
         
             
                parser (3.3.8.0)
         
     | 
| 
       163 
163 
     | 
    
         
             
                  ast (~> 2.4.1)
         
     | 
| 
       164 
164 
     | 
    
         
             
                  racc
         
     | 
| 
         @@ -225,6 +225,7 @@ GEM 
     | 
|
| 
       225 
225 
     | 
    
         
             
                  unicode-emoji (~> 4.0, >= 4.0.4)
         
     | 
| 
       226 
226 
     | 
    
         
             
                unicode-emoji (4.0.4)
         
     | 
| 
       227 
227 
     | 
    
         
             
                uri (1.0.3)
         
     | 
| 
      
 228 
     | 
    
         
            +
                veils (0.4.0)
         
     | 
| 
       228 
229 
     | 
    
         
             
                verbose (0.0.2)
         
     | 
| 
       229 
230 
     | 
    
         
             
                  loog (~> 0.2)
         
     | 
| 
       230 
231 
     | 
    
         
             
                  tago (~> 0.0)
         
     | 
| 
         @@ -257,6 +258,7 @@ DEPENDENCIES 
     | 
|
| 
       257 
258 
     | 
    
         
             
              rubocop-rake (> 0)
         
     | 
| 
       258 
259 
     | 
    
         
             
              simplecov (~> 0.22)
         
     | 
| 
       259 
260 
     | 
    
         
             
              simplecov-cobertura (~> 2.1)
         
     | 
| 
      
 261 
     | 
    
         
            +
              veils (> 0)
         
     | 
| 
       260 
262 
     | 
    
         
             
              webmock (~> 3.25)
         
     | 
| 
       261 
263 
     | 
    
         
             
              yard (~> 0.9)
         
     | 
| 
       262 
264 
     | 
    
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/fbe/conclude.rb
    CHANGED
    
    | 
         @@ -160,21 +160,20 @@ class Fbe::Conclude 
     | 
|
| 
       160 
160 
     | 
    
         
             
              def roll(&)
         
     | 
| 
       161 
161 
     | 
    
         
             
                passed = 0
         
     | 
| 
       162 
162 
     | 
    
         
             
                start = Time.now
         
     | 
| 
       163 
     | 
    
         
            -
                 
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
             
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
             
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                      end
         
     | 
| 
       170 
     | 
    
         
            -
                      if Time.now > start + @timeout
         
     | 
| 
       171 
     | 
    
         
            -
                        @loog.debug("We've spent more than #{start.ago}, must stop here")
         
     | 
| 
       172 
     | 
    
         
            -
                        throw :stop
         
     | 
| 
       173 
     | 
    
         
            -
                      end
         
     | 
| 
       174 
     | 
    
         
            -
                      n = yield fbt, a
         
     | 
| 
       175 
     | 
    
         
            -
                      @loog.info("#{n.what}: #{n.details}") unless n.nil?
         
     | 
| 
       176 
     | 
    
         
            -
                      passed += 1
         
     | 
| 
      
 163 
     | 
    
         
            +
                oct = Fbe.octo(loog: @loog, options: @options, global: @global)
         
     | 
| 
      
 164 
     | 
    
         
            +
                @fb.txn do |fbt|
         
     | 
| 
      
 165 
     | 
    
         
            +
                  fbt.query(@query).each do |a|
         
     | 
| 
      
 166 
     | 
    
         
            +
                    if @quota_aware && oct.off_quota
         
     | 
| 
      
 167 
     | 
    
         
            +
                      @loog.debug('We ran out of GitHub quota, must stop here')
         
     | 
| 
      
 168 
     | 
    
         
            +
                      throw :commit
         
     | 
| 
       177 
169 
     | 
    
         
             
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
                    if Time.now > start + @timeout
         
     | 
| 
      
 171 
     | 
    
         
            +
                      @loog.debug("We've spent more than #{start.ago}, must stop here")
         
     | 
| 
      
 172 
     | 
    
         
            +
                      throw :commit
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
                    n = yield fbt, a
         
     | 
| 
      
 175 
     | 
    
         
            +
                    @loog.info("#{n.what}: #{n.details}") unless n.nil?
         
     | 
| 
      
 176 
     | 
    
         
            +
                    passed += 1
         
     | 
| 
       178 
177 
     | 
    
         
             
                  end
         
     | 
| 
       179 
178 
     | 
    
         
             
                end
         
     | 
| 
       180 
179 
     | 
    
         
             
                @loog.debug("Found and processed #{passed} facts by: #{@query}")
         
     | 
    
        data/lib/fbe/iterate.rb
    CHANGED
    
    | 
         @@ -107,11 +107,23 @@ class Fbe::Iterate 
     | 
|
| 
       107 
107 
     | 
    
         
             
                raise 'Use "by" first' if @query.nil?
         
     | 
| 
       108 
108 
     | 
    
         
             
                seen = {}
         
     | 
| 
       109 
109 
     | 
    
         
             
                oct = Fbe.octo(loog: @loog, options: @options, global: @global)
         
     | 
| 
      
 110 
     | 
    
         
            +
                if oct.off_quota
         
     | 
| 
      
 111 
     | 
    
         
            +
                  @loog.debug('We are off GitHub quota, cannot even start, sorry')
         
     | 
| 
      
 112 
     | 
    
         
            +
                  return
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
       110 
114 
     | 
    
         
             
                repos = Fbe.unmask_repos(loog: @loog, options: @options, global: @global)
         
     | 
| 
       111 
115 
     | 
    
         
             
                restarted = []
         
     | 
| 
       112 
116 
     | 
    
         
             
                start = Time.now
         
     | 
| 
       113 
117 
     | 
    
         
             
                loop do
         
     | 
| 
      
 118 
     | 
    
         
            +
                  if oct.off_quota
         
     | 
| 
      
 119 
     | 
    
         
            +
                    @loog.info("We are off GitHub quota, time to stop after #{start.ago}")
         
     | 
| 
      
 120 
     | 
    
         
            +
                    break
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
       114 
122 
     | 
    
         
             
                  repos.each do |repo|
         
     | 
| 
      
 123 
     | 
    
         
            +
                    if oct.off_quota
         
     | 
| 
      
 124 
     | 
    
         
            +
                      @loog.debug("We are off GitHub quota, we must skip #{repo}")
         
     | 
| 
      
 125 
     | 
    
         
            +
                      break
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
       115 
127 
     | 
    
         
             
                    if Time.now - start > timeout
         
     | 
| 
       116 
128 
     | 
    
         
             
                      $loog.info("We are doing this for #{start.ago} already, won't check #{repo}")
         
     | 
| 
       117 
129 
     | 
    
         
             
                      next
         
     | 
| 
         @@ -152,14 +164,6 @@ class Fbe::Iterate 
     | 
|
| 
       152 
164 
     | 
    
         
             
                      end
         
     | 
| 
       153 
165 
     | 
    
         
             
                    f.what = @label
         
     | 
| 
       154 
166 
     | 
    
         
             
                    seen[repo] += 1
         
     | 
| 
       155 
     | 
    
         
            -
                    if oct.off_quota
         
     | 
| 
       156 
     | 
    
         
            -
                      @loog.debug('We are off GitHub quota, time to stop')
         
     | 
| 
       157 
     | 
    
         
            -
                      break
         
     | 
| 
       158 
     | 
    
         
            -
                    end
         
     | 
| 
       159 
     | 
    
         
            -
                  end
         
     | 
| 
       160 
     | 
    
         
            -
                  if oct.off_quota
         
     | 
| 
       161 
     | 
    
         
            -
                    @loog.info("We are off GitHub quota, time to stop after #{start.ago}")
         
     | 
| 
       162 
     | 
    
         
            -
                    break
         
     | 
| 
       163 
167 
     | 
    
         
             
                  end
         
     | 
| 
       164 
168 
     | 
    
         
             
                  unless seen.any? { |r, v| v < @repeats && !restarted.include?(r) }
         
     | 
| 
       165 
169 
     | 
    
         
             
                    @loog.debug("No more repos to scan (out of #{repos.size}), quitting after #{start.ago}")
         
     | 
    
        data/lib/fbe/octo.rb
    CHANGED
    
    | 
         @@ -13,7 +13,6 @@ require 'verbose' 
     | 
|
| 
       13 
13 
     | 
    
         
             
            require_relative '../fbe'
         
     | 
| 
       14 
14 
     | 
    
         
             
            require_relative 'middleware'
         
     | 
| 
       15 
15 
     | 
    
         
             
            require_relative 'middleware/formatter'
         
     | 
| 
       16 
     | 
    
         
            -
            require_relative 'middleware/quota'
         
     | 
| 
       17 
16 
     | 
    
         | 
| 
       18 
17 
     | 
    
         
             
            # Makes a call to the GitHub API.
         
     | 
| 
       19 
18 
     | 
    
         
             
            #
         
     | 
| 
         @@ -71,7 +70,6 @@ def Fbe.octo(options: $options, global: $global, loog: $loog) 
     | 
|
| 
       71 
70 
     | 
    
         
             
                          methods: [:get],
         
     | 
| 
       72 
71 
     | 
    
         
             
                          backoff_factor: 2
         
     | 
| 
       73 
72 
     | 
    
         
             
                        )
         
     | 
| 
       74 
     | 
    
         
            -
                        builder.use(Fbe::Middleware::Quota, loog:, pause: options.github_api_pause || 60)
         
     | 
| 
       75 
73 
     | 
    
         
             
                        builder.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false, logger: Loog::NULL)
         
     | 
| 
       76 
74 
     | 
    
         
             
                        builder.use(Octokit::Response::RaiseError)
         
     | 
| 
       77 
75 
     | 
    
         
             
                        builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
         
     | 
| 
         @@ -84,12 +82,13 @@ def Fbe.octo(options: $options, global: $global, loog: $loog) 
     | 
|
| 
       84 
82 
     | 
    
         
             
                    o = Fbe::FakeOctokit.new
         
     | 
| 
       85 
83 
     | 
    
         
             
                  end
         
     | 
| 
       86 
84 
     | 
    
         
             
                  decoor(o, loog:) do
         
     | 
| 
       87 
     | 
    
         
            -
                    def off_quota
         
     | 
| 
      
 85 
     | 
    
         
            +
                    def off_quota(threshold: 50)
         
     | 
| 
       88 
86 
     | 
    
         
             
                      left = @origin.rate_limit.remaining
         
     | 
| 
       89 
     | 
    
         
            -
                      if left <  
     | 
| 
       90 
     | 
    
         
            -
                        @loog.info("Too much GitHub API quota consumed already ( 
     | 
| 
      
 87 
     | 
    
         
            +
                      if left < threshold
         
     | 
| 
      
 88 
     | 
    
         
            +
                        @loog.info("Too much GitHub API quota consumed already (#{left} < #{threshold}), stopping")
         
     | 
| 
       91 
89 
     | 
    
         
             
                        true
         
     | 
| 
       92 
90 
     | 
    
         
             
                      else
         
     | 
| 
      
 91 
     | 
    
         
            +
                        @loog.debug("Still #{left} GitHub API quota left (>#{threshold})")
         
     | 
| 
       93 
92 
     | 
    
         
             
                        false
         
     | 
| 
       94 
93 
     | 
    
         
             
                      end
         
     | 
| 
       95 
94 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -149,13 +148,14 @@ class Fbe::FakeOctokit 
     | 
|
| 
       149 
148 
     | 
    
         
             
                true
         
     | 
| 
       150 
149 
     | 
    
         
             
              end
         
     | 
| 
       151 
150 
     | 
    
         | 
| 
       152 
     | 
    
         
            -
               
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
      
 151 
     | 
    
         
            +
              # Get details of the user.
         
     | 
| 
      
 152 
     | 
    
         
            +
              # @param [String|Integer] uid The login of the user or its ID
         
     | 
| 
      
 153 
     | 
    
         
            +
              def user(uid)
         
     | 
| 
      
 154 
     | 
    
         
            +
                login = (uid == 526_301 ? 'yegor256' : 'torvalds') if uid.is_a?(Integer)
         
     | 
| 
       155 
155 
     | 
    
         
             
                {
         
     | 
| 
       156 
156 
     | 
    
         
             
                  id: 444,
         
     | 
| 
       157 
157 
     | 
    
         
             
                  login:,
         
     | 
| 
       158 
     | 
    
         
            -
                  type:  
     | 
| 
      
 158 
     | 
    
         
            +
                  type: uid == 29_139_614 ? 'Bot' : 'User'
         
     | 
| 
       159 
159 
     | 
    
         
             
                }
         
     | 
| 
       160 
160 
     | 
    
         
             
              end
         
     | 
| 
       161 
161 
     | 
    
         | 
    
        data/lib/fbe.rb
    CHANGED
    
    
    
        data/test/fbe/test_conclude.rb
    CHANGED
    
    | 
         @@ -61,6 +61,38 @@ class TestConclude < Fbe::Test 
     | 
|
| 
       61 
61 
     | 
    
         
             
                assert_equal(42, f.bar)
         
     | 
| 
       62 
62 
     | 
    
         
             
              end
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
      
 64 
     | 
    
         
            +
              def test_considers_until_quota
         
     | 
| 
      
 65 
     | 
    
         
            +
                WebMock.disable_net_connect!
         
     | 
| 
      
 66 
     | 
    
         
            +
                fb = Factbase.new
         
     | 
| 
      
 67 
     | 
    
         
            +
                5.times do
         
     | 
| 
      
 68 
     | 
    
         
            +
                  fb.insert.foo = 1
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
                options = Judges::Options.new
         
     | 
| 
      
 71 
     | 
    
         
            +
                stub_request(:get, %r{https://api.github.com/users/.*}).to_return(
         
     | 
| 
      
 72 
     | 
    
         
            +
                  {
         
     | 
| 
      
 73 
     | 
    
         
            +
                    body: { id: rand(100) }.to_json,
         
     | 
| 
      
 74 
     | 
    
         
            +
                    headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '999' }
         
     | 
| 
      
 75 
     | 
    
         
            +
                  },
         
     | 
| 
      
 76 
     | 
    
         
            +
                  {
         
     | 
| 
      
 77 
     | 
    
         
            +
                    body: { id: rand(100) }.to_json,
         
     | 
| 
      
 78 
     | 
    
         
            +
                    headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '9' }
         
     | 
| 
      
 79 
     | 
    
         
            +
                  }
         
     | 
| 
      
 80 
     | 
    
         
            +
                )
         
     | 
| 
      
 81 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/rate_limit').to_return(
         
     | 
| 
      
 82 
     | 
    
         
            +
                  body: 'hm...', headers: { 'X-RateLimit-Remaining' => '777' }
         
     | 
| 
      
 83 
     | 
    
         
            +
                ).times(1)
         
     | 
| 
      
 84 
     | 
    
         
            +
                global = {}
         
     | 
| 
      
 85 
     | 
    
         
            +
                o = Fbe.octo(loog: Loog::NULL, options:, global:)
         
     | 
| 
      
 86 
     | 
    
         
            +
                Fbe.conclude(fb:, judge: 'boom', loog: Loog::NULL, options:, global:) do
         
     | 
| 
      
 87 
     | 
    
         
            +
                  quota_aware
         
     | 
| 
      
 88 
     | 
    
         
            +
                  on '(exists foo)'
         
     | 
| 
      
 89 
     | 
    
         
            +
                  consider do |f|
         
     | 
| 
      
 90 
     | 
    
         
            +
                    f.bar = o.user("user-#{rand(100)}")[:id]
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
                assert_equal(2, fb.query('(exists bar)').each.to_a.size)
         
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
       64 
96 
     | 
    
         
             
              def test_ignores_globals
         
     | 
| 
       65 
97 
     | 
    
         
             
                $fb = nil
         
     | 
| 
       66 
98 
     | 
    
         
             
                $loog = nil
         
     | 
    
        data/test/fbe/test_octo.rb
    CHANGED
    
    | 
         @@ -56,7 +56,7 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       56 
56 
     | 
    
         
             
                global = {}
         
     | 
| 
       57 
57 
     | 
    
         
             
                o = Fbe.octo(loog: Loog::NULL, global:, options: Judges::Options.new)
         
     | 
| 
       58 
58 
     | 
    
         
             
                stub_request(:get, 'https://api.github.com/users/yegor256')
         
     | 
| 
       59 
     | 
    
         
            -
                  .to_return( 
     | 
| 
      
 59 
     | 
    
         
            +
                  .to_return(body: '{}', headers: { 'Cache-Control' => 'public, max-age=60', 'etag' => 'abc' })
         
     | 
| 
       60 
60 
     | 
    
         
             
                  .times(1)
         
     | 
| 
       61 
61 
     | 
    
         
             
                  .then
         
     | 
| 
       62 
62 
     | 
    
         
             
                  .to_raise('second request should be cached, not passed to GitHub API!')
         
     | 
| 
         @@ -64,12 +64,50 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       64 
64 
     | 
    
         
             
                o.user('yegor256')
         
     | 
| 
       65 
65 
     | 
    
         
             
              end
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
      
 67 
     | 
    
         
            +
              def test_rate_limit_remaining
         
     | 
| 
      
 68 
     | 
    
         
            +
                WebMock.disable_net_connect!
         
     | 
| 
      
 69 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/rate_limit').to_return(
         
     | 
| 
      
 70 
     | 
    
         
            +
                  { body: '{}', headers: { 'X-RateLimit-Remaining' => '222' } }
         
     | 
| 
      
 71 
     | 
    
         
            +
                )
         
     | 
| 
      
 72 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/user/42').to_return(
         
     | 
| 
      
 73 
     | 
    
         
            +
                  body: '', headers: { 'X-RateLimit-Remaining' => '4' }
         
     | 
| 
      
 74 
     | 
    
         
            +
                )
         
     | 
| 
      
 75 
     | 
    
         
            +
                o = Octokit::Client.new
         
     | 
| 
      
 76 
     | 
    
         
            +
                assert_equal(222, o.rate_limit.remaining)
         
     | 
| 
      
 77 
     | 
    
         
            +
                o.user(42)
         
     | 
| 
      
 78 
     | 
    
         
            +
                assert_equal(4, o.rate_limit.remaining)
         
     | 
| 
      
 79 
     | 
    
         
            +
                assert_equal(4, o.rate_limit.remaining)
         
     | 
| 
      
 80 
     | 
    
         
            +
              end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       67 
82 
     | 
    
         
             
              def test_off_quota
         
     | 
| 
       68 
83 
     | 
    
         
             
                WebMock.disable_net_connect!
         
     | 
| 
       69 
     | 
    
         
            -
                stub_request(:get, 'https://api.github.com/rate_limit')
         
     | 
| 
       70 
     | 
    
         
            -
                   
     | 
| 
      
 84 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/rate_limit').to_return(
         
     | 
| 
      
 85 
     | 
    
         
            +
                  body: '{}', headers: { 'X-RateLimit-Remaining' => '333' }
         
     | 
| 
      
 86 
     | 
    
         
            +
                )
         
     | 
| 
      
 87 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/user/42').to_return(
         
     | 
| 
      
 88 
     | 
    
         
            +
                  body: '', headers: { 'X-RateLimit-Remaining' => '3' }
         
     | 
| 
      
 89 
     | 
    
         
            +
                )
         
     | 
| 
       71 
90 
     | 
    
         
             
                o = Fbe.octo(loog: Loog::NULL, global: {}, options: Judges::Options.new)
         
     | 
| 
       72 
91 
     | 
    
         
             
                refute(o.off_quota)
         
     | 
| 
      
 92 
     | 
    
         
            +
                o.user(42)
         
     | 
| 
      
 93 
     | 
    
         
            +
                assert(o.off_quota)
         
     | 
| 
      
 94 
     | 
    
         
            +
              end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
              def test_off_quota_twice
         
     | 
| 
      
 97 
     | 
    
         
            +
                WebMock.disable_net_connect!
         
     | 
| 
      
 98 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/rate_limit').to_return(
         
     | 
| 
      
 99 
     | 
    
         
            +
                  body: '{}', headers: { 'X-RateLimit-Remaining' => '333' }
         
     | 
| 
      
 100 
     | 
    
         
            +
                )
         
     | 
| 
      
 101 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/user/42').to_return(
         
     | 
| 
      
 102 
     | 
    
         
            +
                  { body: '', headers: { 'X-RateLimit-Remaining' => '5555' } },
         
     | 
| 
      
 103 
     | 
    
         
            +
                  { body: '', headers: { 'X-RateLimit-Remaining' => '5' } }
         
     | 
| 
      
 104 
     | 
    
         
            +
                )
         
     | 
| 
      
 105 
     | 
    
         
            +
                o = Fbe.octo(loog: Loog::VERBOSE, global: {}, options: Judges::Options.new)
         
     | 
| 
      
 106 
     | 
    
         
            +
                refute(o.off_quota)
         
     | 
| 
      
 107 
     | 
    
         
            +
                o.user(42)
         
     | 
| 
      
 108 
     | 
    
         
            +
                refute(o.off_quota)
         
     | 
| 
      
 109 
     | 
    
         
            +
                o.user(42)
         
     | 
| 
      
 110 
     | 
    
         
            +
                assert(o.off_quota)
         
     | 
| 
       73 
111 
     | 
    
         
             
              end
         
     | 
| 
       74 
112 
     | 
    
         | 
| 
       75 
113 
     | 
    
         
             
              def test_retrying
         
     | 
| 
         @@ -80,7 +118,7 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       80 
118 
     | 
    
         
             
                  .to_raise(Octokit::TooManyRequests.new)
         
     | 
| 
       81 
119 
     | 
    
         
             
                  .times(1)
         
     | 
| 
       82 
120 
     | 
    
         
             
                  .then
         
     | 
| 
       83 
     | 
    
         
            -
                  .to_return( 
     | 
| 
      
 121 
     | 
    
         
            +
                  .to_return(body: '{}')
         
     | 
| 
       84 
122 
     | 
    
         
             
                o.user('yegor256')
         
     | 
| 
       85 
123 
     | 
    
         
             
              end
         
     | 
| 
       86 
124 
     | 
    
         | 
| 
         @@ -92,7 +130,7 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       92 
130 
     | 
    
         
             
                  .to_return(status: 503)
         
     | 
| 
       93 
131 
     | 
    
         
             
                  .times(1)
         
     | 
| 
       94 
132 
     | 
    
         
             
                  .then
         
     | 
| 
       95 
     | 
    
         
            -
                  .to_return( 
     | 
| 
      
 133 
     | 
    
         
            +
                  .to_return(body: '{}')
         
     | 
| 
       96 
134 
     | 
    
         
             
                o.user('yegor256')
         
     | 
| 
       97 
135 
     | 
    
         
             
              end
         
     | 
| 
       98 
136 
     | 
    
         | 
| 
         @@ -133,29 +171,20 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       133 
171 
     | 
    
         | 
| 
       134 
172 
     | 
    
         
             
              def test_pauses_when_quota_is_exceeded
         
     | 
| 
       135 
173 
     | 
    
         
             
                WebMock.disable_net_connect!
         
     | 
| 
       136 
     | 
    
         
            -
                 
     | 
| 
       137 
     | 
    
         
            -
                 
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                   
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
                   
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
                        'x-ratelimit-remaining' => limit.to_s
         
     | 
| 
       151 
     | 
    
         
            -
                      }
         
     | 
| 
       152 
     | 
    
         
            -
                    )
         
     | 
| 
       153 
     | 
    
         
            -
                    .times(1)
         
     | 
| 
       154 
     | 
    
         
            -
                  o.user(user)
         
     | 
| 
       155 
     | 
    
         
            -
                  refute(o.off_quota) if n > 100
         
     | 
| 
       156 
     | 
    
         
            -
                  limit -= 1
         
     | 
| 
       157 
     | 
    
         
            -
                end
         
     | 
| 
       158 
     | 
    
         
            -
                assert_in_delta(pause, Time.now - start_time, 5)
         
     | 
| 
      
 174 
     | 
    
         
            +
                o = Fbe.octo(loog: Loog::NULL, global: {}, options: Judges::Options.new({ 'github_api_pause' => 0.01 }))
         
     | 
| 
      
 175 
     | 
    
         
            +
                stub_request(:get, 'https://api.github.com/users/foo')
         
     | 
| 
      
 176 
     | 
    
         
            +
                  .to_return(
         
     | 
| 
      
 177 
     | 
    
         
            +
                    body: '{}',
         
     | 
| 
      
 178 
     | 
    
         
            +
                    headers: { 'x-ratelimit-remaining' => '1' }
         
     | 
| 
      
 179 
     | 
    
         
            +
                  )
         
     | 
| 
      
 180 
     | 
    
         
            +
                  .to_return(
         
     | 
| 
      
 181 
     | 
    
         
            +
                    body: '{}',
         
     | 
| 
      
 182 
     | 
    
         
            +
                    headers: { 'x-ratelimit-remaining' => '10000' }
         
     | 
| 
      
 183 
     | 
    
         
            +
                  )
         
     | 
| 
      
 184 
     | 
    
         
            +
                o.user('foo')
         
     | 
| 
      
 185 
     | 
    
         
            +
                assert(o.off_quota)
         
     | 
| 
      
 186 
     | 
    
         
            +
                o.user('foo')
         
     | 
| 
      
 187 
     | 
    
         
            +
                refute(o.off_quota)
         
     | 
| 
       159 
188 
     | 
    
         
             
              end
         
     | 
| 
       160 
189 
     | 
    
         | 
| 
       161 
190 
     | 
    
         
             
              def test_fetches_fake_check_runs_for_ref
         
     | 
| 
         @@ -193,4 +222,10 @@ class TestOcto < Fbe::Test 
     | 
|
| 
       193 
222 
     | 
    
         
             
                result = o.workflow_run_job('zerocracy/baza', 0)
         
     | 
| 
       194 
223 
     | 
    
         
             
                assert_equal(0, result[:id])
         
     | 
| 
       195 
224 
     | 
    
         
             
              end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
              def test_reads_quota
         
     | 
| 
      
 227 
     | 
    
         
            +
                WebMock.enable_net_connect!
         
     | 
| 
      
 228 
     | 
    
         
            +
                o = Fbe.octo(loog: Loog::VERBOSE, global: {}, options: Judges::Options.new({ 'github_api_pause' => 0.01 }))
         
     | 
| 
      
 229 
     | 
    
         
            +
                refute_nil(o.off_quota)
         
     | 
| 
      
 230 
     | 
    
         
            +
              end
         
     | 
| 
       196 
231 
     | 
    
         
             
            end
         
     | 
    
        data/test/test__helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,13 +1,13 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: fbe
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.7.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Yegor Bugayenko
         
     | 
| 
       8 
8 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       9 
9 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       10 
     | 
    
         
            -
            date: 2025-04- 
     | 
| 
      
 10 
     | 
    
         
            +
            date: 2025-04-16 00:00:00.000000000 Z
         
     | 
| 
       11 
11 
     | 
    
         
             
            dependencies:
         
     | 
| 
       12 
12 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       13 
13 
     | 
    
         
             
              name: backtrace
         
     | 
| 
         @@ -305,7 +305,6 @@ files: 
     | 
|
| 
       305 
305 
     | 
    
         
             
            - lib/fbe/just_one.rb
         
     | 
| 
       306 
306 
     | 
    
         
             
            - lib/fbe/middleware.rb
         
     | 
| 
       307 
307 
     | 
    
         
             
            - lib/fbe/middleware/formatter.rb
         
     | 
| 
       308 
     | 
    
         
            -
            - lib/fbe/middleware/quota.rb
         
     | 
| 
       309 
308 
     | 
    
         
             
            - lib/fbe/octo.rb
         
     | 
| 
       310 
309 
     | 
    
         
             
            - lib/fbe/overwrite.rb
         
     | 
| 
       311 
310 
     | 
    
         
             
            - lib/fbe/pmp.rb
         
     | 
| 
         @@ -317,7 +316,6 @@ files: 
     | 
|
| 
       317 
316 
     | 
    
         
             
            - renovate.json
         
     | 
| 
       318 
317 
     | 
    
         
             
            - rules/basic.fe
         
     | 
| 
       319 
318 
     | 
    
         
             
            - test/fbe/middleware/test_formatter.rb
         
     | 
| 
       320 
     | 
    
         
            -
            - test/fbe/middleware/test_quota.rb
         
     | 
| 
       321 
319 
     | 
    
         
             
            - test/fbe/test_award.rb
         
     | 
| 
       322 
320 
     | 
    
         
             
            - test/fbe/test_bylaws.rb
         
     | 
| 
       323 
321 
     | 
    
         
             
            - test/fbe/test_conclude.rb
         
     | 
    
        data/lib/fbe/middleware/quota.rb
    DELETED
    
    | 
         @@ -1,64 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
         
     | 
| 
       4 
     | 
    
         
            -
            # SPDX-License-Identifier: MIT
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            require 'faraday'
         
     | 
| 
       7 
     | 
    
         
            -
            require_relative '../middleware'
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            # Faraday Middleware that monitors GitHub API rate limits.
         
     | 
| 
       10 
     | 
    
         
            -
            #
         
     | 
| 
       11 
     | 
    
         
            -
            # Author:: Yegor Bugayenko (yegor256@gmail.com)
         
     | 
| 
       12 
     | 
    
         
            -
            # Copyright:: Copyright (c) 2024-2025 Zerocracy
         
     | 
| 
       13 
     | 
    
         
            -
            # License:: MIT
         
     | 
| 
       14 
     | 
    
         
            -
            class Fbe::Middleware::Quota < Faraday::Middleware
         
     | 
| 
       15 
     | 
    
         
            -
              # Constructor.
         
     | 
| 
       16 
     | 
    
         
            -
              #
         
     | 
| 
       17 
     | 
    
         
            -
              # @param [Object] app The Faraday app
         
     | 
| 
       18 
     | 
    
         
            -
              # @param [Loog] loog The logging facility
         
     | 
| 
       19 
     | 
    
         
            -
              # @param [Integer] pause Seconds to pause when rate limit is reached
         
     | 
| 
       20 
     | 
    
         
            -
              # @param [Integer] limit Maximum number of requests before checking rate limit
         
     | 
| 
       21 
     | 
    
         
            -
              # @param [Integer] rate Minimum remaining requests threshold
         
     | 
| 
       22 
     | 
    
         
            -
              def initialize(app, loog: Loog::NULL, pause: 60, limit: 100, rate: 5)
         
     | 
| 
       23 
     | 
    
         
            -
                super(app)
         
     | 
| 
       24 
     | 
    
         
            -
                @requests = 0
         
     | 
| 
       25 
     | 
    
         
            -
                @app = app
         
     | 
| 
       26 
     | 
    
         
            -
                raise 'The "loog" cannot be nil' if loog.nil?
         
     | 
| 
       27 
     | 
    
         
            -
                @loog = loog
         
     | 
| 
       28 
     | 
    
         
            -
                raise 'The "pause" cannot be nil' if pause.nil?
         
     | 
| 
       29 
     | 
    
         
            -
                raise 'The "pause" must be a positive integer' unless pause.positive?
         
     | 
| 
       30 
     | 
    
         
            -
                @pause = pause
         
     | 
| 
       31 
     | 
    
         
            -
                raise 'The "limit" cannot be nil' if limit.nil?
         
     | 
| 
       32 
     | 
    
         
            -
                raise 'The "limit" must be a positive integer' unless limit.positive?
         
     | 
| 
       33 
     | 
    
         
            -
                @limit = limit
         
     | 
| 
       34 
     | 
    
         
            -
                raise 'The "rate" cannot be nil' if rate.nil?
         
     | 
| 
       35 
     | 
    
         
            -
                raise 'The "rate" must be a positive integer' unless rate.positive?
         
     | 
| 
       36 
     | 
    
         
            -
                @rate = rate
         
     | 
| 
       37 
     | 
    
         
            -
              end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
              # Process the request and handle rate limiting.
         
     | 
| 
       40 
     | 
    
         
            -
              #
         
     | 
| 
       41 
     | 
    
         
            -
              # @param [Faraday::Env] env The environment
         
     | 
| 
       42 
     | 
    
         
            -
              # @return [Faraday::Response] The response
         
     | 
| 
       43 
     | 
    
         
            -
              def call(env)
         
     | 
| 
       44 
     | 
    
         
            -
                @requests += 1
         
     | 
| 
       45 
     | 
    
         
            -
                response = @app.call(env)
         
     | 
| 
       46 
     | 
    
         
            -
                if out_of_limit?(env)
         
     | 
| 
       47 
     | 
    
         
            -
                  @loog.info("Too much GitHub API quota consumed, pausing for #{@pause} seconds")
         
     | 
| 
       48 
     | 
    
         
            -
                  sleep(@pause)
         
     | 
| 
       49 
     | 
    
         
            -
                  @requests = 0
         
     | 
| 
       50 
     | 
    
         
            -
                end
         
     | 
| 
       51 
     | 
    
         
            -
                response
         
     | 
| 
       52 
     | 
    
         
            -
              end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              private
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
              # Check if we're approaching the rate limit.
         
     | 
| 
       57 
     | 
    
         
            -
              #
         
     | 
| 
       58 
     | 
    
         
            -
              # @param [Faraday::Env] env The environment
         
     | 
| 
       59 
     | 
    
         
            -
              # @return [Boolean] True if we should pause to avoid hitting rate limits
         
     | 
| 
       60 
     | 
    
         
            -
              def out_of_limit?(env)
         
     | 
| 
       61 
     | 
    
         
            -
                remaining = env.response_headers['x-ratelimit-remaining'].to_i
         
     | 
| 
       62 
     | 
    
         
            -
                (@requests % @limit).zero? && remaining < @rate
         
     | 
| 
       63 
     | 
    
         
            -
              end
         
     | 
| 
       64 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,66 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
         
     | 
| 
       4 
     | 
    
         
            -
            # SPDX-License-Identifier: MIT
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
            require 'faraday'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'logger'
         
     | 
| 
       8 
     | 
    
         
            -
            require 'loog'
         
     | 
| 
       9 
     | 
    
         
            -
            require 'judges'
         
     | 
| 
       10 
     | 
    
         
            -
            require 'judges/options'
         
     | 
| 
       11 
     | 
    
         
            -
            require_relative '../../../lib/fbe/middleware'
         
     | 
| 
       12 
     | 
    
         
            -
            require_relative '../../../lib/fbe/middleware/quota'
         
     | 
| 
       13 
     | 
    
         
            -
            require_relative '../../test__helper'
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            class QuotaTest < Fbe::Test
         
     | 
| 
       16 
     | 
    
         
            -
              class FakeApp
         
     | 
| 
       17 
     | 
    
         
            -
                def initialize
         
     | 
| 
       18 
     | 
    
         
            -
                  @calls = 0
         
     | 
| 
       19 
     | 
    
         
            -
                end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                def call(env)
         
     | 
| 
       22 
     | 
    
         
            -
                  @calls += 1
         
     | 
| 
       23 
     | 
    
         
            -
                  response_headers = {
         
     | 
| 
       24 
     | 
    
         
            -
                    'x-ratelimit-remaining' => (100 - @calls).to_s
         
     | 
| 
       25 
     | 
    
         
            -
                  }
         
     | 
| 
       26 
     | 
    
         
            -
                  env[:response_headers] = response_headers
         
     | 
| 
       27 
     | 
    
         
            -
                  env
         
     | 
| 
       28 
     | 
    
         
            -
                end
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
              def test_quota_middleware_pauses_when_quota_low
         
     | 
| 
       32 
     | 
    
         
            -
                loog = Loog::NULL
         
     | 
| 
       33 
     | 
    
         
            -
                pause = 0.1
         
     | 
| 
       34 
     | 
    
         
            -
                app = FakeApp.new
         
     | 
| 
       35 
     | 
    
         
            -
                middleware = Fbe::Middleware::Quota.new(app, loog:, pause:)
         
     | 
| 
       36 
     | 
    
         
            -
                start_time = Time.now
         
     | 
| 
       37 
     | 
    
         
            -
                105.times do
         
     | 
| 
       38 
     | 
    
         
            -
                  env = Judges::Options.new(
         
     | 
| 
       39 
     | 
    
         
            -
                    'method' => :get,
         
     | 
| 
       40 
     | 
    
         
            -
                    'url' => 'http://example.com',
         
     | 
| 
       41 
     | 
    
         
            -
                    'request_headers' => {},
         
     | 
| 
       42 
     | 
    
         
            -
                    'response_headers' => {}
         
     | 
| 
       43 
     | 
    
         
            -
                  )
         
     | 
| 
       44 
     | 
    
         
            -
                  middleware.call(env)
         
     | 
| 
       45 
     | 
    
         
            -
                end
         
     | 
| 
       46 
     | 
    
         
            -
                assert_in_delta pause, Time.now - start_time, 0.4
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
              def test_quota_middleware_logs_when_quota_low
         
     | 
| 
       50 
     | 
    
         
            -
                pause = 0.1
         
     | 
| 
       51 
     | 
    
         
            -
                log_output = StringIO.new
         
     | 
| 
       52 
     | 
    
         
            -
                loog = Logger.new(log_output)
         
     | 
| 
       53 
     | 
    
         
            -
                app = FakeApp.new
         
     | 
| 
       54 
     | 
    
         
            -
                middleware = Fbe::Middleware::Quota.new(app, loog:, pause:)
         
     | 
| 
       55 
     | 
    
         
            -
                105.times do
         
     | 
| 
       56 
     | 
    
         
            -
                  env = Judges::Options.new(
         
     | 
| 
       57 
     | 
    
         
            -
                    'method' => :get,
         
     | 
| 
       58 
     | 
    
         
            -
                    'url' => 'http://example.com',
         
     | 
| 
       59 
     | 
    
         
            -
                    'request_headers' => {},
         
     | 
| 
       60 
     | 
    
         
            -
                    'response_headers' => {}
         
     | 
| 
       61 
     | 
    
         
            -
                  )
         
     | 
| 
       62 
     | 
    
         
            -
                  middleware.call(env)
         
     | 
| 
       63 
     | 
    
         
            -
                end
         
     | 
| 
       64 
     | 
    
         
            -
                assert_match(/Too much GitHub API quota/, log_output.string)
         
     | 
| 
       65 
     | 
    
         
            -
              end
         
     | 
| 
       66 
     | 
    
         
            -
            end
         
     |