rest-core 3.5.4 → 3.5.5
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/.travis.yml +0 -1
- data/CHANGES.md +6 -0
- data/Gemfile +1 -0
- data/README.md +64 -5
- data/TODO.md +5 -6
- data/lib/rest-core/builder.rb +1 -1
- data/lib/rest-core/engine.rb +1 -0
- data/lib/rest-core/engine/http-client.rb +1 -0
- data/lib/rest-core/middleware/json_response.rb +9 -4
- data/lib/rest-core/thread_pool.rb +32 -27
- data/lib/rest-core/util/json.rb +1 -0
- data/lib/rest-core/util/payload.rb +5 -1
- data/lib/rest-core/version.rb +1 -1
- data/rest-core.gemspec +4 -4
- data/task/gemgem.rb +6 -2
- data/test/test_builder.rb +1 -1
- data/test/test_default_payload.rb +12 -8
- data/test/test_error_handler.rb +3 -3
- data/test/test_httpclient.rb +72 -1
- data/test/test_thread_pool.rb +28 -4
- data/test/test_timeout.rb +12 -12
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02a017ca6ef776af782e4e7c575858b0cb8f3703
|
4
|
+
data.tar.gz: 8d29c4f87749dccb787c0134f6938a95fe57b733
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d6aad0bedad2f4b7a72a78ec984721515157508d20983425eb2f0354fad6cd092beaaa4d626ae4f1000339d248535d83b9b1da8568afe13adcdb5cf5064fe07
|
7
|
+
data.tar.gz: 2b75fccd0ba262c7f8915217cd142dbcc85f49497a2fe7b40b5d84b3818b74dea0b0982ba8ab601fa6a044c83e346054edd7beab24a56f67766a5c688ad61942
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
@@ -25,6 +25,7 @@ end
|
|
25
25
|
|
26
26
|
platforms :rbx do
|
27
27
|
gem 'rubysl-weakref' # used in rest-core
|
28
|
+
gem 'rubysl-socket' # used in test
|
28
29
|
gem 'rubysl-singleton' # used in rake
|
29
30
|
gem 'rubysl-rexml' # used in crack used in webmock
|
30
31
|
gem 'rubysl-bigdecimal' # used in crack used in webmock
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# rest-core [](http://travis-ci.org/godfat/rest-core) [](https://coveralls.io/r/godfat/rest-core)
|
1
|
+
# rest-core [](http://travis-ci.org/godfat/rest-core) [](https://coveralls.io/r/godfat/rest-core) [](https://gitter.im/godfat/rest-core)
|
2
2
|
|
3
3
|
by Lin Jen-Shin ([godfat](http://godfat.org))
|
4
4
|
|
@@ -301,8 +301,9 @@ Not only JavaScript could receive server-sent events, any languages could.
|
|
301
301
|
Doing so would establish a keep-alive connection to the server, and receive
|
302
302
|
data periodically. We'll take Firebase as an example:
|
303
303
|
|
304
|
-
If you are using Firebase, please consider
|
305
|
-
|
304
|
+
If you are using Firebase, please consider [rest-firebase][] instead.
|
305
|
+
|
306
|
+
[rest-firebase]: https://github.com/CodementorIO/rest-firebase
|
306
307
|
|
307
308
|
``` ruby
|
308
309
|
require 'rest-core'
|
@@ -685,9 +686,67 @@ and complete.
|
|
685
686
|
|
686
687
|
[example/use-cases.rb]: example/use-cases.rb
|
687
688
|
|
689
|
+
## Configure the underlying HTTP engine
|
690
|
+
|
691
|
+
Occasionally we might want to configure the underlying HTTP engine, which
|
692
|
+
for now is [httpclient][]. For example, we might not want to decompress
|
693
|
+
gzip automatically, (rest-core configures httpclient to request and
|
694
|
+
decompress gzip automatically). or we might want to skip verifying SSL
|
695
|
+
in some situation. (e.g. making requests against a self-signed testing server)
|
696
|
+
|
697
|
+
In such cases, we could use `config_engine` option to configure the underlying
|
698
|
+
engine. This could be set with request based, client instance based, or
|
699
|
+
client class based. Please refer to:
|
700
|
+
[How We Pick the Default Value](#how-we-pick-the-default-value),
|
701
|
+
except that there's no middleware for `config_engine`.
|
702
|
+
|
703
|
+
Here are some examples:
|
704
|
+
|
705
|
+
``` ruby
|
706
|
+
require 'rest-core'
|
707
|
+
YourClient = RC::Builder.client
|
708
|
+
|
709
|
+
# class based:
|
710
|
+
def YourClient.default_config_engine
|
711
|
+
lambda do |engine|
|
712
|
+
# disable auto-gzip:
|
713
|
+
engine.transparent_gzip_decompression = false
|
714
|
+
|
715
|
+
# disable verifying SSL
|
716
|
+
engine.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
# instance based:
|
721
|
+
client = YourClient.new(:config_engine => lambda do |engine|
|
722
|
+
# disable auto-gzip:
|
723
|
+
engine.transparent_gzip_decompression = false
|
724
|
+
|
725
|
+
# disable verifying SSL
|
726
|
+
engine.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
727
|
+
end)
|
728
|
+
|
729
|
+
# request based:
|
730
|
+
client.get('http://example.com/', {}, :config_engine => lambda do |engine|
|
731
|
+
# disable auto-gzip:
|
732
|
+
engine.transparent_gzip_decompression = false
|
733
|
+
|
734
|
+
# disable verifying SSL
|
735
|
+
engine.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
736
|
+
end)
|
737
|
+
```
|
738
|
+
|
739
|
+
As we stated in
|
740
|
+
[How We Pick the Default Value](#how-we-pick-the-default-value),
|
741
|
+
the priority here is:
|
742
|
+
|
743
|
+
0. request based
|
744
|
+
0. instance based
|
745
|
+
0. class based
|
746
|
+
|
688
747
|
## rest-core users:
|
689
748
|
|
690
|
-
* [rest-firebase]
|
749
|
+
* [rest-firebase][]
|
691
750
|
* [rest-more][]
|
692
751
|
* [rest-more-yahoo_buy](https://github.com/GoodLife/rest-more-yahoo_buy)
|
693
752
|
* [s2sync](https://github.com/brucehsu/s2sync)
|
@@ -727,7 +786,7 @@ and complete.
|
|
727
786
|
|
728
787
|
Apache License 2.0
|
729
788
|
|
730
|
-
Copyright (c) 2011-
|
789
|
+
Copyright (c) 2011-2015, Lin Jen-Shin (godfat)
|
731
790
|
|
732
791
|
Licensed under the Apache License, Version 2.0 (the "License");
|
733
792
|
you may not use this file except in compliance with the License.
|
data/TODO.md
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
# TODO
|
2
2
|
|
3
|
-
|
4
|
-
* X-Method-Override
|
3
|
+
# NEAR FUTURE
|
5
4
|
|
6
|
-
|
5
|
+
* revisit error_callback (use middleware)
|
6
|
+
* ActiveRecord::ConnectionAdapters::ConnectionManagement
|
7
|
+
|
8
|
+
# FAR FUTURE
|
7
9
|
|
8
10
|
* middleware composer
|
9
11
|
* headers and payload logs for CommonLogger
|
10
|
-
|
11
|
-
# rest-request
|
12
|
-
|
13
12
|
* fix DRY by defining `prepare :: env -> env`
|
14
13
|
* FAIL and LOG need to be reimplemented as well.
|
data/lib/rest-core/builder.rb
CHANGED
data/lib/rest-core/engine.rb
CHANGED
@@ -9,6 +9,7 @@ class RestCore::HttpClient < RestCore::Engine
|
|
9
9
|
client.cookie_manager = nil
|
10
10
|
client.follow_redirect_count = 0
|
11
11
|
client.transparent_gzip_decompression = true
|
12
|
+
config = config_engine(env) and config.call(client)
|
12
13
|
payload, headers = payload_and_headers(env)
|
13
14
|
|
14
15
|
if env[HIJACK]
|
@@ -28,11 +28,16 @@ class RestCore::JsonResponse
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def process response
|
31
|
-
# StackExchange returns the problematic BOM! in UTF-8, so we need to
|
32
|
-
# strip it or it would break JSON parsers (i.e. yajl-ruby and json)
|
33
31
|
body = response[RESPONSE_BODY].to_s.sub(/\A\xEF\xBB\xBF/, '')
|
34
|
-
response
|
35
|
-
|
32
|
+
if response[HIJACK] && Json.respond_to?(:decode_from_io)
|
33
|
+
response.merge(
|
34
|
+
RESPONSE_SOCKET => Json.decode_from_io(response[RESPONSE_SOCKET]))
|
35
|
+
else
|
36
|
+
# StackExchange returns the problematic BOM! in UTF-8, so we need to
|
37
|
+
# strip it or it would break JSON parsers (i.e. yajl-ruby and json)
|
38
|
+
response.merge(RESPONSE_BODY => Json.decode("[#{body}]").first)
|
39
|
+
# [this].first is not needed for yajl-ruby
|
40
|
+
end
|
36
41
|
rescue Json.const_get(:ParseError) => error
|
37
42
|
fail(response, ParseError.new(error, body))
|
38
43
|
end
|
@@ -11,25 +11,24 @@ class RestCore::ThreadPool
|
|
11
11
|
class Queue
|
12
12
|
def initialize
|
13
13
|
@queue = []
|
14
|
-
@mutex = Mutex.new
|
15
14
|
@condv = ConditionVariable.new
|
16
15
|
end
|
17
16
|
|
17
|
+
def size
|
18
|
+
@queue.size
|
19
|
+
end
|
20
|
+
|
18
21
|
def << task
|
19
|
-
|
20
|
-
|
21
|
-
condv.signal
|
22
|
-
end
|
22
|
+
queue << task
|
23
|
+
condv.signal
|
23
24
|
end
|
24
25
|
|
25
|
-
def pop timeout=60
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
queue.shift
|
32
|
-
end
|
26
|
+
def pop mutex, timeout=60
|
27
|
+
if queue.empty?
|
28
|
+
condv.wait(mutex, timeout)
|
29
|
+
queue.shift || lambda{ |_| false } # shutdown idle workers
|
30
|
+
else
|
31
|
+
queue.shift
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
@@ -38,7 +37,7 @@ class RestCore::ThreadPool
|
|
38
37
|
end
|
39
38
|
|
40
39
|
protected
|
41
|
-
attr_reader :queue, :
|
40
|
+
attr_reader :queue, :condv
|
42
41
|
end
|
43
42
|
|
44
43
|
class Task < Struct.new(:job, :mutex, :thread, :cancelled)
|
@@ -61,7 +60,7 @@ class RestCore::ThreadPool
|
|
61
60
|
(@pools ||= {})[client_class] ||= new(client_class)
|
62
61
|
end
|
63
62
|
|
64
|
-
attr_reader :client_class
|
63
|
+
attr_reader :client_class, :workers
|
65
64
|
|
66
65
|
def initialize client_class
|
67
66
|
@client_class = client_class
|
@@ -87,37 +86,43 @@ class RestCore::ThreadPool
|
|
87
86
|
client_class.pool_idle_time
|
88
87
|
end
|
89
88
|
|
90
|
-
def defer
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
def defer promise_mutex, &job
|
90
|
+
mutex.synchronize do
|
91
|
+
task = Task.new(job, promise_mutex)
|
92
|
+
queue << task
|
93
|
+
spawn_worker if waiting < queue.size && workers.size < max_size
|
94
|
+
task
|
95
|
+
end
|
95
96
|
end
|
96
97
|
|
97
98
|
def trim force=false
|
98
|
-
|
99
|
+
mutex.synchronize do
|
100
|
+
queue << lambda{ |_| false } if force || waiting > 0
|
101
|
+
end
|
99
102
|
end
|
100
103
|
|
101
104
|
# Block on shutting down, and should not add more jobs while shutting down
|
102
105
|
def shutdown
|
103
106
|
workers.size.times{ trim(true) }
|
104
107
|
workers.first.join && trim(true) until workers.empty?
|
105
|
-
queue.clear
|
108
|
+
mutex.synchronize{ queue.clear }
|
106
109
|
end
|
107
110
|
|
108
111
|
protected
|
109
|
-
attr_reader :queue, :mutex, :condv, :
|
112
|
+
attr_reader :queue, :mutex, :condv, :waiting
|
110
113
|
|
111
114
|
private
|
112
115
|
def spawn_worker
|
113
116
|
workers << Thread.new{
|
114
|
-
Thread.current.abort_on_exception =
|
117
|
+
Thread.current.abort_on_exception = true
|
115
118
|
|
116
119
|
task = nil
|
117
120
|
begin
|
118
|
-
mutex.synchronize
|
119
|
-
|
120
|
-
|
121
|
+
mutex.synchronize do
|
122
|
+
@waiting += 1
|
123
|
+
task = queue.pop(mutex, idle_time)
|
124
|
+
@waiting -= 1
|
125
|
+
end
|
121
126
|
end while task.call(Thread.current)
|
122
127
|
|
123
128
|
mutex.synchronize{ workers.delete(Thread.current) }
|
data/lib/rest-core/util/json.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.5.
|
2
|
+
# stub: rest-core 3.5.5 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.5"
|
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-
|
11
|
+
s.date = "2015-07-22"
|
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 = [
|
@@ -113,7 +113,7 @@ Gem::Specification.new do |s|
|
|
113
113
|
"test/test_universal.rb"]
|
114
114
|
s.homepage = "https://github.com/godfat/rest-core"
|
115
115
|
s.licenses = ["Apache License 2.0"]
|
116
|
-
s.rubygems_version = "2.4.
|
116
|
+
s.rubygems_version = "2.4.8"
|
117
117
|
s.summary = "Modular Ruby clients interface for REST APIs."
|
118
118
|
s.test_files = [
|
119
119
|
"test/test_auth_basic.rb",
|
data/task/gemgem.rb
CHANGED
@@ -100,8 +100,12 @@ module Gemgem
|
|
100
100
|
if ENV['COV'] || ENV['CI']
|
101
101
|
require 'simplecov'
|
102
102
|
if ENV['CI']
|
103
|
-
|
104
|
-
|
103
|
+
begin
|
104
|
+
require 'coveralls'
|
105
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
106
|
+
rescue LoadError => e
|
107
|
+
puts "Cannot load coveralls, skip: #{e}"
|
108
|
+
end
|
105
109
|
end
|
106
110
|
SimpleCov.start do
|
107
111
|
add_filter('test/')
|
data/test/test_builder.rb
CHANGED
@@ -25,7 +25,7 @@ describe RC::Builder do
|
|
25
25
|
would 'accept middleware without a member' do
|
26
26
|
RC::Builder.client{
|
27
27
|
use Class.new.send(:include, RC::Middleware)
|
28
|
-
}.members.should.eq []
|
28
|
+
}.members.should.eq [:config_engine]
|
29
29
|
end
|
30
30
|
|
31
31
|
would 'not have duplicated fields' do
|
@@ -5,6 +5,10 @@ describe RC::DefaultPayload do
|
|
5
5
|
app = RC::DefaultPayload.new(RC::Dry.new, {})
|
6
6
|
env = {RC::REQUEST_PAYLOAD => {}}
|
7
7
|
|
8
|
+
before do
|
9
|
+
app.instance_eval{@payload = {}}
|
10
|
+
end
|
11
|
+
|
8
12
|
would 'do nothing' do
|
9
13
|
app.call(env){ |r| r[RC::REQUEST_PAYLOAD].should.eq({}) }
|
10
14
|
end
|
@@ -16,9 +20,9 @@ describe RC::DefaultPayload do
|
|
16
20
|
{'pay' => 'load'}}) }
|
17
21
|
|
18
22
|
format = {'format' => 'json'}
|
19
|
-
|
23
|
+
e = {RC::REQUEST_PAYLOAD => format}
|
20
24
|
|
21
|
-
app.call(
|
25
|
+
app.call(e){ |r| r.should.eq({RC::REQUEST_PAYLOAD =>
|
22
26
|
{'pay' => 'load'}.merge(format)})}
|
23
27
|
end
|
24
28
|
|
@@ -32,15 +36,15 @@ describe RC::DefaultPayload do
|
|
32
36
|
|
33
37
|
would 'accept non-hash payload' do
|
34
38
|
u = RC::Universal.new(:log_method => false)
|
35
|
-
|
36
|
-
u.request_full(
|
39
|
+
e = {RC::REQUEST_PAYLOAD => 'payload'}
|
40
|
+
u.request_full(e, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
37
41
|
|
38
42
|
u.payload = 'default'
|
39
|
-
u.request_full(
|
40
|
-
u.request_full({}
|
43
|
+
u.request_full( e, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
44
|
+
u.request_full({}, u.dry)[RC::REQUEST_PAYLOAD].should.eq('default')
|
41
45
|
|
42
46
|
u = RC::Builder.client{use RC::DefaultPayload, 'maylord'}.new
|
43
|
-
u.request_full({}
|
44
|
-
u.request_full(
|
47
|
+
u.request_full({}, u.dry)[RC::REQUEST_PAYLOAD].should.eq('maylord')
|
48
|
+
u.request_full( e, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
|
45
49
|
end
|
46
50
|
end
|
data/test/test_error_handler.rb
CHANGED
@@ -44,17 +44,17 @@ describe RC::ErrorHandler do
|
|
44
44
|
|
45
45
|
would 'set full backtrace' do
|
46
46
|
url = 'http://example.com/'
|
47
|
-
|
47
|
+
c = RC::Builder.client do
|
48
48
|
use RC::ErrorHandler, lambda{ |env|
|
49
49
|
RuntimeError.new(env[RC::RESPONSE_BODY]) }
|
50
50
|
use RC::ErrorDetectorHttp
|
51
51
|
end.new
|
52
52
|
stub_request(:get, url).to_return(:status => 404, :body => 'nnf')
|
53
|
-
|
53
|
+
c.get(url) do |error|
|
54
54
|
error.message.should.eq 'nnf'
|
55
55
|
error.backtrace.grep(/^#{__FILE__}/).should.not.empty?
|
56
56
|
end
|
57
|
-
|
57
|
+
c.wait
|
58
58
|
end
|
59
59
|
|
60
60
|
would 'not call error_handler if there is already an exception' do
|
data/test/test_httpclient.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
|
2
2
|
require 'rest-core/test'
|
3
3
|
|
4
|
+
require 'openssl'
|
5
|
+
require 'socket'
|
6
|
+
require 'zlib'
|
7
|
+
|
4
8
|
describe RC::HttpClient do
|
5
9
|
describe 'POST Payload' do
|
6
10
|
after do
|
@@ -8,7 +12,6 @@ describe RC::HttpClient do
|
|
8
12
|
end
|
9
13
|
|
10
14
|
client = RC::Builder.client
|
11
|
-
client.builder.run(RC::HttpClient)
|
12
15
|
path = 'http://example.com'
|
13
16
|
ok = 'OK'
|
14
17
|
c = client.new
|
@@ -43,5 +46,73 @@ describe RC::HttpClient do
|
|
43
46
|
c.request(RC::ASYNC => true).message.should.eq 'boom'
|
44
47
|
Muack.verify
|
45
48
|
end
|
49
|
+
|
50
|
+
def accept body
|
51
|
+
server = TCPServer.new(0)
|
52
|
+
t = Thread.new do
|
53
|
+
client = server.accept
|
54
|
+
client.write(<<-HTTP)
|
55
|
+
HTTP/1.0 200 OK\r
|
56
|
+
Connection: close\r
|
57
|
+
Content-Encoding: deflate\r
|
58
|
+
\r
|
59
|
+
#{body}\r
|
60
|
+
HTTP
|
61
|
+
client.close_write
|
62
|
+
end
|
63
|
+
|
64
|
+
yield("http://localhost:#{server.local_address.ip_port}")
|
65
|
+
|
66
|
+
t.join
|
67
|
+
end
|
68
|
+
|
69
|
+
would 'accept deflate' do
|
70
|
+
accept(Zlib::Deflate.deflate(ok)) do |site|
|
71
|
+
c.post(site, 'body').should.eq ok
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
config_engine = lambda do |engine|
|
76
|
+
engine.transparent_gzip_decompression = false
|
77
|
+
engine.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
78
|
+
end
|
79
|
+
|
80
|
+
define_method(:define_default_config_engine) do |d|
|
81
|
+
d.singleton_class.module_eval do
|
82
|
+
define_method(:default_config_engine) do
|
83
|
+
config_engine
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
would 'disable auto-deflate' do
|
89
|
+
accept(ok) do |site|
|
90
|
+
c.post(site, 'body', {}, :config_engine => config_engine).
|
91
|
+
chomp.should.eq ok
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
would 'disable auto-deflate with class default_config_engine' do
|
96
|
+
accept(ok) do |site|
|
97
|
+
d = RC::Builder.client
|
98
|
+
define_default_config_engine(d)
|
99
|
+
d.new.post(site, 'body').chomp.should.eq ok
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
would 'disable auto-deflate with instance default_config_engine' do
|
104
|
+
accept(ok) do |site|
|
105
|
+
d = RC::Builder.client.new
|
106
|
+
define_default_config_engine(d)
|
107
|
+
d.post(site, 'body').chomp.should.eq ok
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
would 'disable auto-deflate with setting config_engine' do
|
112
|
+
accept(ok) do |site|
|
113
|
+
d = RC::Builder.client.new(:config_engine => config_engine)
|
114
|
+
d.post(site, 'body').chomp.should.eq ok
|
115
|
+
end
|
116
|
+
end
|
46
117
|
end
|
47
118
|
end
|
data/test/test_thread_pool.rb
CHANGED
@@ -2,9 +2,33 @@
|
|
2
2
|
require 'rest-core/test'
|
3
3
|
|
4
4
|
describe RC::ThreadPool do
|
5
|
-
would 'have the same pool for the same client' do
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# would 'have the same pool for the same client' do
|
6
|
+
# client = RC::Builder.client
|
7
|
+
# pool = RC::ThreadPool[client]
|
8
|
+
# RC::ThreadPool[client].object_id.should.eq pool.object_id
|
9
|
+
# end
|
10
|
+
|
11
|
+
would 'not waiting forever' do
|
12
|
+
mutex = Mutex.new
|
13
|
+
condv = ConditionVariable.new
|
14
|
+
klass = Struct.new(:pool_size, :pool_idle_time).new(2, 10)
|
15
|
+
pool = RC::ThreadPool[klass]
|
16
|
+
pool.defer(mutex){mutex.synchronize{ condv.signal }} # populate one worker
|
17
|
+
mutex.synchronize{ condv.wait(mutex) }
|
18
|
+
called = []
|
19
|
+
pool.defer(mutex) do
|
20
|
+
sleep 1
|
21
|
+
called << 0
|
22
|
+
end
|
23
|
+
pool.defer(mutex) do
|
24
|
+
sleep 1
|
25
|
+
called << 0
|
26
|
+
pool.defer(mutex) do
|
27
|
+
called << 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
sleep 5
|
31
|
+
p called
|
32
|
+
ok
|
9
33
|
end
|
10
34
|
end
|
data/test/test_timeout.rb
CHANGED
@@ -23,7 +23,7 @@ describe RC::Timeout do
|
|
23
23
|
|
24
24
|
would "not raise timeout error if there's already an error" do
|
25
25
|
env = {'timeout' => 0.01}
|
26
|
-
mock(app.app).call(
|
26
|
+
mock(app.app).call(having(env)){ raise "error" }
|
27
27
|
lambda{ app.call(env){} }.should .raise(RuntimeError)
|
28
28
|
lambda{ sleep 0.01 }.should.not.raise(Timeout::Error)
|
29
29
|
end
|
@@ -51,21 +51,21 @@ describe RC::Timeout do
|
|
51
51
|
|
52
52
|
would 'cancel the task if timing out for thread pool' do
|
53
53
|
timer = fake_timer
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
a = sleeping_app
|
55
|
+
a.pool_size = 1
|
56
|
+
a.new.request(RC::TIMER => timer, RC::ASYNC => true).
|
57
57
|
message.should.eq 'boom'
|
58
58
|
timer.timer.should.not.nil?
|
59
59
|
end
|
60
60
|
|
61
61
|
would 'still timeout if the task never processed for thread pool' do
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
a = sleeping_app
|
63
|
+
a.pool_size = 1
|
64
|
+
a.new.request(RC::TIMER => fake_timer, RC::ASYNC => true) do |e|
|
65
65
|
e.message.should.eq 'boom'
|
66
|
-
|
66
|
+
a.new.request(RC::TIMER => fake_timer, RC::ASYNC => true).tap{}
|
67
67
|
end
|
68
|
-
|
68
|
+
a.wait
|
69
69
|
end
|
70
70
|
|
71
71
|
would 'interrupt the task if timing out' do
|
@@ -85,7 +85,7 @@ describe RC::Timeout do
|
|
85
85
|
def timer ; @block; end
|
86
86
|
self
|
87
87
|
end
|
88
|
-
|
88
|
+
a = RC::Builder.client do
|
89
89
|
run Class.new(RC::Engine){
|
90
90
|
def request _, env
|
91
91
|
env['pipe'].puts
|
@@ -94,8 +94,8 @@ describe RC::Timeout do
|
|
94
94
|
}
|
95
95
|
end
|
96
96
|
(-1..1).each do |size|
|
97
|
-
|
98
|
-
|
97
|
+
a.pool_size = size
|
98
|
+
a.new.request(RC::TIMER => timer, RC::ASYNC => true, 'pipe' => wr).
|
99
99
|
message.should.eq 'boom'
|
100
100
|
end
|
101
101
|
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.5
|
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-
|
11
|
+
date: 2015-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
188
|
version: '0'
|
189
189
|
requirements: []
|
190
190
|
rubyforge_project:
|
191
|
-
rubygems_version: 2.4.
|
191
|
+
rubygems_version: 2.4.8
|
192
192
|
signing_key:
|
193
193
|
specification_version: 4
|
194
194
|
summary: Modular Ruby clients interface for REST APIs.
|