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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c924d022a2e6884c045b8d70ad7c1a30d86a5ca5
4
- data.tar.gz: 29232062eafc2a9f2dc6619da8470c79cf475dab
3
+ metadata.gz: 02a017ca6ef776af782e4e7c575858b0cb8f3703
4
+ data.tar.gz: 8d29c4f87749dccb787c0134f6938a95fe57b733
5
5
  SHA512:
6
- metadata.gz: b9b3a2c2fd0c54d3406988ded11b4954a7f620f3209a8fec4187e013a39b039be17a8ce68186365ed6c7d0a740130b177ab06f9323cea5b87bd88746235c3351
7
- data.tar.gz: 87b917cd53b4f80ed97d7ed172b5ad54063d5db868b525ca0501297f85c2f413d1c88d43ee80a8e59cda2179f5c0600156f4d36b0e85eca8169bfba210fe2d75
6
+ metadata.gz: 0d6aad0bedad2f4b7a72a78ec984721515157508d20983425eb2f0354fad6cd092beaaa4d626ae4f1000339d248535d83b9b1da8568afe13adcdb5cf5064fe07
7
+ data.tar.gz: 2b75fccd0ba262c7f8915217cd142dbcc85f49497a2fe7b40b5d84b3818b74dea0b0982ba8ab601fa6a044c83e346054edd7beab24a56f67766a5c688ad61942
data/.travis.yml CHANGED
@@ -6,7 +6,6 @@ rvm:
6
6
  - 2.2
7
7
  - rbx-2
8
8
  - jruby
9
- - jruby-head
10
9
 
11
10
  install: 'bundle install --retry=3'
12
11
  script: 'ruby -r bundler/setup -S rake test'
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGES
2
2
 
3
+ ## rest-core 3.5.5 -- 2015-07-22
4
+
5
+ ### Bugs fixed
6
+
7
+ * Fixed a possible data race for thread pool when enqueuing very quickly.
8
+
3
9
  ## rest-core 3.5.4 -- 2015-01-17
4
10
 
5
11
  ### Bugs fixed
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 [![Build Status](https://secure.travis-ci.org/godfat/rest-core.png?branch=master)](http://travis-ci.org/godfat/rest-core) [![Coverage Status](https://coveralls.io/repos/godfat/rest-core/badge.png)](https://coveralls.io/r/godfat/rest-core)
1
+ # rest-core [![Build Status](https://secure.travis-ci.org/godfat/rest-core.png?branch=master)](http://travis-ci.org/godfat/rest-core) [![Coverage Status](https://coveralls.io/repos/godfat/rest-core/badge.png)](https://coveralls.io/r/godfat/rest-core) [![Join the chat at https://gitter.im/godfat/rest-core](https://badges.gitter.im/Join%20Chat.svg)](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 the pre-built client in
305
- [rest-more][] instead.
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](https://github.com/CodementorIO/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-2014, Lin Jen-Shin (godfat)
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
- * middleware revisit (how to initialize?)
4
- * X-Method-Override
3
+ # NEAR FUTURE
5
4
 
6
- # FEATURE
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.
@@ -54,7 +54,7 @@ class RestCore::Builder
54
54
  end
55
55
 
56
56
  def to_client *attrs
57
- fields = members + attrs
57
+ fields = (members + attrs + [:config_engine]).uniq
58
58
  struct = build_struct(fields)
59
59
  client = Class.new(struct)
60
60
  client.const_set('Struct', struct)
@@ -3,6 +3,7 @@ require 'rest-core/promise'
3
3
  require 'rest-core/middleware'
4
4
 
5
5
  class RestCore::Engine
6
+ def self.members; [:config_engine]; end
6
7
  include RestCore::Middleware
7
8
 
8
9
  def call env, &k
@@ -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.merge(RESPONSE_BODY => Json.decode("[#{body}]").first)
35
- # [this].first is not needed for yajl-ruby
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
- mutex.synchronize do
20
- queue << task
21
- condv.signal
22
- end
22
+ queue << task
23
+ condv.signal
23
24
  end
24
25
 
25
- def pop timeout=60
26
- mutex.synchronize do
27
- if queue.empty?
28
- condv.wait(mutex, timeout)
29
- queue.shift || lambda{ |_| false } # shutdown idle workers
30
- else
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, :mutex, :condv
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 mutex=nil, &job
91
- task = Task.new(job, mutex)
92
- queue << task
93
- spawn_worker if waiting == 0 && workers.size < max_size
94
- task
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
- queue << lambda{ |_| false } if force || waiting > 0
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, :workers, :waiting
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 = !!$DEBUG
117
+ Thread.current.abort_on_exception = true
115
118
 
116
119
  task = nil
117
120
  begin
118
- mutex.synchronize{ @waiting += 1 }
119
- task = queue.pop(idle_time)
120
- mutex.synchronize{ @waiting -= 1 }
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) }
@@ -23,6 +23,7 @@ module RestCore::Json
23
23
  def decode json
24
24
  Yajl::Parser.parse(json)
25
25
  end
26
+ alias_method :decode_from_io, :decode
26
27
  end
27
28
 
28
29
  module Json
@@ -3,7 +3,11 @@
3
3
 
4
4
  require 'rest-core/error'
5
5
 
6
- require 'mime/types'
6
+ begin
7
+ require 'mime/types/columnar'
8
+ rescue LoadError
9
+ require 'mime/types'
10
+ end
7
11
 
8
12
  require 'stringio'
9
13
  require 'tempfile'
@@ -1,4 +1,4 @@
1
1
 
2
2
  module RestCore
3
- VERSION = '3.5.4'
3
+ VERSION = '3.5.5'
4
4
  end
data/rest-core.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: rest-core 3.5.4 ruby lib
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.4"
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-01-17"
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.5"
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
- require 'coveralls'
104
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
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
- env = {RC::REQUEST_PAYLOAD => format}
23
+ e = {RC::REQUEST_PAYLOAD => format}
20
24
 
21
- app.call(env){ |r| r.should.eq({RC::REQUEST_PAYLOAD =>
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
- env = {RC::REQUEST_PAYLOAD => 'payload'}
36
- u.request_full(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
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(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
40
- u.request_full({} , u.dry)[RC::REQUEST_PAYLOAD].should.eq('default')
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({} , u.dry)[RC::REQUEST_PAYLOAD].should.eq('maylord')
44
- u.request_full(env, u.dry)[RC::REQUEST_PAYLOAD].should.eq('payload')
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
@@ -44,17 +44,17 @@ describe RC::ErrorHandler do
44
44
 
45
45
  would 'set full backtrace' do
46
46
  url = 'http://example.com/'
47
- client = RC::Builder.client do
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
- client.get(url) do |error|
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
- client.wait
57
+ c.wait
58
58
  end
59
59
 
60
60
  would 'not call error_handler if there is already an exception' do
@@ -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
@@ -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
- client = RC::Builder.client
7
- pool = RC::ThreadPool[client]
8
- RC::ThreadPool[client].object_id.should.eq pool.object_id
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(hash_including(env)){ raise "error" }
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
- app = sleeping_app
55
- app.pool_size = 1
56
- app.new.request(RC::TIMER => timer, RC::ASYNC => true).
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
- app = sleeping_app
63
- app.pool_size = 1
64
- app.new.request(RC::TIMER => fake_timer, RC::ASYNC => true) do |e|
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
- app.new.request(RC::TIMER => fake_timer, RC::ASYNC => true).tap{}
66
+ a.new.request(RC::TIMER => fake_timer, RC::ASYNC => true).tap{}
67
67
  end
68
- app.wait
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
- app = RC::Builder.client do
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
- app.pool_size = size
98
- app.new.request(RC::TIMER => timer, RC::ASYNC => true, 'pipe' => wr).
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
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-01-17 00:00:00.000000000 Z
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.5
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.