rest-core 3.5.1 → 3.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -3
- data/CHANGES.md +11 -0
- data/lib/rest-core/client.rb +1 -5
- data/lib/rest-core/promise.rb +39 -28
- data/lib/rest-core/timer.rb +3 -2
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +3 -3
- data/test/test_httpclient.rb +1 -2
- data/test/test_timeout.rb +4 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0399835474967a9425ce60b8073d0b4a49e7c572
|
4
|
+
data.tar.gz: 6cac1d0a2fce2e8f5ea64e64b2b56343d8e61368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5beda3343160e6e04d7df902f702a6d99aa02ef49c6e7d9085d398c76ec07d518e096af779bdbf336a6e2b80fe20438f630676b4c97cd20706d990d0a263c5db
|
7
|
+
data.tar.gz: 1ee0950dd782a66de5bf11fe8e5cf4f7a42da6717883a7d25c58be37abb7c38d7ad5b1334bef1325b45e42eafd46d250ae0b928d4846757af0bfc7fe90019c1d
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## rest-core 3.5.2 -- 2015-01-09
|
4
|
+
|
5
|
+
### Bugs fixed
|
6
|
+
|
7
|
+
* Now callbacks would respect `RC::RESPONSE_KEY`.
|
8
|
+
* Clear `Thread.current[:backtrace]` after done in thread pool to reduce
|
9
|
+
memory footprint.
|
10
|
+
* Fixed backtrace for exception raised in callbacks.
|
11
|
+
* Fixed some potential corner cases where errors are not properly handled
|
12
|
+
when timeout happened.
|
13
|
+
|
3
14
|
## rest-core 3.5.1 -- 2014-12-27
|
4
15
|
|
5
16
|
* Ruby 2.2 compatibility.
|
data/lib/rest-core/client.rb
CHANGED
@@ -214,11 +214,7 @@ module RestCore::Client
|
|
214
214
|
RC::Promise.set_backtrace(err) unless err.backtrace
|
215
215
|
error_callback.call(err) if error_callback
|
216
216
|
if res[ASYNC]
|
217
|
-
|
218
|
-
res.merge(RESPONSE_SOCKET => err)
|
219
|
-
else
|
220
|
-
res.merge(RESPONSE_BODY => err)
|
221
|
-
end
|
217
|
+
res.merge(response_key(res) => err)
|
222
218
|
else
|
223
219
|
raise err
|
224
220
|
end
|
data/lib/rest-core/promise.rb
CHANGED
@@ -65,16 +65,15 @@ class RestCore::Promise
|
|
65
65
|
# called in client thread
|
66
66
|
def defer
|
67
67
|
if pool_size < 0 # negative number for blocking call
|
68
|
-
self.thread = Thread.current
|
69
|
-
|
70
|
-
env[TIMER].on_timeout{ cancel_task } if env[TIMER]
|
71
|
-
protected_yield{ yield }
|
68
|
+
self.thread = Thread.current # set working thread
|
69
|
+
protected_yield{ yield } # avoid any exception and do the job
|
72
70
|
else
|
73
71
|
backtrace = caller + self.class.backtrace
|
74
72
|
if pool_size > 0
|
75
73
|
self.task = client_class.thread_pool.defer(mutex) do
|
76
74
|
Thread.current[:backtrace] = backtrace
|
77
75
|
protected_yield{ yield }
|
76
|
+
Thread.current[:backtrace] = nil
|
78
77
|
end
|
79
78
|
else
|
80
79
|
self.thread = Thread.new do
|
@@ -82,8 +81,6 @@ class RestCore::Promise
|
|
82
81
|
protected_yield{ yield }
|
83
82
|
end
|
84
83
|
end
|
85
|
-
# set timeout after thread/task set
|
86
|
-
env[TIMER].on_timeout{ cancel_task } if env[TIMER]
|
87
84
|
end
|
88
85
|
end
|
89
86
|
|
@@ -153,32 +150,31 @@ class RestCore::Promise
|
|
153
150
|
# called in a new thread if pool_size == 0, otherwise from the pool
|
154
151
|
# i.e. requesting thread
|
155
152
|
def protected_yield
|
156
|
-
|
153
|
+
if env[TIMER]
|
154
|
+
timeout_protected_yield{ yield }
|
155
|
+
else
|
156
|
+
yield
|
157
|
+
end
|
157
158
|
rescue Exception => e
|
158
159
|
mutex.synchronize do
|
159
|
-
|
160
|
-
|
161
|
-
self.class.set_backtrace(e)
|
162
|
-
end
|
163
|
-
|
164
|
-
if done?
|
160
|
+
self.class.set_backtrace(e)
|
161
|
+
if done? # log user callback error
|
165
162
|
callback_error(e)
|
166
|
-
else
|
163
|
+
else # IOError, SystemCallError, etc
|
167
164
|
begin
|
168
|
-
rejecting(e)
|
169
|
-
rescue Exception =>
|
170
|
-
callback_error(
|
165
|
+
rejecting(e)
|
166
|
+
rescue Exception => f # log user callback error
|
167
|
+
callback_error(f){ self.class.set_backtrace(f) }
|
171
168
|
end
|
172
169
|
end
|
173
170
|
end
|
174
171
|
end
|
175
172
|
|
176
|
-
|
177
|
-
|
178
|
-
def never_raise_yield
|
173
|
+
def timeout_protected_yield
|
174
|
+
env[TIMER].on_timeout{ cancel_task } # set timeout
|
179
175
|
yield
|
180
|
-
|
181
|
-
|
176
|
+
ensure
|
177
|
+
env[TIMER].cancel
|
182
178
|
end
|
183
179
|
|
184
180
|
# called in client thread, when yield is called
|
@@ -195,8 +191,10 @@ class RestCore::Promise
|
|
195
191
|
self.called = true
|
196
192
|
end
|
197
193
|
|
194
|
+
# log user callback error
|
198
195
|
def callback_error e
|
199
196
|
never_raise_yield do
|
197
|
+
yield if block_given?
|
200
198
|
if env[CLIENT].error_callback
|
201
199
|
env[CLIENT].error_callback.call(e)
|
202
200
|
else
|
@@ -205,18 +203,31 @@ class RestCore::Promise
|
|
205
203
|
end
|
206
204
|
end
|
207
205
|
|
208
|
-
|
206
|
+
# timeout!
|
207
|
+
def cancel_task backtrace=nil
|
209
208
|
mutex.synchronize do
|
210
|
-
next if done?
|
209
|
+
next if done? # don't cancel if it's done
|
211
210
|
if t = thread || task.thread
|
212
|
-
t.raise(env[TIMER].error)
|
213
|
-
else
|
214
|
-
|
215
|
-
|
211
|
+
t.raise(env[TIMER].error) # raise Timeout::Error to working thread
|
212
|
+
else # task was queued and never started, just cancel it and
|
213
|
+
begin # fulfil the promise with Timeout::Error
|
214
|
+
task.cancel
|
215
|
+
rejecting(env[TIMER].error)
|
216
|
+
rescue Exception => e # log user callback error
|
217
|
+
callback_error(e){e.set_backtrace(e.backtrace + (backtrace || []))}
|
218
|
+
end
|
216
219
|
end
|
217
220
|
end
|
218
221
|
end
|
219
222
|
|
223
|
+
# only use this for unimportant stuffs and in most critical section
|
224
|
+
# e.g. error logging in critical section
|
225
|
+
def never_raise_yield
|
226
|
+
yield
|
227
|
+
rescue Exception => e
|
228
|
+
Thread.main.raise(e) if !!$DEBUG
|
229
|
+
end
|
230
|
+
|
220
231
|
def client_class; env[CLIENT].class; end
|
221
232
|
def pool_size
|
222
233
|
@pool_size ||= if client_class.respond_to?(:pool_size)
|
data/lib/rest-core/timer.rb
CHANGED
@@ -34,16 +34,17 @@ class RestCore::Timer
|
|
34
34
|
self.timeout = timeout
|
35
35
|
self.error = error
|
36
36
|
self.block = block
|
37
|
-
start
|
37
|
+
start if block_given?
|
38
38
|
end
|
39
39
|
|
40
40
|
def on_timeout &block
|
41
41
|
self.block = block
|
42
|
+
start if block_given?
|
42
43
|
end
|
43
44
|
|
44
45
|
# should never raise!
|
45
46
|
def cancel
|
46
|
-
timer.cancel
|
47
|
+
timer.cancel if timer
|
47
48
|
self.block = nil
|
48
49
|
end
|
49
50
|
|
data/lib/rest-core/version.rb
CHANGED
data/rest-core.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: rest-core 3.5.
|
2
|
+
# stub: rest-core 3.5.2 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "rest-core"
|
6
|
-
s.version = "3.5.
|
6
|
+
s.version = "3.5.2"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib"]
|
10
10
|
s.authors = ["Lin Jen-Shin (godfat)"]
|
11
|
-
s.date = "
|
11
|
+
s.date = "2015-01-09"
|
12
12
|
s.description = "Modular Ruby clients interface for REST APIs.\n\nThere has been an explosion in the number of REST APIs available today.\nTo address the need for a way to access these APIs easily and elegantly,\nwe have developed rest-core, which consists of composable middleware\nthat allows you to build a REST client for any REST API. Or in the case of\ncommon APIs such as Facebook, Github, and Twitter, you can simply use the\ndedicated clients provided by [rest-more][].\n\n[rest-more]: https://github.com/godfat/rest-more"
|
13
13
|
s.email = ["godfat (XD) godfat.org"]
|
14
14
|
s.files = [
|
data/test/test_httpclient.rb
CHANGED
@@ -40,8 +40,7 @@ describe RC::HttpClient do
|
|
40
40
|
|
41
41
|
would 'not kill the thread if error was coming from the task' do
|
42
42
|
mock(HTTPClient).new{ raise 'boom' }.with_any_args
|
43
|
-
c.request(RC::
|
44
|
-
RC::ASYNC => true).first.message.should.eq 'boom'
|
43
|
+
c.request(RC::ASYNC => true).message.should.eq 'boom'
|
45
44
|
Muack.verify
|
46
45
|
end
|
47
46
|
end
|
data/test/test_timeout.rb
CHANGED
@@ -43,9 +43,8 @@ describe RC::Timeout do
|
|
43
43
|
}
|
44
44
|
end
|
45
45
|
app.pool_size = 1
|
46
|
-
app.new.request(RC::
|
47
|
-
|
48
|
-
first.message.should.eq 'boom'
|
46
|
+
app.new.request(RC::TIMER => timer, RC::ASYNC => true).
|
47
|
+
message.should.eq 'boom'
|
49
48
|
end
|
50
49
|
|
51
50
|
would 'interrupt the task if timing out' do
|
@@ -71,9 +70,8 @@ describe RC::Timeout do
|
|
71
70
|
end
|
72
71
|
(-1..1).each do |size|
|
73
72
|
app.pool_size = size
|
74
|
-
app.new.request(RC::
|
75
|
-
|
76
|
-
first.message.should.eq 'boom'
|
73
|
+
app.new.request(RC::TIMER => timer, RC::ASYNC => true, 'pipe' => wr).
|
74
|
+
message.should.eq 'boom'
|
77
75
|
end
|
78
76
|
end
|
79
77
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.5.
|
4
|
+
version: 3.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lin Jen-Shin (godfat)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|