fbe 0.23.6 → 0.23.7
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/.github/workflows/typos.yml +1 -1
- data/lib/fbe/middleware/trace.rb +7 -1
- data/lib/fbe/octo.rb +4 -4
- data/lib/fbe.rb +1 -1
- data/test/fbe/middleware/test_trace.rb +62 -0
- data/test/fbe/test_octo.rb +123 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36afd4e19f2a84e050e41ba6395a35cbc1bd404c8f6c1971affd64aa4c9c9e27
|
4
|
+
data.tar.gz: 904a216825c9bb411036db7c2486e492a6a58ca6b77f26b05f39c37cae377867
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3de96beb257378efe098e4ba1406a06dab673c6717ef249fd92bd31b92483f983847af33e6b34d00b707c4bddf2271f8afee4a597802e9c9d80300cd343625c
|
7
|
+
data.tar.gz: ce3036d1e93ca6585bc188724c9e34552ce5bc658c8d15ffe5e74d0cf59682322475941cac47e33c76338da5e07d84a44d4f0b0b407084c7918e26f7421b1a54
|
data/.github/workflows/typos.yml
CHANGED
data/lib/fbe/middleware/trace.rb
CHANGED
@@ -31,9 +31,12 @@ class Fbe::Middleware::Trace < Faraday::Middleware
|
|
31
31
|
#
|
32
32
|
# @param [Object] app The next middleware in the stack
|
33
33
|
# @param [Array] trace The array to store trace entries
|
34
|
-
|
34
|
+
# @param [Array<Symbol>] ignores The array of symbols (see Faraday::HttpCache::CACHE_STATUSES),
|
35
|
+
# which will be ignored
|
36
|
+
def initialize(app, trace, ignores: [])
|
35
37
|
super(app)
|
36
38
|
@trace = trace
|
39
|
+
@ignores = ignores
|
37
40
|
end
|
38
41
|
|
39
42
|
# Processes the HTTP request and records trace information.
|
@@ -47,6 +50,9 @@ class Fbe::Middleware::Trace < Faraday::Middleware
|
|
47
50
|
started_at: Time.now
|
48
51
|
}
|
49
52
|
@app.call(env).on_complete do |response_env|
|
53
|
+
next if !@ignores.empty? &&
|
54
|
+
response_env[:http_cache_trace] &&
|
55
|
+
(response_env[:http_cache_trace] & @ignores).size.positive?
|
50
56
|
finished = Time.now
|
51
57
|
duration = finished - entry[:started_at]
|
52
58
|
entry[:status] = response_env.status
|
data/lib/fbe/octo.rb
CHANGED
@@ -86,6 +86,10 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
|
|
86
86
|
methods: [:get],
|
87
87
|
backoff_factor: 2
|
88
88
|
)
|
89
|
+
builder.use(Octokit::Response::RaiseError)
|
90
|
+
builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
|
91
|
+
builder.use(Fbe::Middleware::RateLimit)
|
92
|
+
builder.use(Fbe::Middleware::Trace, trace, ignores: [:fresh])
|
89
93
|
if options.sqlite_cache
|
90
94
|
maxsize = Filesize.from(options.sqlite_cache_maxsize || '10M').to_i
|
91
95
|
maxvsize = Filesize.from(options.sqlite_cache_maxvsize || '10K').to_i
|
@@ -106,10 +110,6 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
|
|
106
110
|
serializer: Marshal, shared_cache: false, logger: Loog::NULL
|
107
111
|
)
|
108
112
|
end
|
109
|
-
builder.use(Octokit::Response::RaiseError)
|
110
|
-
builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
|
111
|
-
builder.use(Fbe::Middleware::RateLimit)
|
112
|
-
builder.use(Fbe::Middleware::Trace, trace)
|
113
113
|
builder.adapter(Faraday.default_adapter)
|
114
114
|
end
|
115
115
|
o.middleware = stack
|
data/lib/fbe.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
6
|
require 'faraday'
|
7
|
+
require 'faraday/http_cache'
|
7
8
|
require 'webmock'
|
8
9
|
require_relative '../../test__helper'
|
9
10
|
require_relative '../../../lib/fbe'
|
@@ -103,4 +104,65 @@ class TraceTest < Fbe::Test
|
|
103
104
|
assert_includes url, 'q=test'
|
104
105
|
assert_includes url, 'page=2'
|
105
106
|
end
|
107
|
+
|
108
|
+
def test_trace_and_cache_middlewares_together
|
109
|
+
WebMock.disable_net_connect!
|
110
|
+
now = Time.now
|
111
|
+
stub_request(:get, 'https://api.example.com/page')
|
112
|
+
.to_return(
|
113
|
+
status: 200,
|
114
|
+
headers: {
|
115
|
+
'date' => now.httpdate,
|
116
|
+
'cache-control' => 'public, max-age=60, s-maxage=60',
|
117
|
+
'last-modified' => (now - (6 * 60 * 60)).httpdate
|
118
|
+
},
|
119
|
+
body: 'some body 1'
|
120
|
+
)
|
121
|
+
.times(1)
|
122
|
+
.then
|
123
|
+
.to_return(
|
124
|
+
status: 200,
|
125
|
+
headers: {
|
126
|
+
'date' => (now + 70).httpdate,
|
127
|
+
'cache-control' => 'public, max-age=60, s-maxage=60',
|
128
|
+
'last-modified' => (now - (6 * 60 * 60)).httpdate,
|
129
|
+
'content-type' => 'application/json; charset=utf-8'
|
130
|
+
},
|
131
|
+
body: 'some body 2'
|
132
|
+
)
|
133
|
+
.times(1)
|
134
|
+
.then.to_raise('no more request to /page')
|
135
|
+
trace_real = []
|
136
|
+
trace_full = []
|
137
|
+
builder =
|
138
|
+
Faraday::RackBuilder.new do |f|
|
139
|
+
f.use Fbe::Middleware::Trace, trace_full
|
140
|
+
f.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false, logger: Loog::NULL)
|
141
|
+
f.use Fbe::Middleware::Trace, trace_real
|
142
|
+
f.adapter :net_http
|
143
|
+
end
|
144
|
+
conn = Faraday::Connection.new(builder: builder)
|
145
|
+
5.times do
|
146
|
+
r = conn.get('https://api.example.com/page')
|
147
|
+
assert_equal('some body 1', r.body)
|
148
|
+
end
|
149
|
+
assert_equal(1, trace_real.size)
|
150
|
+
assert_equal(5, trace_full.size)
|
151
|
+
trace_real.clear
|
152
|
+
trace_full.clear
|
153
|
+
5.times do
|
154
|
+
r = conn.get('https://api.example.com/page')
|
155
|
+
assert_equal('some body 1', r.body)
|
156
|
+
end
|
157
|
+
assert_equal(0, trace_real.size)
|
158
|
+
assert_equal(5, trace_full.size)
|
159
|
+
Time.stub(:now, now + 70) do
|
160
|
+
5.times do
|
161
|
+
r = conn.get('https://api.example.com/page')
|
162
|
+
assert_equal('some body 2', r.body)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
assert_equal(1, trace_real.size)
|
166
|
+
assert_equal(10, trace_full.size)
|
167
|
+
end
|
106
168
|
end
|
data/test/fbe/test_octo.rb
CHANGED
@@ -421,14 +421,69 @@ class TestOcto < Fbe::Test
|
|
421
421
|
octo = Fbe.octo(loog: Loog::NULL, global: {}, options: Judges::Options.new({ 'sqlite_cache' => fcache }))
|
422
422
|
octo.user(123)
|
423
423
|
loog = Loog::Buffer.new
|
424
|
-
octo = Fbe.octo(loog
|
424
|
+
octo = Fbe.octo(loog:, global: {}, options: Judges::Options.new({ 'sqlite_cache' => fcache }))
|
425
425
|
WebMock.remove_request_stub(stub)
|
426
426
|
octo.user(123)
|
427
|
-
octo.print_trace!
|
428
|
-
|
427
|
+
octo.print_trace!(all: true)
|
428
|
+
refute_match('/user/123: 1', loog.to_s)
|
429
429
|
end
|
430
430
|
end
|
431
431
|
|
432
|
+
def test_octo_not_trace_cached_requests
|
433
|
+
WebMock.disable_net_connect!
|
434
|
+
now = Time.now
|
435
|
+
stub_request(:get, 'https://api.github.com/rate_limit')
|
436
|
+
.to_return(
|
437
|
+
status: 200, headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '5000' },
|
438
|
+
body: { 'rate' => { 'limit' => 5000, 'remaining' => 5000, 'reset' => 1_672_531_200 } }.to_json
|
439
|
+
)
|
440
|
+
stub_request(:get, 'https://api.github.com/repos/zerocracy/baza.rb')
|
441
|
+
.to_return(
|
442
|
+
status: 200,
|
443
|
+
headers: {
|
444
|
+
'date' => now.httpdate,
|
445
|
+
'cache-control' => 'public, max-age=60, s-maxage=60',
|
446
|
+
'last-modified' => (now - (6 * 60 * 60)).httpdate,
|
447
|
+
'content-type' => 'application/json; charset=utf-8'
|
448
|
+
},
|
449
|
+
body: { id: 840_215_648, name: 'baza.rb' }.to_json
|
450
|
+
)
|
451
|
+
.times(1)
|
452
|
+
.then
|
453
|
+
.to_return(
|
454
|
+
status: 200,
|
455
|
+
headers: {
|
456
|
+
'date' => (now + 70).httpdate,
|
457
|
+
'cache-control' => 'public, max-age=60, s-maxage=60',
|
458
|
+
'last-modified' => (now - (6 * 60 * 60)).httpdate,
|
459
|
+
'content-type' => 'application/json; charset=utf-8'
|
460
|
+
},
|
461
|
+
body: { id: 840_215_648, name: 'baza.rb' }.to_json
|
462
|
+
)
|
463
|
+
.times(1)
|
464
|
+
.then.to_raise('no more request to /repos/zerocracy/baza.rb')
|
465
|
+
loog = Loog::Buffer.new
|
466
|
+
o = Fbe.octo(loog:, global: {}, options: Judges::Options.new({}))
|
467
|
+
o.print_trace!(all: true)
|
468
|
+
Time.stub(:now, now) do
|
469
|
+
5.times do
|
470
|
+
o.repo('zerocracy/baza.rb')
|
471
|
+
end
|
472
|
+
end
|
473
|
+
o.print_trace!(all: true)
|
474
|
+
Time.stub(:now, now + 70) do
|
475
|
+
25.times do
|
476
|
+
o.repo('zerocracy/baza.rb')
|
477
|
+
end
|
478
|
+
end
|
479
|
+
o.print_trace!(all: true)
|
480
|
+
assert_requested :get, 'https://api.github.com/repos/zerocracy/baza.rb', times: 2
|
481
|
+
output = loog.to_s
|
482
|
+
assert_match('/repos/zerocracy/baza.rb: 1', output)
|
483
|
+
refute_match('/repos/zerocracy/baza.rb: 5', output)
|
484
|
+
refute_match('/repos/zerocracy/baza.rb: 25', output)
|
485
|
+
end
|
486
|
+
|
432
487
|
def test_trace_gets_cleared_after_print
|
433
488
|
WebMock.disable_net_connect!
|
434
489
|
stub_request(:get, 'https://api.github.com/rate_limit').to_return(
|
@@ -542,4 +597,69 @@ class TestOcto < Fbe::Test
|
|
542
597
|
o.print_trace!(all: true)
|
543
598
|
assert_match(/321 quota left/, loog.to_s)
|
544
599
|
end
|
600
|
+
|
601
|
+
def test_throttling_request_to_rate_limit
|
602
|
+
WebMock.disable_net_connect!
|
603
|
+
stub_request(:get, 'https://api.github.com/rate_limit')
|
604
|
+
.to_return(
|
605
|
+
status: 200, headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '5000' },
|
606
|
+
body: { 'rate' => { 'limit' => 5000, 'remaining' => 5000, 'reset' => 1_672_531_200 } }.to_json
|
607
|
+
)
|
608
|
+
.then.to_return(
|
609
|
+
status: 200, headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '4900' },
|
610
|
+
body: { 'rate' => { 'limit' => 5000, 'remaining' => 4900, 'reset' => 1_672_531_200 } }.to_json
|
611
|
+
)
|
612
|
+
.then.to_return(
|
613
|
+
status: 200, headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '4800' },
|
614
|
+
body: { 'rate' => { 'limit' => 5000, 'remaining' => 4800, 'reset' => 1_672_531_200 } }.to_json
|
615
|
+
)
|
616
|
+
.then.to_raise('no more request to /rate_limit')
|
617
|
+
stub_request(:get, 'https://api.github.com/user/1')
|
618
|
+
.to_return(
|
619
|
+
status: 200, headers: { 'Content-Type' => 'application/json' },
|
620
|
+
body: { 'id' => 1, 'login' => 'user1' }.to_json
|
621
|
+
).times(1)
|
622
|
+
stub_request(:get, 'https://api.github.com/user/111')
|
623
|
+
.to_return(
|
624
|
+
status: 200, headers: { 'Content-Type' => 'application/json' },
|
625
|
+
body: { 'id' => 111, 'login' => 'user111' }.to_json
|
626
|
+
)
|
627
|
+
.times(201)
|
628
|
+
.then.to_raise('no more request to /user/111')
|
629
|
+
loog = Loog::Buffer.new
|
630
|
+
o = Fbe.octo(loog:, global: {}, options: Judges::Options.new({}))
|
631
|
+
o.user(1)
|
632
|
+
o.print_trace!(all: true)
|
633
|
+
201.times do
|
634
|
+
o.user(111)
|
635
|
+
o.rate_limit!.remaining
|
636
|
+
end
|
637
|
+
o.print_trace!(all: true)
|
638
|
+
output = loog.to_s
|
639
|
+
assert_requested :get, 'https://api.github.com/user/1', times: 1
|
640
|
+
assert_requested :get, 'https://api.github.com/user/111', times: 201
|
641
|
+
assert_requested :get, 'https://api.github.com/rate_limit', times: 3
|
642
|
+
assert_match('2 URLs vs 2 requests', output)
|
643
|
+
assert_match('/user/1: 1', output)
|
644
|
+
assert_match('/rate_limit: 1', output)
|
645
|
+
assert_match('2 URLs vs 203 requests', output)
|
646
|
+
assert_match('/user/111: 201', output)
|
647
|
+
assert_match('/rate_limit: 2', output)
|
648
|
+
end
|
649
|
+
|
650
|
+
def test_octo_http_cache_middleware_located_in_end_of_chain
|
651
|
+
WebMock.disable_net_connect!
|
652
|
+
stub_request(:get, 'https://api.github.com/rate_limit')
|
653
|
+
.to_return(
|
654
|
+
status: 200, headers: { 'Content-Type' => 'application/json', 'X-RateLimit-Remaining' => '5000' },
|
655
|
+
body: { 'rate' => { 'limit' => 5000, 'remaining' => 5000, 'reset' => 1_672_531_200 } }.to_json
|
656
|
+
)
|
657
|
+
o = Fbe.octo(loog: fake_loog, global: {}, options: Judges::Options.new({}))
|
658
|
+
assert_equal('Faraday::HttpCache', o.middleware.handlers.last.name, <<~MSG.strip.gsub!(/\s+/, ' '))
|
659
|
+
Faraday::HttpCache middleware must be located in the end of chain middlewares,
|
660
|
+
because the Oktokit client change Faraday::HttpCache position to the last,
|
661
|
+
for more info, see: https://github.com/zerocracy/fbe/issues/230#issuecomment-3020551743 and
|
662
|
+
https://github.com/octokit/octokit.rb/blob/ea3413c3174571e87c83d358fc893cc7613091fa/lib/octokit/connection.rb#L109-L119
|
663
|
+
MSG
|
664
|
+
end
|
545
665
|
end
|