rest-core 3.6.0 → 4.0.0
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/.gitmodules +3 -0
- data/.travis.yml +0 -1
- data/CHANGES.md +28 -0
- data/Gemfile +0 -2
- data/README.md +14 -95
- data/Rakefile +16 -3
- data/example/simple.rb +1 -0
- data/example/use-cases.rb +15 -3
- data/lib/rest-core.rb +38 -75
- data/lib/rest-core/client/universal.rb +3 -1
- data/lib/rest-core/client_oauth1.rb +64 -59
- data/lib/rest-core/event.rb +9 -11
- data/lib/rest-core/middleware/auth_basic.rb +21 -21
- data/lib/rest-core/middleware/bypass.rb +8 -8
- data/lib/rest-core/middleware/cache.rb +94 -90
- data/lib/rest-core/middleware/clash_response.rb +15 -14
- data/lib/rest-core/middleware/common_logger.rb +27 -26
- data/lib/rest-core/middleware/default_headers.rb +8 -8
- data/lib/rest-core/middleware/default_payload.rb +8 -8
- data/lib/rest-core/middleware/default_query.rb +8 -8
- data/lib/rest-core/middleware/default_site.rb +12 -12
- data/lib/rest-core/middleware/defaults.rb +38 -38
- data/lib/rest-core/middleware/error_detector.rb +10 -10
- data/lib/rest-core/middleware/error_detector_http.rb +6 -4
- data/lib/rest-core/middleware/error_handler.rb +14 -14
- data/lib/rest-core/middleware/follow_redirect.rb +28 -27
- data/lib/rest-core/middleware/json_request.rb +13 -11
- data/lib/rest-core/middleware/json_response.rb +29 -28
- data/lib/rest-core/middleware/oauth1_header.rb +84 -83
- data/lib/rest-core/middleware/oauth2_header.rb +27 -25
- data/lib/rest-core/middleware/oauth2_query.rb +15 -15
- data/lib/rest-core/middleware/query_response.rb +14 -14
- data/lib/rest-core/middleware/retry.rb +25 -23
- data/lib/rest-core/middleware/smash_response.rb +15 -14
- data/lib/rest-core/middleware/timeout.rb +18 -19
- data/lib/rest-core/test.rb +1 -18
- data/lib/rest-core/util/clash.rb +38 -37
- data/lib/rest-core/util/config.rb +40 -39
- data/lib/rest-core/util/dalli_extension.rb +11 -10
- data/lib/rest-core/util/hmac.rb +9 -8
- data/lib/rest-core/util/json.rb +55 -54
- data/lib/rest-core/util/parse_link.rb +13 -12
- data/lib/rest-core/util/parse_query.rb +24 -22
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +121 -158
- data/test/test_cache.rb +2 -0
- data/test/test_default_payload.rb +1 -1
- data/test/test_error_handler.rb +5 -4
- data/test/test_timeout.rb +9 -8
- data/test/test_universal.rb +8 -0
- metadata +9 -73
- data/lib/rest-core/builder.rb +0 -162
- data/lib/rest-core/client.rb +0 -277
- data/lib/rest-core/client/simple.rb +0 -2
- data/lib/rest-core/engine.rb +0 -36
- data/lib/rest-core/engine/dry.rb +0 -9
- data/lib/rest-core/engine/http-client.rb +0 -41
- data/lib/rest-core/error.rb +0 -5
- data/lib/rest-core/event_source.rb +0 -137
- data/lib/rest-core/middleware.rb +0 -151
- data/lib/rest-core/promise.rb +0 -249
- data/lib/rest-core/thread_pool.rb +0 -131
- data/lib/rest-core/timer.rb +0 -58
- data/lib/rest-core/util/payload.rb +0 -173
- data/test/test_builder.rb +0 -40
- data/test/test_client.rb +0 -177
- data/test/test_event_source.rb +0 -159
- data/test/test_future.rb +0 -16
- data/test/test_httpclient.rb +0 -118
- data/test/test_payload.rb +0 -204
- data/test/test_promise.rb +0 -146
- data/test/test_simple.rb +0 -38
- data/test/test_thread_pool.rb +0 -10
@@ -1,131 +0,0 @@
|
|
1
|
-
|
2
|
-
# reference implementation: puma
|
3
|
-
# https://github.com/puma/puma/blob/v2.7.1/lib/puma/thread_pool.rb
|
4
|
-
|
5
|
-
require 'thread'
|
6
|
-
require 'rest-core'
|
7
|
-
|
8
|
-
class RestCore::ThreadPool
|
9
|
-
include RestCore
|
10
|
-
|
11
|
-
class Queue
|
12
|
-
def initialize
|
13
|
-
@queue = []
|
14
|
-
@condv = ConditionVariable.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def size
|
18
|
-
@queue.size
|
19
|
-
end
|
20
|
-
|
21
|
-
def << task
|
22
|
-
queue << task
|
23
|
-
condv.signal
|
24
|
-
end
|
25
|
-
|
26
|
-
def pop mutex, timeout=60
|
27
|
-
if queue.empty?
|
28
|
-
condv.wait(mutex, timeout)
|
29
|
-
queue.shift || lambda{ |_| false } # shutdown idle workers
|
30
|
-
else
|
31
|
-
queue.shift
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def clear
|
36
|
-
queue.clear
|
37
|
-
end
|
38
|
-
|
39
|
-
protected
|
40
|
-
attr_reader :queue, :condv
|
41
|
-
end
|
42
|
-
|
43
|
-
class Task < Struct.new(:job, :mutex, :thread, :cancelled)
|
44
|
-
# this should never fail
|
45
|
-
def call working_thread
|
46
|
-
mutex.synchronize do
|
47
|
-
return if cancelled
|
48
|
-
self.thread = working_thread
|
49
|
-
end
|
50
|
-
job.call
|
51
|
-
true
|
52
|
-
end
|
53
|
-
|
54
|
-
def cancel
|
55
|
-
self.cancelled = true
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.[] client_class
|
60
|
-
(@pools ||= {})[client_class] ||= new(client_class)
|
61
|
-
end
|
62
|
-
|
63
|
-
attr_reader :client_class, :workers
|
64
|
-
|
65
|
-
def initialize client_class
|
66
|
-
@client_class = client_class
|
67
|
-
@queue = Queue.new
|
68
|
-
@mutex = Mutex.new
|
69
|
-
@workers = []
|
70
|
-
@waiting = 0
|
71
|
-
end
|
72
|
-
|
73
|
-
def inspect
|
74
|
-
"#<#{self.class.name} client_class=#{client_class}>"
|
75
|
-
end
|
76
|
-
|
77
|
-
def size
|
78
|
-
workers.size
|
79
|
-
end
|
80
|
-
|
81
|
-
def max_size
|
82
|
-
client_class.pool_size
|
83
|
-
end
|
84
|
-
|
85
|
-
def idle_time
|
86
|
-
client_class.pool_idle_time
|
87
|
-
end
|
88
|
-
|
89
|
-
def defer promise_mutex, &job
|
90
|
-
mutex.synchronize do
|
91
|
-
task = Task.new(job, promise_mutex)
|
92
|
-
queue << task
|
93
|
-
spawn_worker if waiting < queue.size && workers.size < max_size
|
94
|
-
task
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def trim force=false
|
99
|
-
mutex.synchronize do
|
100
|
-
queue << lambda{ |_| false } if force || waiting > 0
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Block on shutting down, and should not add more jobs while shutting down
|
105
|
-
def shutdown
|
106
|
-
workers.size.times{ trim(true) }
|
107
|
-
workers.first.join && trim(true) until workers.empty?
|
108
|
-
mutex.synchronize{ queue.clear }
|
109
|
-
end
|
110
|
-
|
111
|
-
protected
|
112
|
-
attr_reader :queue, :mutex, :condv, :waiting
|
113
|
-
|
114
|
-
private
|
115
|
-
def spawn_worker
|
116
|
-
workers << Thread.new{
|
117
|
-
Thread.current.abort_on_exception = true
|
118
|
-
|
119
|
-
task = nil
|
120
|
-
begin
|
121
|
-
mutex.synchronize do
|
122
|
-
@waiting += 1
|
123
|
-
task = queue.pop(mutex, idle_time)
|
124
|
-
@waiting -= 1
|
125
|
-
end
|
126
|
-
end while task.call(Thread.current)
|
127
|
-
|
128
|
-
mutex.synchronize{ workers.delete(Thread.current) }
|
129
|
-
}
|
130
|
-
end
|
131
|
-
end
|
data/lib/rest-core/timer.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'thread'
|
3
|
-
require 'timers'
|
4
|
-
|
5
|
-
class RestCore::Timer
|
6
|
-
@mutex = Mutex.new
|
7
|
-
@interval = 1
|
8
|
-
|
9
|
-
singleton_class.module_eval do
|
10
|
-
attr_accessor :interval
|
11
|
-
|
12
|
-
def group
|
13
|
-
@group ||= @mutex.synchronize{ @group ||= group_new }
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
def group_new
|
18
|
-
g = Timers::Group.new
|
19
|
-
g.every(interval){}
|
20
|
-
@thread = Thread.new do
|
21
|
-
begin
|
22
|
-
g.wait
|
23
|
-
rescue => e
|
24
|
-
warn "RestCore::Timer: ERROR: #{e}\n from #{e.backtrace.inspect}"
|
25
|
-
end while g.count > 1
|
26
|
-
@group = nil
|
27
|
-
end
|
28
|
-
g
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
attr_accessor :timeout, :error, :timer
|
33
|
-
def initialize timeout, error, &block
|
34
|
-
self.timeout = timeout
|
35
|
-
self.error = error
|
36
|
-
self.block = block
|
37
|
-
start if block_given?
|
38
|
-
end
|
39
|
-
|
40
|
-
def on_timeout &block
|
41
|
-
self.block = block
|
42
|
-
start if block_given?
|
43
|
-
end
|
44
|
-
|
45
|
-
# should never raise!
|
46
|
-
def cancel
|
47
|
-
timer.cancel if timer
|
48
|
-
self.block = nil
|
49
|
-
end
|
50
|
-
|
51
|
-
def start
|
52
|
-
return if timeout.nil? || timeout.zero?
|
53
|
-
self.timer = self.class.group.after(timeout){ block.call if block }
|
54
|
-
end
|
55
|
-
|
56
|
-
protected
|
57
|
-
attr_accessor :block
|
58
|
-
end
|
@@ -1,173 +0,0 @@
|
|
1
|
-
|
2
|
-
# stolen and modified from rest-client
|
3
|
-
|
4
|
-
require 'rest-core/error'
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'mime/types/columnar'
|
8
|
-
rescue LoadError
|
9
|
-
require 'mime/types'
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'stringio'
|
13
|
-
require 'tempfile'
|
14
|
-
|
15
|
-
module RestCore; end
|
16
|
-
class RestCore::Payload
|
17
|
-
include RestCore
|
18
|
-
|
19
|
-
def self.generate_with_headers payload, headers
|
20
|
-
h = if p = generate(payload)
|
21
|
-
p.headers.merge(headers)
|
22
|
-
else
|
23
|
-
headers
|
24
|
-
end
|
25
|
-
[p, h]
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.generate payload
|
29
|
-
if payload.respond_to?(:read)
|
30
|
-
Streamed.new(payload)
|
31
|
-
|
32
|
-
elsif payload.kind_of?(String)
|
33
|
-
StreamedString.new(payload)
|
34
|
-
|
35
|
-
elsif payload.kind_of?(Hash)
|
36
|
-
if payload.empty?
|
37
|
-
nil
|
38
|
-
|
39
|
-
elsif Middleware.contain_binary?(payload)
|
40
|
-
Multipart.new(payload)
|
41
|
-
|
42
|
-
else
|
43
|
-
UrlEncoded.new(payload)
|
44
|
-
end
|
45
|
-
|
46
|
-
else
|
47
|
-
raise Error.new("Payload should be either String, Hash, or" \
|
48
|
-
" responding to `read', but: #{payload.inspect}")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# Payload API
|
53
|
-
attr_reader :io
|
54
|
-
alias_method :to_io, :io
|
55
|
-
|
56
|
-
def initialize payload; @io = payload ; end
|
57
|
-
def read bytes=nil; io.read(bytes) ; end
|
58
|
-
def close ; io.close unless closed?; end
|
59
|
-
def closed? ; io.closed? ; end
|
60
|
-
def headers ; {} ; end
|
61
|
-
|
62
|
-
def size
|
63
|
-
if io.respond_to?(:size)
|
64
|
-
io.size
|
65
|
-
elsif io.respond_to?(:stat)
|
66
|
-
io.stat.size
|
67
|
-
else
|
68
|
-
0
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class Streamed < Payload
|
73
|
-
def headers
|
74
|
-
{'Content-Length' => size.to_s}
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
class StreamedString < Streamed
|
79
|
-
def initialize payload
|
80
|
-
super(StringIO.new(payload))
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class UrlEncoded < StreamedString
|
85
|
-
def initialize payload
|
86
|
-
super(RestCore::Middleware.percent_encode(payload))
|
87
|
-
end
|
88
|
-
|
89
|
-
def headers
|
90
|
-
super.merge('Content-Type' => 'application/x-www-form-urlencoded')
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
class Multipart < Streamed
|
95
|
-
EOL = "\r\n"
|
96
|
-
|
97
|
-
def initialize payload
|
98
|
-
super(Tempfile.new("rest-core.payload.#{boundary}"))
|
99
|
-
|
100
|
-
io.binmode
|
101
|
-
|
102
|
-
payload.each_with_index do |(k, v), i|
|
103
|
-
if v.kind_of?(Array)
|
104
|
-
v.each{ |vv| part(k, vv) }
|
105
|
-
else
|
106
|
-
part(k, v)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
io.write("--#{boundary}--#{EOL}")
|
110
|
-
io.rewind
|
111
|
-
end
|
112
|
-
|
113
|
-
def part k, v
|
114
|
-
io.write("--#{boundary}#{EOL}Content-Disposition: form-data")
|
115
|
-
io.write("; name=\"#{k}\"") if k
|
116
|
-
if v.respond_to?(:read)
|
117
|
-
part_binary(k, v)
|
118
|
-
else
|
119
|
-
part_plantext(k, v)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def part_plantext k, v
|
124
|
-
io.write("#{EOL}#{EOL}#{v}#{EOL}")
|
125
|
-
end
|
126
|
-
|
127
|
-
def part_binary k, v
|
128
|
-
if v.respond_to?(:original_filename) # Rails
|
129
|
-
io.write("; filename=\"#{v.original_filename}\"#{EOL}")
|
130
|
-
elsif v.respond_to?(:path) # files
|
131
|
-
io.write("; filename=\"#{File.basename(v.path)}\"#{EOL}")
|
132
|
-
else # io
|
133
|
-
io.write("; filename=\"#{k}\"#{EOL}")
|
134
|
-
end
|
135
|
-
|
136
|
-
# supply your own content type for regular files, will you?
|
137
|
-
if v.respond_to?(:content_type) # Rails
|
138
|
-
io.write("Content-Type: #{v.content_type}#{EOL}#{EOL}")
|
139
|
-
elsif v.respond_to?(:path) && type = mime_type(v.path) # files
|
140
|
-
io.write("Content-Type: #{type}#{EOL}#{EOL}")
|
141
|
-
else
|
142
|
-
io.write(EOL)
|
143
|
-
end
|
144
|
-
|
145
|
-
while data = v.read(8192)
|
146
|
-
io.write(data)
|
147
|
-
end
|
148
|
-
|
149
|
-
io.write(EOL)
|
150
|
-
|
151
|
-
ensure
|
152
|
-
v.close if v.respond_to?(:close)
|
153
|
-
end
|
154
|
-
|
155
|
-
def mime_type path
|
156
|
-
mime = MIME::Types.type_for(path)
|
157
|
-
mime.first && mime.first.content_type
|
158
|
-
end
|
159
|
-
|
160
|
-
def boundary
|
161
|
-
@boundary ||= rand(1_000_000).to_s
|
162
|
-
end
|
163
|
-
|
164
|
-
def headers
|
165
|
-
super.merge('Content-Type' =>
|
166
|
-
"multipart/form-data; boundary=#{boundary}")
|
167
|
-
end
|
168
|
-
|
169
|
-
def close
|
170
|
-
io.close! unless io.closed?
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
data/test/test_builder.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'rest-core/test'
|
3
|
-
|
4
|
-
describe RC::Builder do
|
5
|
-
would 'default client app is a kind of RestCore::Engine' do
|
6
|
-
RC::Builder.client.new.app.should.kind_of? RC::Engine
|
7
|
-
end
|
8
|
-
|
9
|
-
would 'default app is a kind of RestCore::Engine' do
|
10
|
-
RC::Builder.new.to_app.should.kind_of? RC::Engine
|
11
|
-
end
|
12
|
-
|
13
|
-
would 'switch default_engine to RestCore::Dry a' do
|
14
|
-
builder = Class.new(RC::Builder)
|
15
|
-
builder.default_engine = RC::Dry
|
16
|
-
builder.new.to_app.class.should.eq RC::Dry
|
17
|
-
end
|
18
|
-
|
19
|
-
would 'switch default_engine to RestCore::Dry b' do
|
20
|
-
builder = RC::Builder.dup
|
21
|
-
builder.default_engine = RC::Dry
|
22
|
-
builder.client.new.app.class.should.eq RC::Dry
|
23
|
-
end
|
24
|
-
|
25
|
-
would 'accept middleware without a member' do
|
26
|
-
RC::Builder.client{
|
27
|
-
use Class.new.send(:include, RC::Middleware)
|
28
|
-
}.members.should.eq [:config_engine]
|
29
|
-
end
|
30
|
-
|
31
|
-
would 'not have duplicated fields' do
|
32
|
-
middleware = Class.new do
|
33
|
-
def self.members; [:value]; end
|
34
|
-
include RC::Middleware
|
35
|
-
end
|
36
|
-
client = RC::Builder.client(:value){ use middleware }.new
|
37
|
-
client.value = 10
|
38
|
-
client.value.should.eq 10
|
39
|
-
end
|
40
|
-
end
|
data/test/test_client.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'rest-core/test'
|
3
|
-
|
4
|
-
describe RC::Simple do
|
5
|
-
after do
|
6
|
-
WebMock.reset!
|
7
|
-
Muack.verify
|
8
|
-
end
|
9
|
-
|
10
|
-
url = 'http://example.com/'
|
11
|
-
|
12
|
-
would 'do simple request' do
|
13
|
-
c = RC::Simple.new
|
14
|
-
[:get, :post, :delete, :put, :patch].each do |method|
|
15
|
-
stub_request(method, url).to_return(:body => '[]')
|
16
|
-
c.send(method, url).should.eq '[]'
|
17
|
-
end
|
18
|
-
|
19
|
-
stub_request(:head , url).to_return(:headers => {'A' => 'B'})
|
20
|
-
c. head(url).should.eq('A' => 'B')
|
21
|
-
|
22
|
-
stub_request(:options, url).to_return(:headers => {'A' => 'B'})
|
23
|
-
c.options(url).should.eq('A' => 'B')
|
24
|
-
end
|
25
|
-
|
26
|
-
would 'call the callback' do
|
27
|
-
[:get, :post, :delete, :put, :patch].each do |method|
|
28
|
-
stub_request(method, url).to_return(:body => '123')
|
29
|
-
(client = RC::Simple.new).send(method, url){ |res|
|
30
|
-
res.should.eq '123' }.should.eq client
|
31
|
-
client.wait
|
32
|
-
end
|
33
|
-
|
34
|
-
stub_request(:head, url).to_return(:headers => {'A' => 'B'})
|
35
|
-
(client = RC::Simple.new).head(url){ |res|
|
36
|
-
res.should.eq({'A' => 'B'})
|
37
|
-
}.should.eq client
|
38
|
-
client.wait
|
39
|
-
|
40
|
-
stub_request(:options, url).to_return(:headers => {'A' => 'B'})
|
41
|
-
(client = RC::Simple.new).options(url){ |res|
|
42
|
-
res.should.eq('A' => 'B')
|
43
|
-
}.should.eq client
|
44
|
-
client.wait
|
45
|
-
end
|
46
|
-
|
47
|
-
would 'wait for all the requests' do
|
48
|
-
t, i, m = 5, 0, Mutex.new
|
49
|
-
stub_request(:get, url).to_return do
|
50
|
-
m.synchronize{ i += 1 }
|
51
|
-
Thread.pass
|
52
|
-
{}
|
53
|
-
end
|
54
|
-
|
55
|
-
client = RC::Builder.client
|
56
|
-
t.times{ client.new.get(url) }
|
57
|
-
client.wait
|
58
|
-
client.promises.should.empty?
|
59
|
-
i.should.eq t
|
60
|
-
end
|
61
|
-
|
62
|
-
would 'wait for callback' do
|
63
|
-
rd, wr = IO.pipe
|
64
|
-
called = false
|
65
|
-
stub_request(:get, url).to_return(:body => 'nnf')
|
66
|
-
client = RC::Builder.client.new.get(url) do |nnf|
|
67
|
-
wr.puts
|
68
|
-
sleep 0.001 # make sure our callback is slow enough,
|
69
|
-
# so that if `wait` is not waiting for the callback,
|
70
|
-
# it would leave before the callback is completely done.
|
71
|
-
# without sleeping, the callback is very likely to be
|
72
|
-
# done first than `wait` anyway. raising the sleeping time
|
73
|
-
# would make this test more reliable...
|
74
|
-
called = true
|
75
|
-
nil # test against returning nil, so that Promise#response is not set
|
76
|
-
end
|
77
|
-
rd.gets
|
78
|
-
client.wait
|
79
|
-
called.should.eq true
|
80
|
-
end
|
81
|
-
|
82
|
-
would 'cleanup promises' do
|
83
|
-
stub_request(:get, url).to_return(:body => 'nnf')
|
84
|
-
client = RC::Builder.client
|
85
|
-
5.times{ client.new.get(url) }
|
86
|
-
Thread.pass
|
87
|
-
GC.start # can only force GC run on MRI, so we mock for jruby and rubinius
|
88
|
-
stub(any_instance_of(WeakRef)).weakref_alive?{false}
|
89
|
-
client.new.get(url)
|
90
|
-
client.promises.size.should.lt 6
|
91
|
-
client.shutdown
|
92
|
-
client.promises.should.empty?
|
93
|
-
end
|
94
|
-
|
95
|
-
would 'have correct to_i' do
|
96
|
-
stub_request(:get, url).to_return(:body => '123')
|
97
|
-
RC::Simple.new.get(url).to_i.should.eq 123
|
98
|
-
end
|
99
|
-
|
100
|
-
would 'use defaults' do
|
101
|
-
client = RC::Builder.client do
|
102
|
-
use RC::Timeout, 4
|
103
|
-
end
|
104
|
-
c = client.new
|
105
|
-
c.timeout.should.eq 4 # default goes to middleware
|
106
|
-
client.extend(Module.new do
|
107
|
-
def default_timeout
|
108
|
-
3
|
109
|
-
end
|
110
|
-
end)
|
111
|
-
c.timeout.should.eq 4 # default is cached, so it stays the same
|
112
|
-
c.timeout = nil # clear cache
|
113
|
-
c.timeout.should.eq 3 # now default goes to module default
|
114
|
-
class << client
|
115
|
-
def default_timeout # module defaults could be overriden
|
116
|
-
super - 1
|
117
|
-
end
|
118
|
-
end
|
119
|
-
c.timeout = nil
|
120
|
-
c.timeout.should.eq 2 # so it goes to class default
|
121
|
-
c.timeout = 1 # setup instance level value
|
122
|
-
c.build_env( )['timeout'].should.eq 1 # pick instance var
|
123
|
-
c.build_env({'timeout' => 0})['timeout'].should.eq 0 # per-request var
|
124
|
-
c.timeout.should.eq 1 # won't affect underlying instance var
|
125
|
-
c.timeout = nil
|
126
|
-
c.timeout.should.eq 2 # goes back to class default
|
127
|
-
c.timeout = false
|
128
|
-
c.timeout.should.eq false # false would disable default
|
129
|
-
end
|
130
|
-
|
131
|
-
would 'work for inheritance' do
|
132
|
-
stub_request(:get, url).to_return(:body => '123')
|
133
|
-
Class.new(RC::Simple).new.get(url).should.eq '123'
|
134
|
-
end
|
135
|
-
|
136
|
-
would 'not deadlock when exception was raised in the callback' do
|
137
|
-
client = Class.new(RC::Simple).new
|
138
|
-
stub_request(:get, url).to_return(:body => 'nnf')
|
139
|
-
|
140
|
-
(-1..1).each do |size|
|
141
|
-
mock(any_instance_of(RC::Promise)).warn(is_a(String)) do |msg|
|
142
|
-
msg.should.include?('nnf')
|
143
|
-
end
|
144
|
-
client.class.pool_size = size
|
145
|
-
client.get(url) do |body|
|
146
|
-
raise body
|
147
|
-
end
|
148
|
-
client.class.shutdown
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
would 'be able to access caller outside the callback' do
|
153
|
-
client = RC::Simple.new
|
154
|
-
stub_request(:get, url).to_return(:body => 'nnf')
|
155
|
-
client.get(url) do
|
156
|
-
current_file = /^#{__FILE__}/
|
157
|
-
caller.grep(current_file).should.empty?
|
158
|
-
RC::Promise.backtrace.grep(current_file).should.not.empty?
|
159
|
-
client.get(url) do
|
160
|
-
RC::Promise.backtrace.last.should.not =~ /promise\.rb:\d+:in/
|
161
|
-
client = nil
|
162
|
-
end
|
163
|
-
end
|
164
|
-
client.wait
|
165
|
-
client.should.nil? # to make sure the inner most block did run
|
166
|
-
end
|
167
|
-
|
168
|
-
would 'call error_callback' do
|
169
|
-
error = nil
|
170
|
-
error_callback = lambda{ |e| error = e }
|
171
|
-
should.raise(Errno::ECONNREFUSED) do
|
172
|
-
RC::Simple.new(:error_callback => error_callback).
|
173
|
-
get('http://localhost:1').tap{}
|
174
|
-
end
|
175
|
-
error.should.kind_of?(Errno::ECONNREFUSED)
|
176
|
-
end
|
177
|
-
end
|