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 +4 -4
- data/CHANGES.md +9 -0
- data/lib/rest-core/event_source.rb +18 -5
- data/lib/rest-core/middleware/error_handler.rb +5 -1
- data/lib/rest-core/promise.rb +23 -8
- data/lib/rest-core/timer.rb +1 -0
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +3 -3
- data/test/test_event_source.rb +31 -0
- 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: 85f12b68843aae98a2ceaa7d85346e0c99627f21
|
4
|
+
data.tar.gz: d8ba6d00b676443be83d939f7b676ad75f96ec0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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)
|
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
|
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
|
data/lib/rest-core/promise.rb
CHANGED
@@ -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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
data/lib/rest-core/timer.rb
CHANGED
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.4.
|
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.
|
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-
|
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 = [
|
data/test/test_event_source.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2014-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|