rest-core 3.6.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +0 -1
  4. data/CHANGES.md +28 -0
  5. data/Gemfile +0 -2
  6. data/README.md +14 -95
  7. data/Rakefile +16 -3
  8. data/example/simple.rb +1 -0
  9. data/example/use-cases.rb +15 -3
  10. data/lib/rest-core.rb +38 -75
  11. data/lib/rest-core/client/universal.rb +3 -1
  12. data/lib/rest-core/client_oauth1.rb +64 -59
  13. data/lib/rest-core/event.rb +9 -11
  14. data/lib/rest-core/middleware/auth_basic.rb +21 -21
  15. data/lib/rest-core/middleware/bypass.rb +8 -8
  16. data/lib/rest-core/middleware/cache.rb +94 -90
  17. data/lib/rest-core/middleware/clash_response.rb +15 -14
  18. data/lib/rest-core/middleware/common_logger.rb +27 -26
  19. data/lib/rest-core/middleware/default_headers.rb +8 -8
  20. data/lib/rest-core/middleware/default_payload.rb +8 -8
  21. data/lib/rest-core/middleware/default_query.rb +8 -8
  22. data/lib/rest-core/middleware/default_site.rb +12 -12
  23. data/lib/rest-core/middleware/defaults.rb +38 -38
  24. data/lib/rest-core/middleware/error_detector.rb +10 -10
  25. data/lib/rest-core/middleware/error_detector_http.rb +6 -4
  26. data/lib/rest-core/middleware/error_handler.rb +14 -14
  27. data/lib/rest-core/middleware/follow_redirect.rb +28 -27
  28. data/lib/rest-core/middleware/json_request.rb +13 -11
  29. data/lib/rest-core/middleware/json_response.rb +29 -28
  30. data/lib/rest-core/middleware/oauth1_header.rb +84 -83
  31. data/lib/rest-core/middleware/oauth2_header.rb +27 -25
  32. data/lib/rest-core/middleware/oauth2_query.rb +15 -15
  33. data/lib/rest-core/middleware/query_response.rb +14 -14
  34. data/lib/rest-core/middleware/retry.rb +25 -23
  35. data/lib/rest-core/middleware/smash_response.rb +15 -14
  36. data/lib/rest-core/middleware/timeout.rb +18 -19
  37. data/lib/rest-core/test.rb +1 -18
  38. data/lib/rest-core/util/clash.rb +38 -37
  39. data/lib/rest-core/util/config.rb +40 -39
  40. data/lib/rest-core/util/dalli_extension.rb +11 -10
  41. data/lib/rest-core/util/hmac.rb +9 -8
  42. data/lib/rest-core/util/json.rb +55 -54
  43. data/lib/rest-core/util/parse_link.rb +13 -12
  44. data/lib/rest-core/util/parse_query.rb +24 -22
  45. data/lib/rest-core/version.rb +1 -1
  46. data/rest-core.gemspec +121 -158
  47. data/test/test_cache.rb +2 -0
  48. data/test/test_default_payload.rb +1 -1
  49. data/test/test_error_handler.rb +5 -4
  50. data/test/test_timeout.rb +9 -8
  51. data/test/test_universal.rb +8 -0
  52. metadata +9 -73
  53. data/lib/rest-core/builder.rb +0 -162
  54. data/lib/rest-core/client.rb +0 -277
  55. data/lib/rest-core/client/simple.rb +0 -2
  56. data/lib/rest-core/engine.rb +0 -36
  57. data/lib/rest-core/engine/dry.rb +0 -9
  58. data/lib/rest-core/engine/http-client.rb +0 -41
  59. data/lib/rest-core/error.rb +0 -5
  60. data/lib/rest-core/event_source.rb +0 -137
  61. data/lib/rest-core/middleware.rb +0 -151
  62. data/lib/rest-core/promise.rb +0 -249
  63. data/lib/rest-core/thread_pool.rb +0 -131
  64. data/lib/rest-core/timer.rb +0 -58
  65. data/lib/rest-core/util/payload.rb +0 -173
  66. data/test/test_builder.rb +0 -40
  67. data/test/test_client.rb +0 -177
  68. data/test/test_event_source.rb +0 -159
  69. data/test/test_future.rb +0 -16
  70. data/test/test_httpclient.rb +0 -118
  71. data/test/test_payload.rb +0 -204
  72. data/test/test_promise.rb +0 -146
  73. data/test/test_simple.rb +0 -38
  74. data/test/test_thread_pool.rb +0 -10
@@ -8,6 +8,7 @@ describe RC::Universal do
8
8
  WebMock.reset!
9
9
  end
10
10
 
11
+ # TODO: RuntimeError: The request GET http://localhost:1/ with body nil was expected to execute 1 time but it executed 2 times
11
12
  would 'only send payload for post, put, patch' do
12
13
  c = RC::Universal.new(:log_method => false, :payload => '$payload')
13
14
  [:get, :delete, :head, :options].each do |method|
@@ -69,4 +70,11 @@ describe RC::Universal do
69
70
  errors.map(&:class).should.eq [Errno::ECONNREFUSED]*2
70
71
  called.map(&:class).should.eq [Errno::ECONNREFUSED]
71
72
  end
73
+
74
+ would 'not deadlock with ErrorHandler' do
75
+ c = RC::Universal.new(:log_method => false).
76
+ event_source('http://localhost:1')
77
+ c.onerror{ |e| e.should.kind_of?(Errno::ECONNREFUSED) }
78
+ c.start.wait
79
+ end
72
80
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 4.0.0
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: 2016-01-27 00:00:00.000000000 Z
11
+ date: 2016-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httpclient
14
+ name: rest-builder
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -24,45 +24,12 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: mime-types
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: timers
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 4.0.1
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 4.0.1
55
27
  description: |-
56
- Modular Ruby clients interface for REST APIs.
57
-
58
- There has been an explosion in the number of REST APIs available today.
59
- To address the need for a way to access these APIs easily and elegantly,
60
- we have developed rest-core, which consists of composable middleware
61
- that allows you to build a REST client for any REST API. Or in the case of
62
- common APIs such as Facebook, Github, and Twitter, you can simply use the
63
- dedicated clients provided by [rest-more][].
28
+ Various [rest-builder](https://github.com/godfat/rest-builder) middleware
29
+ for building REST clients.
64
30
 
65
- [rest-more]: https://github.com/godfat/rest-more
31
+ Checkout [rest-more](https://github.com/godfat/rest-more) for pre-built
32
+ clients.
66
33
  email:
67
34
  - godfat (XD) godfat.org
68
35
  executables: []
@@ -82,18 +49,9 @@ files:
82
49
  - example/simple.rb
83
50
  - example/use-cases.rb
84
51
  - lib/rest-core.rb
85
- - lib/rest-core/builder.rb
86
- - lib/rest-core/client.rb
87
- - lib/rest-core/client/simple.rb
88
52
  - lib/rest-core/client/universal.rb
89
53
  - lib/rest-core/client_oauth1.rb
90
- - lib/rest-core/engine.rb
91
- - lib/rest-core/engine/dry.rb
92
- - lib/rest-core/engine/http-client.rb
93
- - lib/rest-core/error.rb
94
54
  - lib/rest-core/event.rb
95
- - lib/rest-core/event_source.rb
96
- - lib/rest-core/middleware.rb
97
55
  - lib/rest-core/middleware/auth_basic.rb
98
56
  - lib/rest-core/middleware/bypass.rb
99
57
  - lib/rest-core/middleware/cache.rb
@@ -117,10 +75,7 @@ files:
117
75
  - lib/rest-core/middleware/retry.rb
118
76
  - lib/rest-core/middleware/smash_response.rb
119
77
  - lib/rest-core/middleware/timeout.rb
120
- - lib/rest-core/promise.rb
121
78
  - lib/rest-core/test.rb
122
- - lib/rest-core/thread_pool.rb
123
- - lib/rest-core/timer.rb
124
79
  - lib/rest-core/util/clash.rb
125
80
  - lib/rest-core/util/config.rb
126
81
  - lib/rest-core/util/dalli_extension.rb
@@ -128,7 +83,6 @@ files:
128
83
  - lib/rest-core/util/json.rb
129
84
  - lib/rest-core/util/parse_link.rb
130
85
  - lib/rest-core/util/parse_query.rb
131
- - lib/rest-core/util/payload.rb
132
86
  - lib/rest-core/util/smash.rb
133
87
  - lib/rest-core/version.rb
134
88
  - rest-core.gemspec
@@ -136,11 +90,9 @@ files:
136
90
  - task/gemgem.rb
137
91
  - test/config/rest-core.yaml
138
92
  - test/test_auth_basic.rb
139
- - test/test_builder.rb
140
93
  - test/test_cache.rb
141
94
  - test/test_clash.rb
142
95
  - test/test_clash_response.rb
143
- - test/test_client.rb
144
96
  - test/test_client_oauth1.rb
145
97
  - test/test_config.rb
146
98
  - test/test_dalli_extension.rb
@@ -151,23 +103,16 @@ files:
151
103
  - test/test_error_detector.rb
152
104
  - test/test_error_detector_http.rb
153
105
  - test/test_error_handler.rb
154
- - test/test_event_source.rb
155
106
  - test/test_follow_redirect.rb
156
- - test/test_future.rb
157
- - test/test_httpclient.rb
158
107
  - test/test_json_request.rb
159
108
  - test/test_json_response.rb
160
109
  - test/test_oauth1_header.rb
161
110
  - test/test_oauth2_header.rb
162
111
  - test/test_parse_link.rb
163
- - test/test_payload.rb
164
- - test/test_promise.rb
165
112
  - test/test_query_response.rb
166
113
  - test/test_retry.rb
167
- - test/test_simple.rb
168
114
  - test/test_smash.rb
169
115
  - test/test_smash_response.rb
170
- - test/test_thread_pool.rb
171
116
  - test/test_timeout.rb
172
117
  - test/test_universal.rb
173
118
  homepage: https://github.com/godfat/rest-core
@@ -190,17 +135,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
135
  version: '0'
191
136
  requirements: []
192
137
  rubyforge_project:
193
- rubygems_version: 2.5.1
138
+ rubygems_version: 2.5.2
194
139
  signing_key:
195
140
  specification_version: 4
196
- summary: Modular Ruby clients interface for REST APIs.
141
+ summary: Various [rest-builder](https://github.com/godfat/rest-builder) middleware
197
142
  test_files:
198
143
  - test/test_auth_basic.rb
199
- - test/test_builder.rb
200
144
  - test/test_cache.rb
201
145
  - test/test_clash.rb
202
146
  - test/test_clash_response.rb
203
- - test/test_client.rb
204
147
  - test/test_client_oauth1.rb
205
148
  - test/test_config.rb
206
149
  - test/test_dalli_extension.rb
@@ -211,22 +154,15 @@ test_files:
211
154
  - test/test_error_detector.rb
212
155
  - test/test_error_detector_http.rb
213
156
  - test/test_error_handler.rb
214
- - test/test_event_source.rb
215
157
  - test/test_follow_redirect.rb
216
- - test/test_future.rb
217
- - test/test_httpclient.rb
218
158
  - test/test_json_request.rb
219
159
  - test/test_json_response.rb
220
160
  - test/test_oauth1_header.rb
221
161
  - test/test_oauth2_header.rb
222
162
  - test/test_parse_link.rb
223
- - test/test_payload.rb
224
- - test/test_promise.rb
225
163
  - test/test_query_response.rb
226
164
  - test/test_retry.rb
227
- - test/test_simple.rb
228
165
  - test/test_smash.rb
229
166
  - test/test_smash_response.rb
230
- - test/test_thread_pool.rb
231
167
  - test/test_timeout.rb
232
168
  - test/test_universal.rb
@@ -1,162 +0,0 @@
1
-
2
- require 'thread'
3
- require 'weakref'
4
- require 'rest-core/client'
5
-
6
- class RestCore::Builder
7
- include RestCore
8
-
9
- singleton_class.module_eval do
10
- attr_writer :default_engine
11
- def default_engine
12
- @default_engine ||= RestCore::HttpClient
13
- end
14
-
15
- def client *attrs, &block
16
- new(&block).to_client(*attrs)
17
- end
18
- end
19
-
20
- def initialize &block
21
- @engine = nil
22
- @middles ||= []
23
- instance_eval(&block) if block_given?
24
- end
25
-
26
- attr_reader :middles
27
- attr_writer :default_engine
28
- def default_engine
29
- @default_engine ||= self.class.default_engine
30
- end
31
-
32
- def use middle, *args, &block
33
- middles << [middle, args, block]
34
- end
35
-
36
- def run engine
37
- @engine = engine
38
- end
39
-
40
- def members
41
- middles.map{ |(middle, _, _)|
42
- middle.members if middle.respond_to?(:members)
43
- }.flatten.compact
44
- end
45
-
46
- def to_app engine=@engine || default_engine
47
- # === foldr m.new app middles
48
- middles.reverse.inject(engine.new){ |app, (middle, args, block)|
49
- begin
50
- middle.new(app, *partial_deep_copy(args), &block)
51
- rescue ArgumentError => e
52
- raise ArgumentError.new("#{middle}: #{e}")
53
- end
54
- }
55
- end
56
-
57
- def to_client *attrs
58
- fields = (members + attrs + [:config_engine]).uniq
59
- struct = build_struct(fields)
60
- client = Class.new(struct)
61
- client.const_set('Struct', struct)
62
- class_methods = build_class_methods
63
- client.const_set('ClassMethods', class_methods)
64
- client.singleton_class.send(:include, class_methods)
65
- client.send(:include, Client)
66
- client.builder = self
67
- client.pool_size = 0 # default to no pool
68
- client.pool_idle_time = 60 # default to 60 seconds
69
- client.event_source_class = EventSource
70
- client.promises = []
71
- client.mutex = Mutex.new
72
- client
73
- end
74
-
75
- private
76
- def partial_deep_copy obj
77
- case obj
78
- when Array; obj.map{ |o| partial_deep_copy(o) }
79
- when Hash ; obj.inject({}){ |r, (k, v)| r[k] = partial_deep_copy(v); r }
80
- else ; obj
81
- end
82
- end
83
-
84
- def build_struct fields
85
- if fields.empty?
86
- Struct.new(nil)
87
- else
88
- Struct.new(*fields.uniq)
89
- end
90
- end
91
-
92
- def build_class_methods
93
- Module.new do
94
- attr_accessor :builder, :pool_size, :pool_idle_time,
95
- :event_source_class, :promises, :mutex
96
-
97
- def inherited sub
98
- sub.builder = builder
99
- sub.pool_size = pool_size
100
- sub.pool_idle_time = pool_idle_time
101
- sub.event_source_class = event_source_class
102
- sub.promises = []
103
- sub.mutex = Mutex.new
104
- end
105
-
106
- def thread_pool; RestCore::ThreadPool[self]; end
107
-
108
- def defer returns=:future_body
109
- raise ArgumentError.new('no block given') unless block_given?
110
- promise = RestCore::Promise.new({RestCore::CLIENT => self},
111
- lambda{ |res|
112
- if err = res[FAIL].find{ |f| f.kind_of?(Exception) }
113
- Promise.set_backtrace(err) unless err.backtrace
114
- raise err
115
- else
116
- res
117
- end
118
- })
119
- give_promise(WeakRef.new(promise))
120
- promise.defer do
121
- begin
122
- promise.done(yield)
123
- rescue => e
124
- promise.reject(e)
125
- end
126
- end
127
- promise.send(returns)
128
- end
129
-
130
- def give_promise weak_promise, ps=promises, m=mutex
131
- m.synchronize do
132
- ps << weak_promise
133
- ps.keep_if(&:weakref_alive?)
134
- end
135
- end
136
-
137
- # Shutdown the thread pool for this client and wait for all requests
138
- def shutdown
139
- thread_pool.shutdown
140
- wait
141
- end
142
-
143
- # Wait for all the requests to be done for this client
144
- def wait ps=promises, m=mutex
145
- return self if ps.empty?
146
- current_promises = nil
147
- m.synchronize do
148
- current_promises = ps.dup
149
- ps.clear
150
- end
151
- current_promises.each do |p|
152
- next unless p.weakref_alive?
153
- begin
154
- p.wait
155
- rescue WeakRef::RefError # it's gc'ed after we think it's alive
156
- end
157
- end
158
- wait(ps, m)
159
- end
160
- end
161
- end
162
- end
@@ -1,277 +0,0 @@
1
-
2
- require 'thread'
3
- require 'weakref'
4
- require 'rest-core'
5
-
6
- module RestCore::Client
7
- include RestCore
8
-
9
- Unserializable = [Proc, Method, IO]
10
-
11
- def self.included mod
12
- # honor default attributes
13
- src = mod.members.map{ |name|
14
- <<-RUBY
15
- def #{name}
16
- if (r = super).nil?
17
- self.#{name} = default_#{name}
18
- else
19
- r
20
- end
21
- end
22
-
23
- def default_#{name} a=app
24
- if self.class.respond_to?("default_#{name}")
25
- self.class.default_#{name} # old class default style
26
- elsif a.respond_to?(:#{name})
27
- a.#{name}({}) # middleware instance value
28
- elsif a.respond_to?(:app)
29
- default_#{name}(a.app) # walk into next app
30
- else
31
- nil
32
- end
33
- end
34
- private :default_#{name}
35
- RUBY
36
- }
37
- accessor = Module.new
38
- accessor.module_eval(src.join("\n"), __FILE__, __LINE__)
39
- mod.const_set('Accessor', accessor)
40
- mod.send(:include, accessor)
41
- end
42
-
43
- attr_reader :app, :dry, :promises
44
- attr_accessor :error_callback
45
- def initialize o={}
46
- @app ||= self.class.builder.to_app # lighten! would reinitialize anyway
47
- @dry ||= self.class.builder.to_app(Dry)
48
- @promises = [] # don't record any promises in lighten!
49
- @mutex = nil # for locking promises, lazily initialized
50
- # for serialization
51
- @error_callback = nil
52
- o.each{ |key, value| send("#{key}=", value) if respond_to?("#{key}=") }
53
- end
54
-
55
- def attributes
56
- Hash[each_pair.map{ |k, v| [k, send(k)] }]
57
- end
58
-
59
- def inspect
60
- fields = if size > 0
61
- ' ' + attributes.map{ |k, v|
62
- "#{k}=#{v.inspect.sub(/(?<=.{12}).{4,}/, '...')}"
63
- }.join(', ')
64
- else
65
- ''
66
- end
67
- "#<struct #{self.class.name}#{fields}>"
68
- end
69
-
70
- def lighten! o={}
71
- attributes.each{ |k, v| vv = case v;
72
- when Hash; lighten_hash(v)
73
- when Array; lighten_array(v)
74
- when *Unserializable; nil
75
- else v
76
- end
77
- send("#{k}=", vv)}
78
- initialize(o)
79
- @app, @dry = lighten_app(app), lighten_app(dry)
80
- self
81
- end
82
-
83
- def lighten o={}
84
- dup.lighten!(o)
85
- end
86
-
87
- def wait
88
- self.class.wait(promises, mutex)
89
- self
90
- end
91
-
92
- def url path, query={}, opts={}
93
- dry.call(build_env({
94
- REQUEST_PATH => path,
95
- REQUEST_QUERY => query,
96
- DRY => true}.merge(opts)), &Middleware.method(:request_uri))
97
- end
98
-
99
- def get path, query={}, opts={}, &cb
100
- request(
101
- {REQUEST_METHOD => :get ,
102
- REQUEST_PATH => path ,
103
- REQUEST_QUERY => query }.merge(opts), &cb)
104
- end
105
-
106
- def delete path, query={}, opts={}, &cb
107
- request(
108
- {REQUEST_METHOD => :delete,
109
- REQUEST_PATH => path ,
110
- REQUEST_QUERY => query }.merge(opts), &cb)
111
- end
112
-
113
- def head path, query={}, opts={}, &cb
114
- request(
115
- {REQUEST_METHOD => :head ,
116
- REQUEST_PATH => path ,
117
- REQUEST_QUERY => query ,
118
- RESPONSE_KEY => RESPONSE_HEADERS}.merge(opts), &cb)
119
- end
120
-
121
- def options path, query={}, opts={}, &cb
122
- request(
123
- {REQUEST_METHOD => :options,
124
- REQUEST_PATH => path ,
125
- REQUEST_QUERY => query ,
126
- RESPONSE_KEY => RESPONSE_HEADERS}.merge(opts), &cb)
127
- end
128
-
129
- def post path, payload={}, query={}, opts={}, &cb
130
- request(
131
- {REQUEST_METHOD => :post ,
132
- REQUEST_PATH => path ,
133
- REQUEST_QUERY => query ,
134
- REQUEST_PAYLOAD => payload}.merge(opts), &cb)
135
- end
136
-
137
- def put path, payload={}, query={}, opts={}, &cb
138
- request(
139
- {REQUEST_METHOD => :put ,
140
- REQUEST_PATH => path ,
141
- REQUEST_QUERY => query ,
142
- REQUEST_PAYLOAD => payload}.merge(opts), &cb)
143
- end
144
-
145
- def patch path, payload={}, query={}, opts={}, &cb
146
- request(
147
- {REQUEST_METHOD => :patch ,
148
- REQUEST_PATH => path ,
149
- REQUEST_QUERY => query ,
150
- REQUEST_PAYLOAD => payload}.merge(opts), &cb)
151
- end
152
-
153
- def event_source path, query={}, opts={}
154
- self.class.event_source_class.new(self, path, query, opts)
155
- end
156
-
157
- def request env, a=app
158
- if block_given?
159
- request_full(env, a){ |response| yield(response[response_key(env)]) }
160
- else
161
- request_full(env, a)[response_key(env)]
162
- end
163
- end
164
-
165
- def request_full env, a=app, &k
166
- response = a.call(build_env({ASYNC => !!k}.merge(env))) do |res|
167
- (k || RC.id).call(request_complete(res))
168
- end
169
-
170
- give_promise(response)
171
-
172
- if block_given?
173
- self
174
- else
175
- response
176
- end
177
- end
178
-
179
- def give_promise response
180
- # under ASYNC callback, response might not be a response hash
181
- # in that case (maybe in a user created engine), Client#wait
182
- # won't work because we have no way to track the promise.
183
- if response.kind_of?(Hash) && response[PROMISE].kind_of?(Promise)
184
- weak_promise = WeakRef.new(response[PROMISE])
185
- self.class.give_promise(weak_promise)
186
- self.class.give_promise(weak_promise, promises, mutex)
187
- end
188
-
189
- response
190
- end
191
-
192
- def build_env env={}
193
- default_env.merge(
194
- Middleware.string_keys(attributes).merge(Middleware.string_keys(env)))
195
- end
196
-
197
- def default_env
198
- {REQUEST_METHOD => :get,
199
- REQUEST_PATH => '/' ,
200
- REQUEST_QUERY => {} ,
201
- REQUEST_PAYLOAD => {} ,
202
- REQUEST_HEADERS => {} ,
203
- FAIL => [] ,
204
- LOG => [] ,
205
- CLIENT => self}
206
- end
207
- # ------------------------ instance ---------------------
208
-
209
-
210
-
211
- private
212
- def request_complete res
213
- if err = res[FAIL].find{ |f| f.kind_of?(Exception) }
214
- Promise.set_backtrace(err) unless err.backtrace
215
- error_callback.call(err) if error_callback
216
- if res[ASYNC]
217
- res.merge(response_key(res) => err)
218
- else
219
- raise err
220
- end
221
- else
222
- res
223
- end
224
- end
225
-
226
- def mutex
227
- @mutex ||= Mutex.new
228
- end
229
-
230
- def response_key opts
231
- opts[RESPONSE_KEY] ||
232
- if opts[HIJACK] then RESPONSE_SOCKET else RESPONSE_BODY end
233
- end
234
-
235
- def lighten_hash hash
236
- Hash[hash.map{ |(key, value)|
237
- case value
238
- when Hash; lighten_hash(value)
239
- when Array; lighten_array(value)
240
- when *Unserializable; [key, nil]
241
- else [key, value]
242
- end
243
- }]
244
- end
245
-
246
- def lighten_array array
247
- array.map{ |value|
248
- case value
249
- when Hash; lighten_hash(value)
250
- when Array; lighten_array(value)
251
- when *Unserializable; nil
252
- else value
253
- end
254
- }.compact
255
- end
256
-
257
- def lighten_app app
258
- members = if app.class.respond_to?(:members)
259
- app.class.members.map{ |key|
260
- case value = app.send(key, {})
261
- when Hash; lighten_hash(value)
262
- when Array; lighten_array(value)
263
- when *Unserializable; nil
264
- else value
265
- end
266
- }
267
- else
268
- []
269
- end
270
-
271
- if app.respond_to?(:app) && app.app
272
- app.class.new(lighten_app(app.app), *members)
273
- else
274
- app.class.new(*members)
275
- end
276
- end
277
- end