rest-core 3.4.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab6a9f5e489329946784228471a7647aac66bbdd
4
- data.tar.gz: 4b8d30e22074977305146a9a0cc875334c473599
3
+ metadata.gz: 85f12b68843aae98a2ceaa7d85346e0c99627f21
4
+ data.tar.gz: d8ba6d00b676443be83d939f7b676ad75f96ec0a
5
5
  SHA512:
6
- metadata.gz: 09378189003073e9e0fcde4b210c6ef3e5e7441388e006ba5f5e9bb916acd6b191ac7fd7e9649837dcd82e8e5d360a1efe41f3e6fa247fc9911e584b5dd074ce
7
- data.tar.gz: cdf158fd0a2ca140d64792e7daa29575c9914ca5ede20b556ef04f64bc93792f053c3d2e49f59a6888823baa623fc467dbd41edac26544b9d97057e7b511b7e2
6
+ metadata.gz: 56f4c5e7e9b54d700947e99598fa889d1bea1d2a9e07a954fcf795109bf5935263b26db50e881ad71458671213d60961b367738b400d1abe5046ade10c05d6b5
7
+ data.tar.gz: bb5712b4ac86364fcbe05ca8ad938ef6635764e73695a02a982dfb3b6028f0752539063f80ecad5ff630f75c2b185e399e60780eeeeade4938e45066b7743aa1
data/CHANGES.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # CHANGES
2
2
 
3
+ ## rest-core 3.4.1 -- 2014-11-29
4
+
5
+ ### Bugs fixed
6
+
7
+ * Handle errors for `RC::EventSource` more conservatively to avoid any
8
+ potential deadlock.
9
+
10
+ * It would not deadlock even if logging failed.
11
+
3
12
  ## rest-core 3.4.0 -- 2014-11-26
4
13
 
5
14
  ### Incompatible changes
@@ -12,12 +12,13 @@ class RestCore::EventSource < Struct.new(:client, :path, :query, :opts,
12
12
  @onmessage ||= nil
13
13
  @onerror ||= nil
14
14
  @onreconnect ||= nil
15
+ @closed ||= false
15
16
  reconnect
16
17
  self
17
18
  end
18
19
 
19
20
  def closed?
20
- !!(socket && socket.closed?)
21
+ !!(socket && socket.closed?) || @closed
21
22
  end
22
23
 
23
24
  def close
@@ -66,8 +67,11 @@ class RestCore::EventSource < Struct.new(:client, :path, :query, :opts,
66
67
  begin
67
68
  @onerror.call(error, sock) if @onerror
68
69
  onreconnect(error, sock)
69
- rescue
70
- condv.signal # so we can't be reconnecting, need to try to unblock
70
+ rescue Exception => e
71
+ mutex.synchronize do
72
+ @closed = true
73
+ condv.signal # so we can't be reconnecting, need to try to unblock
74
+ end
71
75
  raise
72
76
  end
73
77
  end
@@ -82,7 +86,10 @@ class RestCore::EventSource < Struct.new(:client, :path, :query, :opts,
82
86
  elsif closed? && @onreconnect && @onreconnect.call(error, sock)
83
87
  reconnect
84
88
  else
85
- condv.signal # we could be closing, let's try to unblock it
89
+ mutex.synchronize do
90
+ @closed = true
91
+ condv.signal # we could be closing, let's try to unblock it
92
+ end
86
93
  end
87
94
  self
88
95
  end
@@ -110,6 +117,12 @@ class RestCore::EventSource < Struct.new(:client, :path, :query, :opts,
110
117
  def reconnect
111
118
  o = {REQUEST_HEADERS => {'Accept' => 'text/event-stream'},
112
119
  HIJACK => true}.merge(opts)
113
- client.get(path, query, o){ |sock| onopen(sock) }
120
+ client.get(path, query, o) do |sock|
121
+ if sock.nil? || sock.kind_of?(Exception)
122
+ onerror(sock)
123
+ else
124
+ onopen(sock)
125
+ end
126
+ end
114
127
  end
115
128
  end
@@ -32,7 +32,11 @@ class RestCore::ErrorHandler
32
32
  def process res, err
33
33
  RC::Promise.set_backtrace(err)
34
34
  if res[ASYNC]
35
- res.merge(RESPONSE_BODY => err)
35
+ if res[HIJACK]
36
+ res.merge(RESPONSE_SOCKET => err)
37
+ else
38
+ res.merge(RESPONSE_BODY => err)
39
+ end
36
40
  else
37
41
  raise err
38
42
  end
@@ -25,6 +25,7 @@ class RestCore::Promise
25
25
  Thread.current[:backtrace] || []
26
26
  end
27
27
 
28
+ # should never raise!
28
29
  def self.set_backtrace e
29
30
  e.set_backtrace((e.backtrace || caller) + backtrace)
30
31
  end
@@ -154,18 +155,32 @@ class RestCore::Promise
154
155
  def protected_yield
155
156
  yield
156
157
  rescue Exception => e
157
- # pray if timeout won't trigger here!
158
- env[TIMER].cancel if env[TIMER]
159
158
  mutex.synchronize do
160
- self.class.set_backtrace(e)
161
- # nothing we can do here for an asynchronous exception,
162
- # so we just log the error
163
- # TODO: add error_log_method
164
- warn "RestCore: ERROR: #{e}\n from #{e.backtrace.inspect}"
165
- rejecting(e) unless done? # not done: i/o error; done: callback error
159
+ never_raise_yield do
160
+ env[TIMER].cancel if env[TIMER]
161
+ self.class.set_backtrace(e)
162
+ # TODO: add error_log_method
163
+ warn "RestCore: ERROR: #{e}\n from #{e.backtrace.inspect}"
164
+ end
165
+
166
+ begin
167
+ rejecting(e) unless done? # not done: i/o error; done: callback error
168
+ rescue Exception => e
169
+ never_raise_yield do
170
+ warn "RestCore: ERROR: #{e}\n from #{e.backtrace.inspect}"
171
+ end
172
+ end
166
173
  end
167
174
  end
168
175
 
176
+ # only use this for unimportant stuffs and in most critical section
177
+ # e.g. error logging in critical section
178
+ def never_raise_yield
179
+ yield
180
+ rescue Exception => e
181
+ Thread.main.raise(e) if !!$DEBUG
182
+ end
183
+
169
184
  # called in client thread, when yield is called
170
185
  def callback
171
186
  return response if called
@@ -41,6 +41,7 @@ class RestCore::Timer
41
41
  self.block = block
42
42
  end
43
43
 
44
+ # should never raise!
44
45
  def cancel
45
46
  timer.cancel
46
47
  self.block = nil
@@ -1,4 +1,4 @@
1
1
 
2
2
  module RestCore
3
- VERSION = '3.4.0'
3
+ VERSION = '3.4.1'
4
4
  end
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rest-core 3.4.0 ruby lib
2
+ # stub: rest-core 3.4.1 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "rest-core"
6
- s.version = "3.4.0"
6
+ s.version = "3.4.1"
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 = "2014-11-26"
11
+ s.date = "2014-11-29"
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 = [
@@ -4,6 +4,7 @@ require 'rest-core/test'
4
4
 
5
5
  describe RC::EventSource do
6
6
  after do
7
+ Muack.verify
7
8
  WebMock.reset!
8
9
  end
9
10
 
@@ -131,4 +132,34 @@ SSE
131
132
  end.start.wait
132
133
  m.should.empty?
133
134
  end
135
+
136
+ def mock_warning
137
+ mock(any_instance_of(RC::Promise)).warn(is_a(String)) do |msg|
138
+ msg.should.include?(Errno::ECONNREFUSED.new.message)
139
+ end
140
+ end
141
+
142
+ would 'not deadlock without ErrorHandler' do
143
+ mock_warning
144
+ c = RC::Simple.new.event_source('http://localhost:1')
145
+ c.onerror{ |e| e.should.eq nil }
146
+ c.start.wait
147
+ end
148
+
149
+ would 'not deadlock with ErrorHandler' do
150
+ mock_warning
151
+ c = RC::Universal.new(:log_method => false).
152
+ event_source('http://localhost:1')
153
+ c.onerror{ |e| e.should.kind_of?(Errno::ECONNREFUSED) }
154
+ c.start.wait
155
+ end
156
+
157
+ would 'not deadlock if errors in onmessage' do
158
+ err = nil
159
+ es, m, t = server.call
160
+ es.onmessage do |event, data|
161
+ raise err = "error"
162
+ end.start.wait
163
+ err.should.eq "error"
164
+ end
134
165
  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.4.0
4
+ version: 3.4.1
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: 2014-11-26 00:00:00.000000000 Z
11
+ date: 2014-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient