rest-core 3.5.2 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0399835474967a9425ce60b8073d0b4a49e7c572
4
- data.tar.gz: 6cac1d0a2fce2e8f5ea64e64b2b56343d8e61368
3
+ metadata.gz: fe0c761a5d6c0bc856f35b558c9f70a74ac36815
4
+ data.tar.gz: 27c1295dc0082285072cfcd618afca9f5bf3b39f
5
5
  SHA512:
6
- metadata.gz: 5beda3343160e6e04d7df902f702a6d99aa02ef49c6e7d9085d398c76ec07d518e096af779bdbf336a6e2b80fe20438f630676b4c97cd20706d990d0a263c5db
7
- data.tar.gz: 1ee0950dd782a66de5bf11fe8e5cf4f7a42da6717883a7d25c58be37abb7c38d7ad5b1334bef1325b45e42eafd46d250ae0b928d4846757af0bfc7fe90019c1d
6
+ metadata.gz: c771af63c6cbc5b9ab95043aafedf83aa1e56c56e0179696a828a03b41dcf61cfb7f934db1e40a9e31632ae263e29ad62cdc87223d759603b1be6ac7b9e29154
7
+ data.tar.gz: ae1f3a83d67d4790a0805fd77261d2eee610eb62680b076ff754691ce6cbf64b3a86871b84ebcf1f6a0b2d4247eb174784a65c7b0f8c76e5acd83008a3353050
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGES
2
2
 
3
+ ## rest-core 3.5.3 -- 2015-01-11
4
+
5
+ ### Bugs fixed
6
+
7
+ * Fixed a regression where timeout is not properly handled for thread pool.
8
+
3
9
  ## rest-core 3.5.2 -- 2015-01-09
4
10
 
5
11
  ### Bugs fixed
@@ -68,12 +68,16 @@ class RestCore::Promise
68
68
  self.thread = Thread.current # set working thread
69
69
  protected_yield{ yield } # avoid any exception and do the job
70
70
  else
71
- backtrace = caller + self.class.backtrace
71
+ backtrace = caller + self.class.backtrace # retain the backtrace so far
72
72
  if pool_size > 0
73
- self.task = client_class.thread_pool.defer(mutex) do
74
- Thread.current[:backtrace] = backtrace
75
- protected_yield{ yield }
76
- Thread.current[:backtrace] = nil
73
+ mutex.synchronize do
74
+ # still timing it out if the task never processed
75
+ env[TIMER].on_timeout{ cancel_task } if env[TIMER]
76
+ self.task = client_class.thread_pool.defer(mutex) do
77
+ Thread.current[:backtrace] = backtrace
78
+ protected_yield{ yield }
79
+ Thread.current[:backtrace] = nil
80
+ end
77
81
  end
78
82
  else
79
83
  self.thread = Thread.new do
@@ -162,7 +166,7 @@ class RestCore::Promise
162
166
  callback_error(e)
163
167
  else # IOError, SystemCallError, etc
164
168
  begin
165
- rejecting(e)
169
+ rejecting(e) # would call user callback
166
170
  rescue Exception => f # log user callback error
167
171
  callback_error(f){ self.class.set_backtrace(f) }
168
172
  end
@@ -171,7 +175,8 @@ class RestCore::Promise
171
175
  end
172
176
 
173
177
  def timeout_protected_yield
174
- env[TIMER].on_timeout{ cancel_task } # set timeout
178
+ # timeout might already be set for thread_pool (pool_size > 0)
179
+ env[TIMER].on_timeout{ cancel_task } unless env[TIMER].timer
175
180
  yield
176
181
  ensure
177
182
  env[TIMER].cancel
@@ -210,7 +215,7 @@ class RestCore::Promise
210
215
  if t = thread || task.thread
211
216
  t.raise(env[TIMER].error) # raise Timeout::Error to working thread
212
217
  else # task was queued and never started, just cancel it and
213
- begin # fulfil the promise with Timeout::Error
218
+ begin # fulfill the promise with Timeout::Error
214
219
  task.cancel
215
220
  rejecting(env[TIMER].error)
216
221
  rescue Exception => e # log user callback error
@@ -88,12 +88,10 @@ class RestCore::ThreadPool
88
88
  end
89
89
 
90
90
  def defer mutex=nil, &job
91
- mutex.synchronize do
92
- task = Task.new(job, mutex)
93
- queue << task
94
- spawn_worker if waiting == 0 && workers.size < max_size
95
- task
96
- end
91
+ task = Task.new(job, mutex)
92
+ queue << task
93
+ spawn_worker if waiting == 0 && workers.size < max_size
94
+ task
97
95
  end
98
96
 
99
97
  def trim force=false
@@ -29,7 +29,7 @@ class RestCore::Timer
29
29
  end
30
30
  end
31
31
 
32
- attr_accessor :timeout, :error
32
+ attr_accessor :timeout, :error, :timer
33
33
  def initialize timeout, error, &block
34
34
  self.timeout = timeout
35
35
  self.error = error
@@ -54,5 +54,5 @@ class RestCore::Timer
54
54
  end
55
55
 
56
56
  protected
57
- attr_accessor :block, :timer
57
+ attr_accessor :block
58
58
  end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module RestCore
3
- VERSION = '3.5.2'
3
+ VERSION = '3.5.3'
4
4
  end
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rest-core 3.5.2 ruby lib
2
+ # stub: rest-core 3.5.3 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "rest-core"
6
- s.version = "3.5.2"
6
+ s.version = "3.5.3"
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 = "2015-01-09"
11
+ s.date = "2015-01-11"
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 = [
@@ -28,36 +28,61 @@ describe RC::Timeout do
28
28
  lambda{ sleep 0.01 }.should.not.raise(Timeout::Error)
29
29
  end
30
30
 
31
- would 'cancel the task if timing out' do
32
- timer = Object.new.instance_eval do
33
- def on_timeout; yield ; end
31
+ def fake_timer
32
+ Object.new.instance_eval do
33
+ @block = nil
34
+ def on_timeout; @block = true; Thread.new{yield}; end
34
35
  def error ; 'boom'; end
35
36
  def cancel ; ; end
37
+ def timer ; @block; end
36
38
  self
37
39
  end
38
- app = RC::Builder.client do
40
+ end
41
+
42
+ def sleeping_app
43
+ RC::Builder.client do
39
44
  run Class.new(RC::Engine){
40
45
  def request _, _
41
46
  sleep
42
47
  end
43
48
  }
44
49
  end
50
+ end
51
+
52
+ would 'cancel the task if timing out for thread pool' do
53
+ timer = fake_timer
54
+ app = sleeping_app
45
55
  app.pool_size = 1
46
56
  app.new.request(RC::TIMER => timer, RC::ASYNC => true).
47
57
  message.should.eq 'boom'
58
+ timer.timer.should.not.nil?
59
+ end
60
+
61
+ would 'still timeout if the task never processed for thread pool' do
62
+ app = sleeping_app
63
+ app.pool_size = 1
64
+ app.new.request(RC::TIMER => fake_timer, RC::ASYNC => true) do |e|
65
+ e.message.should.eq 'boom'
66
+ app.new.request(RC::TIMER => fake_timer, RC::ASYNC => true).tap{}
67
+ end
68
+ app.wait
48
69
  end
49
70
 
50
71
  would 'interrupt the task if timing out' do
51
72
  rd, wr = IO.pipe
52
73
  timer = Object.new.instance_eval do
74
+ @block = nil
53
75
  define_singleton_method :on_timeout do |&block|
76
+ @block = block
54
77
  Thread.new do
55
78
  rd.gets
56
79
  block.call
80
+ @block = nil
57
81
  end
58
82
  end
59
83
  def error ; 'boom'; end
60
84
  def cancel ; ; end
85
+ def timer ; @block; end
61
86
  self
62
87
  end
63
88
  app = RC::Builder.client do
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.2
4
+ version: 3.5.3
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: 2015-01-09 00:00:00.000000000 Z
11
+ date: 2015-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient