hessian2 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -4
  3. data/hessian2.gemspec +13 -11
  4. data/lib/hessian2/client.rb +22 -10
  5. data/lib/hessian2/handler.rb +5 -2
  6. data/lib/hessian2/version.rb +1 -1
  7. data/lib/hessian2/writer.rb +2 -1
  8. data/spec/create_monkeys.rb +4 -4
  9. data/spec/object_spec.rb +13 -0
  10. data/test/app.rb +12 -3
  11. data/test/async/em_http_asleep.rb +25 -0
  12. data/test/async/em_http_sleep.rb +25 -0
  13. data/test/async/monkey.asleep.rb +27 -0
  14. data/test/async/mysql2_aquery.rb +37 -0
  15. data/test/fault/monkey.undefined_method.rb +5 -0
  16. data/test/fault/monkey.wrong_arguments.rb +5 -0
  17. data/test/fiber_concurrency/em_http_asleep.rb +17 -0
  18. data/test/fiber_concurrency/em_http_sleep.rb +17 -0
  19. data/test/fiber_concurrency/monkey.asleep.fiber_aware.rb +18 -0
  20. data/test/fiber_concurrency/mysql2_query.rb +29 -0
  21. data/test/fiber_concurrency/net_http_asleep.rb +19 -0
  22. data/test/fiber_concurrency/net_http_sleep.rb +19 -0
  23. data/test/fibered_rainbows/Gemfile +15 -0
  24. data/test/fibered_rainbows/config.ru +11 -0
  25. data/test/fibered_rainbows/rainbows.rb +13 -0
  26. data/test/monkey_service.rb +10 -6
  27. data/test/prepare.rb +7 -0
  28. data/test/thread_concurrency/active_record_execute.rb +29 -0
  29. data/test/thread_concurrency/monkey.asleep.rb +22 -0
  30. data/test/thread_concurrency/net_http_asleep.rb +24 -0
  31. data/test/thread_concurrency/net_http_sleep.rb +24 -0
  32. data/test/threaded_rainbows/Gemfile +13 -0
  33. data/test/threaded_rainbows/config.ru +9 -0
  34. data/test/threaded_rainbows/rainbows.rb +13 -0
  35. metadata +105 -8
  36. data/lib/hessian2/em_client.rb +0 -52
  37. data/test/client.rb +0 -9
  38. data/test/config.ru +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 453a51289b1c88074aa15ecbf5018cbece6297b5
4
- data.tar.gz: 071db1c35b766485e0789ab22395769ac63cf652
3
+ metadata.gz: c3e89025e74e937f051cc7c5532bd58d003dd3cc
4
+ data.tar.gz: 127b7703579d72674763c1f64c6aea4ef72ef051
5
5
  SHA512:
6
- metadata.gz: fd9256a1475ed060499bed2a415eca1eb2bfdb20d1a315935f93dfdd2bb5090bead4ff0820df0f106e8534c34b4e54cbebcf8abc10232d31647040247777fca2
7
- data.tar.gz: 6624cba7d4093cec93d94d14a1dd82a5b39bce2340a6a229a0eaf4e045e88d2e5a29eeec03d8ad29c7b103841820939b13233433a40bf0332c3cc25ca4e26991
6
+ metadata.gz: 229b79558ab04006522bc54ed2fb139ae305621ba0b174da4d4007fff713c74435c4864d3d33075490e28381ef209ab44fc71f70d515df1702f32bf27ce0525b
7
+ data.tar.gz: b1ce0ce88dfe6696ea2a3741ebdb43bf1db8500f4f5d9f79fe602e85ee2446ad42db2c1795bd05385cfe3953069fa3b9ac985f8d694e971ebcdf4ad6a25bdc4c
data/README.md CHANGED
@@ -148,13 +148,49 @@ post '/monkey' do
148
148
  end
149
149
  ```
150
150
 
151
- ## todo
151
+ ## fiber_aware
152
152
 
153
- on linux string slower than thrift
153
+ fibered service, fiber aware client. use em-synchrony/em-http post.
154
154
 
155
- supports packet and envelope
155
+ ``` ruby
156
+ client = Hessian2::Client.new(url, fiber_aware: true)
157
+ concurrency = 2
158
+
159
+ EM.synchrony do
160
+ EM::Synchrony::FiberIterator.new(0...10, concurrency).each do |i|
161
+ puts client.asleep
162
+ end
163
+
164
+ EM.stop
165
+ end
166
+ ```
167
+
168
+ ## async
156
169
 
157
- write in c
170
+ evented service, asynchronous callbacks. use em-synchrony/em-http apost.
171
+
172
+ ``` ruby
173
+ client = Hessian2::Client.new(url, async: true)
174
+
175
+ EM.run do
176
+ http = client.asleep
177
+ http.callback do |r|
178
+ puts Hessian2.parse_rpc(r.response)
179
+ EM.stop
180
+ end
181
+
182
+ http.errback do |r|
183
+ puts r.error
184
+ EM.stop
185
+ end
186
+
187
+ puts "posted."
188
+ end
189
+ ```
190
+
191
+ ## todo
192
+
193
+ supports packet and envelope
158
194
 
159
195
  ## authors
160
196
 
data/hessian2.gemspec CHANGED
@@ -1,25 +1,27 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "hessian2/version"
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'hessian2/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "hessian2"
6
+ s.name = 'hessian2'
7
7
  s.version = Hessian2::VERSION
8
- s.authors = ["takafan"]
9
- s.email = ["takafan@163.com"]
10
- s.homepage = "http://github.com/takafan/hessian2"
8
+ s.authors = ['takafan']
9
+ s.email = ['takafan@163.com']
10
+ s.homepage = 'http://github.com/takafan/hessian2'
11
11
  s.summary = %q{Hessian2}
12
12
  s.description = %q{like json, additionally, 麻绳2 parse your object as a struct.}
13
13
 
14
- s.rubyforge_project = "hessian2"
14
+ s.rubyforge_project = 'hessian2'
15
15
  s.license = 'MIT'
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ["lib"]
20
+ s.require_paths = ['lib']
21
21
 
22
- # specify any dependencies here; for example:
23
- # s.add_development_dependency "rspec"
24
- s.add_runtime_dependency "bigdecimal"
22
+ s.add_development_dependency 'rspec'
23
+ s.add_runtime_dependency 'activerecord'
24
+ s.add_runtime_dependency 'bigdecimal'
25
+ s.add_runtime_dependency 'em-http-request'
26
+ s.add_runtime_dependency 'em-synchrony'
25
27
  end
@@ -1,6 +1,6 @@
1
1
  require 'uri'
2
2
  require 'net/http'
3
- require 'net/https'
3
+ require 'em-synchrony/em-http'
4
4
  require 'hessian2'
5
5
 
6
6
  module Hessian2
@@ -8,12 +8,14 @@ module Hessian2
8
8
  attr_accessor :user, :password
9
9
  attr_reader :scheme, :host, :port, :path, :proxy
10
10
 
11
- def initialize(url, proxy = {})
11
+ def initialize(url, options = {})
12
12
  uri = URI.parse(url)
13
13
  @scheme, @host, @port, @path = uri.scheme, uri.host, uri.port, uri.path.empty? ? '/' : uri.path
14
14
  @path += "?#{uri.query}" if uri.query
15
15
  raise "Unsupported Hessian protocol: #{@scheme}" unless %w(http https).include?(@scheme)
16
- @proxy = proxy
16
+ @async = options.delete(:async)
17
+ @fiber_aware = options.delete(:fiber_aware)
18
+ @proxy = options
17
19
  end
18
20
 
19
21
 
@@ -21,16 +23,26 @@ module Hessian2
21
23
  return invoke(id.id2name, args)
22
24
  end
23
25
 
24
-
25
26
  private
26
27
 
27
28
  def invoke(method, args)
28
- req = Net::HTTP::Post.new(@path, { 'Content-Type' => 'application/binary' })
29
- req.basic_auth @user, @password if @user
30
- conn = Net::HTTP.new(@host, @port, *@proxy.values_at(:host, :port, :user, :password))
31
- conn.use_ssl = true and conn.verify_mode = OpenSSL::SSL::VERIFY_NONE if @scheme == 'https'
32
- conn.start do |http|
33
- Hessian2.parse_rpc(http.request(req, Hessian2.call(method, args)).body)
29
+ req_head = { 'Content-Type' => 'application/binary' }
30
+ req_body = Hessian2.call(method, args)
31
+
32
+ if @async
33
+ EM::HttpRequest.new("#{@scheme}://#{@host}:#{@port}#{@path}").apost(body: req_body, head: req_head)
34
+ elsif @fiber_aware
35
+ http = EM::HttpRequest.new("#{@scheme}://#{@host}:#{@port}#{@path}").post(body: req_body, head: req_head)
36
+ Hessian2.parse_rpc(http.response)
37
+ else
38
+ req = Net::HTTP::Post.new(@path, req_head)
39
+ req.basic_auth @user, @password if @user
40
+ conn = Net::HTTP.new(@host, @port, *@proxy.values_at(:host, :port, :user, :password))
41
+ conn.use_ssl = true and conn.verify_mode = OpenSSL::SSL::VERIFY_NONE if @scheme == 'https'
42
+ conn.start do |http|
43
+ res = http.request(req, req_body)
44
+ Hessian2.parse_rpc(res.body)
45
+ end
34
46
  end
35
47
  end
36
48
 
@@ -4,10 +4,13 @@ module Hessian2
4
4
  module Handler
5
5
 
6
6
  def handle(data)
7
+ val = Hessian2.parse_rpc(data)
7
8
  begin
8
- Hessian2.reply(self.send(*Hessian2.parse_rpc(data)))
9
- rescue NoMethodError, ArgumentError, NameError, Fault => e
9
+ res = self.send(*val)
10
+ rescue NoMethodError, ArgumentError => e
10
11
  Hessian2.write_fault(e)
12
+ else
13
+ Hessian2.reply(res)
11
14
  end
12
15
  end
13
16
 
@@ -1,3 +1,3 @@
1
1
  module Hessian2
2
- VERSION = "2.0.1"
2
+ VERSION = "2.0.2"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'hessian2/constants'
2
2
  require 'bigdecimal'
3
+ require 'active_record'
3
4
 
4
5
  module Hessian2
5
6
  module Writer
@@ -52,7 +53,7 @@ module Hessian2
52
53
  write_float(val)
53
54
  when Fixnum
54
55
  write_int(val)
55
- when Array
56
+ when Array, ActiveRecord::Relation
56
57
  write_array(val, refs, crefs, trefs)
57
58
  when Bignum
58
59
  if val >= -0x80_000_000 && val <= 0x7f_fff_fff # four octet longs
@@ -3,12 +3,12 @@ require File.expand_path('../spec_helper', __FILE__)
3
3
  ActiveRecord::Base.connection.execute("drop table if exists monkeys")
4
4
  ActiveRecord::Base.connection.execute("create table monkeys(id integer(11) not null auto_increment, born_at datetime, name varchar(255), price decimal(10, 2), primary key(id)) charset=utf8")
5
5
 
6
- now = Time.new
7
- 1.upto(1000).each do |i|
6
+ born_at = Time.new(1989, 5, 8)
7
+ 1000.times.each do |i|
8
8
  Monkey.create(
9
- id: i,
9
+ id: i + 1,
10
10
  name: "#{i}号猴",
11
11
  price: 0.25 * i,
12
- born_at: now - 3600 * (1000 - i)
12
+ born_at: born_at + 86400 * i
13
13
  )
14
14
  end
data/spec/object_spec.rb CHANGED
@@ -60,6 +60,19 @@ module Hessian2
60
60
  end
61
61
  end
62
62
 
63
+ it "should write ActiveRecord::Relation" do
64
+ val = Monkey.where(true).limit(2)
65
+ bin = Hessian2.write(val)
66
+
67
+ bytes = bin.each_byte
68
+ expect(bytes.next - 0x78).to eq(val.size)
69
+
70
+ born_at = Time.new(1989, 5, 8)
71
+ Hessian2.parse(bin).each_with_index do |_monkey, i|
72
+ expect([ _monkey.id, _monkey.name, _monkey.price, _monkey.born_at ]).to eq([ i + 1, "#{i}号猴", 0.25 * i, born_at + 86400 * i ])
73
+ end
74
+ end
75
+
63
76
  end
64
77
  end
65
78
  end
data/test/app.rb CHANGED
@@ -1,6 +1,3 @@
1
- lib_path = File.expand_path('../../lib', __FILE__)
2
- $:.unshift(lib_path)
3
- require 'sinatra'
4
1
  require File.expand_path('../monkey_service', __FILE__)
5
2
 
6
3
  set :logging, false
@@ -13,3 +10,15 @@ end
13
10
  post '/' do
14
11
  MonkeyService.handle(request.body.read)
15
12
  end
13
+
14
+ route :get, :post, '/sleep' do
15
+ sleep 1
16
+
17
+ 'wake'
18
+ end
19
+
20
+ route :get, :post, '/asleep' do
21
+ EM::Synchrony.sleep(1)
22
+
23
+ 'awake'
24
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'eventmachine'
3
+ require 'em-synchrony/em-http'
4
+
5
+ EM.run do
6
+ @number_of.times do |i|
7
+ puts i
8
+ http = EM::HttpRequest.new("http://127.0.0.1:8080/asleep").apost
9
+ http.callback do |r|
10
+ puts 'callback'
11
+ @results << r.response
12
+ EM.stop if @results.size >= @number_of
13
+ end
14
+
15
+ http.errback do |r|
16
+ puts "errback #{r.error}"
17
+ EM.stop
18
+ end
19
+ end
20
+
21
+ puts "results.size #{@results.size}"
22
+ end
23
+
24
+ puts @results.inspect
25
+ puts "results.size #{@results.size}"
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'eventmachine'
3
+ require 'em-synchrony/em-http'
4
+
5
+ EM.run do
6
+ @number_of.times do |i|
7
+ puts i
8
+ http = EM::HttpRequest.new("http://127.0.0.1:8080/sleep").apost
9
+ http.callback do |r|
10
+ puts 'callback'
11
+ @results << r.response
12
+ EM.stop if @results.size >= @number_of
13
+ end
14
+
15
+ http.errback do |r|
16
+ puts "errback #{r.error}"
17
+ EM.stop
18
+ end
19
+ end
20
+
21
+ puts "results.size #{@results.size}"
22
+ end
23
+
24
+ puts @results.inspect
25
+ puts "results.size #{@results.size}"
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'eventmachine'
3
+
4
+ client = Hessian2::Client.new('http://127.0.0.1:8080/', async: true)
5
+
6
+ EM.run do
7
+ @number_of.times do |i|
8
+ puts i
9
+ http = client.asleep
10
+ http.callback do |r|
11
+ puts 'callback'
12
+ @results << Hessian2.parse_rpc(r.response)
13
+ EM.stop if @results.size >= @number_of
14
+ end
15
+
16
+ http.errback do |r|
17
+ puts "errback #{r.error}"
18
+ @results << nil
19
+ EM.stop
20
+ end
21
+ end
22
+
23
+ puts "results.size #{@results.size}"
24
+ end
25
+
26
+ puts @results.inspect
27
+ puts "results.size #{@results.size}"
@@ -0,0 +1,37 @@
1
+ require 'em-synchrony'
2
+ require 'em-synchrony/mysql2'
3
+ require 'em-synchrony/fiber_iterator'
4
+ require 'yaml'
5
+
6
+ options = YAML.load_file(File.expand_path('../../../spec/database.yml', __FILE__))
7
+ puts options.inspect
8
+
9
+ number_of = 10
10
+ concurrency = 2
11
+ connection_pool_size = 4
12
+ results = []
13
+
14
+ db = EM::Synchrony::ConnectionPool.new(size: connection_pool_size) do
15
+ Mysql2::EM::Client.new(options)
16
+ end
17
+
18
+ EM.synchrony do
19
+ EM::Synchrony::FiberIterator.new(0...number_of, concurrency).each do |i|
20
+ puts i
21
+ aquery = db.aquery('select sleep(1)')
22
+ aquery.callback do |r|
23
+ puts 'callback'
24
+ results << r.first
25
+ EM.stop if results.size >= number_of
26
+ end
27
+ end
28
+
29
+ puts "results.size #{results.size}"
30
+ end
31
+
32
+ puts results.inspect
33
+ puts "results.size #{results.size}"
34
+
35
+ # time ruby test/async/mysql2_aquery.rb
36
+ # 并发数 >= db连接池的场合,aquery要等空闲连接出来,耗时和query一样
37
+ # 并发数 < db连接池的场合,aquery可以马上用空闲连接发起下一波查询,也就更早拿到callback,比query快
@@ -0,0 +1,5 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+
3
+ client = Hessian2::Client.new('http://127.0.0.1:8080/')
4
+
5
+ puts client.undefined_method
@@ -0,0 +1,5 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+
3
+ client = Hessian2::Client.new('http://127.0.0.1:8080/')
4
+
5
+ puts client.sleep('wrong', 'arguments')
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/em-http'
4
+ require 'em-synchrony/fiber_iterator'
5
+
6
+ EM.synchrony do
7
+ EM::Synchrony::FiberIterator.new(0...@number_of, @concurrency).each do |i|
8
+ puts i
9
+ @results << EM::HttpRequest.new("http://127.0.0.1:8080/asleep").post.response
10
+ end
11
+
12
+ puts "results.size #{@results.size}"
13
+ EM.stop
14
+ end
15
+
16
+ puts @results.inspect
17
+ puts "results.size #{@results.size}"
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/em-http'
4
+ require 'em-synchrony/fiber_iterator'
5
+
6
+ EM.synchrony do
7
+ EM::Synchrony::FiberIterator.new(0...@number_of, @concurrency).each do |i|
8
+ puts i
9
+ @results << EM::HttpRequest.new("http://127.0.0.1:8080/sleep").post.response
10
+ end
11
+
12
+ puts "results.size #{@results.size}"
13
+ EM.stop
14
+ end
15
+
16
+ puts @results.inspect
17
+ puts "results.size #{@results.size}"
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/fiber_iterator'
4
+
5
+ client = Hessian2::Client.new('http://127.0.0.1:8080/', fiber_aware: true)
6
+
7
+ EM.synchrony do
8
+ EM::Synchrony::FiberIterator.new(0...@number_of, @concurrency).each do |i|
9
+ puts i
10
+ @results << client.asleep
11
+ end
12
+
13
+ puts "results.size #{@results.size}"
14
+ EM.stop
15
+ end
16
+
17
+ puts @results.inspect
18
+ puts "results.size #{@results.size}"
@@ -0,0 +1,29 @@
1
+ require 'em-synchrony'
2
+ require 'em-synchrony/mysql2'
3
+ require 'em-synchrony/fiber_iterator'
4
+ require 'yaml'
5
+
6
+ options = YAML.load_file(File.expand_path('../../../spec/database.yml', __FILE__))
7
+ puts options.inspect
8
+
9
+ number_of = 10
10
+ concurrency = 2
11
+ connection_pool_size = 4
12
+ results = []
13
+
14
+ db = EM::Synchrony::ConnectionPool.new(size: connection_pool_size) do
15
+ Mysql2::EM::Client.new(options)
16
+ end
17
+
18
+ EM.synchrony do
19
+ EM::Synchrony::FiberIterator.new(0...number_of, concurrency).each do |i|
20
+ puts i
21
+ results << db.query('select sleep(1)').first
22
+ end
23
+
24
+ puts "results.size #{results.size}"
25
+ EM.stop
26
+ end
27
+
28
+ puts results.inspect
29
+ puts "results.size #{results.size}"
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/fiber_iterator'
4
+ require 'net/http'
5
+
6
+ EM.synchrony do
7
+ EM::Synchrony::FiberIterator.new(0...@number_of, @concurrency).each do |i|
8
+ puts i
9
+ Net::HTTP.new('127.0.0.1', 8080).start do |http|
10
+ @results << http.request(Net::HTTP::Post.new('/asleep')).body
11
+ end
12
+ end
13
+
14
+ puts "results.size #{@results.size}"
15
+ EM.stop
16
+ end
17
+
18
+ puts @results.inspect
19
+ puts "results.size #{@results.size}"
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'em-synchrony'
3
+ require 'em-synchrony/fiber_iterator'
4
+ require 'net/http'
5
+
6
+ EM.synchrony do
7
+ EM::Synchrony::FiberIterator.new(0...@number_of, @concurrency).each do |i|
8
+ puts i
9
+ Net::HTTP.new('127.0.0.1', 8080).start do |http|
10
+ @results << http.request(Net::HTTP::Post.new('/sleep')).body
11
+ end
12
+ end
13
+
14
+ puts "results.size #{@results.size}"
15
+ EM.stop
16
+ end
17
+
18
+ puts @results.inspect
19
+ puts "results.size #{@results.size}"
@@ -0,0 +1,15 @@
1
+ source "http://ruby.taobao.org"
2
+
3
+ gem 'em-synchrony', require: ['em-synchrony']
4
+
5
+ gem 'activerecord'
6
+
7
+ gem 'bigdecimal'
8
+
9
+ gem 'rack-fiber_pool'
10
+
11
+ gem 'rainbows'
12
+
13
+ gem 'sinatra'
14
+
15
+ gem 'sinatra-contrib'
@@ -0,0 +1,11 @@
1
+ lib_path = File.expand_path('../../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+
4
+ require 'hessian2'
5
+ require 'bundler'
6
+ Bundler.require
7
+
8
+ use Rack::FiberPool
9
+
10
+ require ::File.expand_path('../../app', __FILE__)
11
+ run Sinatra::Application
@@ -0,0 +1,13 @@
1
+ Rainbows! do
2
+ use :EventMachine
3
+ end
4
+
5
+ worker_processes 1
6
+
7
+ timeout 30
8
+
9
+ pid '/tmp/monkey.pid'
10
+
11
+ preload_app true
12
+ GC.respond_to?(:copy_on_write_friendly=) and
13
+ GC.copy_on_write_friendly = true
@@ -1,12 +1,16 @@
1
- lib_path = File.expand_path('../../lib', __FILE__)
2
- $:.unshift(lib_path)
3
- require 'hessian2'
4
-
5
1
  class MonkeyService
6
2
  extend Hessian2::Handler
7
3
 
8
- def self.say(name)
9
- "hello #{name}"
4
+ def self.sleep(name = '')
5
+ Kernel.sleep 1
6
+
7
+ "wake #{name}"
8
+ end
9
+
10
+ def self.asleep(name = '')
11
+ EM::Synchrony.sleep(1)
12
+
13
+ "awake #{name}"
10
14
  end
11
15
 
12
16
  end
data/test/prepare.rb ADDED
@@ -0,0 +1,7 @@
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+ require 'hessian2'
4
+
5
+ @number_of = 10
6
+ @concurrency = 2
7
+ @results = []
@@ -0,0 +1,29 @@
1
+ require 'active_record'
2
+ require 'thread/pool'
3
+ require 'yaml'
4
+
5
+ options = YAML.load_file(File.expand_path('../../../spec/database.yml', __FILE__))
6
+ puts options.inspect
7
+
8
+ number_of = 10
9
+ concurrency = 2
10
+ connection_pool_size = 4
11
+ results = []
12
+
13
+ thread_pool = Thread.pool(concurrency)
14
+ db = ActiveRecord::Base.establish_connection(options.merge('pool' => connection_pool_size))
15
+
16
+ number_of.times do |i|
17
+ thread_pool.process do
18
+ puts i
19
+ results << ActiveRecord::Base.connection_pool.with_connection do |conn|
20
+ conn.execute('select sleep(1)').first
21
+ end
22
+ end
23
+ end
24
+
25
+ puts "results.size #{results.size}"
26
+ thread_pool.shutdown
27
+
28
+ puts results.inspect
29
+ puts "results.size #{results.size}"
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'thread/pool'
3
+
4
+ thread_pool = Thread.pool(@concurrency)
5
+ client = Hessian2::Client.new('http://127.0.0.1:8080/')
6
+
7
+ @number_of.times do |i|
8
+ thread_pool.process do
9
+ puts i
10
+ begin
11
+ @results << client.asleep
12
+ rescue RuntimeError => e
13
+ puts "#{e.message}"
14
+ end
15
+ end
16
+ end
17
+
18
+ puts "results.size #{@results.size}"
19
+ thread_pool.shutdown
20
+
21
+ puts @results.inspect
22
+ puts "results.size #{@results.size}"
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'net/http'
3
+ require 'thread/pool'
4
+
5
+ thread_pool = Thread.pool(@concurrency)
6
+
7
+ @number_of.times do |i|
8
+ thread_pool.process do
9
+ puts i
10
+ begin
11
+ Net::HTTP.new('127.0.0.1', 8080).start do |http|
12
+ @results << http.request(Net::HTTP::Post.new('/asleep')).body
13
+ end
14
+ rescue RuntimeError => e
15
+ puts "#{e.message}"
16
+ end
17
+ end
18
+ end
19
+
20
+ puts "results.size #{@results.size}"
21
+ thread_pool.shutdown
22
+
23
+ puts @results.inspect
24
+ puts "results.size #{@results.size}"
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../../prepare', __FILE__)
2
+ require 'net/http'
3
+ require 'thread/pool'
4
+
5
+ thread_pool = Thread.pool(@concurrency)
6
+
7
+ @number_of.times do |i|
8
+ thread_pool.process do
9
+ puts i
10
+ begin
11
+ Net::HTTP.new('127.0.0.1', 8080).start do |http|
12
+ @results << http.request(Net::HTTP::Post.new('/sleep')).body
13
+ end
14
+ rescue RuntimeError => e
15
+ puts "#{e.message}"
16
+ end
17
+ end
18
+ end
19
+
20
+ puts "results.size #{@results.size}"
21
+ thread_pool.shutdown
22
+
23
+ puts @results.inspect
24
+ puts "results.size #{@results.size}"
@@ -0,0 +1,13 @@
1
+ source 'http://ruby.taobao.org'
2
+
3
+ gem 'em-synchrony', require: ['em-synchrony']
4
+
5
+ gem 'activerecord'
6
+
7
+ gem 'bigdecimal'
8
+
9
+ gem 'rainbows'
10
+
11
+ gem 'sinatra'
12
+
13
+ gem 'sinatra-contrib'
@@ -0,0 +1,9 @@
1
+ lib_path = File.expand_path('../../../lib', __FILE__)
2
+ $:.unshift(lib_path)
3
+
4
+ require 'hessian2'
5
+ require 'bundler'
6
+ Bundler.require
7
+
8
+ require ::File.expand_path('../../app', __FILE__)
9
+ run Sinatra::Application
@@ -0,0 +1,13 @@
1
+ Rainbows! do
2
+ use :ThreadSpawn
3
+ end
4
+
5
+ worker_processes 1
6
+
7
+ timeout 30
8
+
9
+ pid '/tmp/monkey.pid'
10
+
11
+ preload_app true
12
+ GC.respond_to?(:copy_on_write_friendly=) and
13
+ GC.copy_on_write_friendly = true
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hessian2
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - takafan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-10 00:00:00.000000000 Z
11
+ date: 2013-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
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'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bigdecimal
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +52,34 @@ dependencies:
24
52
  - - '>='
25
53
  - !ruby/object:Gem::Version
26
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: em-http-request
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: em-synchrony
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
27
83
  description: like json, additionally, 麻绳2 parse your object as a struct.
28
84
  email:
29
85
  - takafan@163.com
@@ -41,7 +97,6 @@ files:
41
97
  - lib/hessian2/class_wrapper.rb
42
98
  - lib/hessian2/client.rb
43
99
  - lib/hessian2/constants.rb
44
- - lib/hessian2/em_client.rb
45
100
  - lib/hessian2/fault.rb
46
101
  - lib/hessian2/handler.rb
47
102
  - lib/hessian2/hessian_client.rb
@@ -68,9 +123,30 @@ files:
68
123
  - spec/struct_wrapper_spec.rb
69
124
  - spec/type_wrapper_spec.rb
70
125
  - test/app.rb
71
- - test/client.rb
72
- - test/config.ru
126
+ - test/async/em_http_asleep.rb
127
+ - test/async/em_http_sleep.rb
128
+ - test/async/monkey.asleep.rb
129
+ - test/async/mysql2_aquery.rb
130
+ - test/fault/monkey.undefined_method.rb
131
+ - test/fault/monkey.wrong_arguments.rb
132
+ - test/fiber_concurrency/em_http_asleep.rb
133
+ - test/fiber_concurrency/em_http_sleep.rb
134
+ - test/fiber_concurrency/monkey.asleep.fiber_aware.rb
135
+ - test/fiber_concurrency/mysql2_query.rb
136
+ - test/fiber_concurrency/net_http_asleep.rb
137
+ - test/fiber_concurrency/net_http_sleep.rb
138
+ - test/fibered_rainbows/Gemfile
139
+ - test/fibered_rainbows/config.ru
140
+ - test/fibered_rainbows/rainbows.rb
73
141
  - test/monkey_service.rb
142
+ - test/prepare.rb
143
+ - test/thread_concurrency/active_record_execute.rb
144
+ - test/thread_concurrency/monkey.asleep.rb
145
+ - test/thread_concurrency/net_http_asleep.rb
146
+ - test/thread_concurrency/net_http_sleep.rb
147
+ - test/threaded_rainbows/Gemfile
148
+ - test/threaded_rainbows/config.ru
149
+ - test/threaded_rainbows/rainbows.rb
74
150
  homepage: http://github.com/takafan/hessian2
75
151
  licenses:
76
152
  - MIT
@@ -91,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
167
  version: '0'
92
168
  requirements: []
93
169
  rubyforge_project: hessian2
94
- rubygems_version: 2.1.5
170
+ rubygems_version: 2.1.9
95
171
  signing_key:
96
172
  specification_version: 4
97
173
  summary: Hessian2
@@ -114,6 +190,27 @@ test_files:
114
190
  - spec/struct_wrapper_spec.rb
115
191
  - spec/type_wrapper_spec.rb
116
192
  - test/app.rb
117
- - test/client.rb
118
- - test/config.ru
193
+ - test/async/em_http_asleep.rb
194
+ - test/async/em_http_sleep.rb
195
+ - test/async/monkey.asleep.rb
196
+ - test/async/mysql2_aquery.rb
197
+ - test/fault/monkey.undefined_method.rb
198
+ - test/fault/monkey.wrong_arguments.rb
199
+ - test/fiber_concurrency/em_http_asleep.rb
200
+ - test/fiber_concurrency/em_http_sleep.rb
201
+ - test/fiber_concurrency/monkey.asleep.fiber_aware.rb
202
+ - test/fiber_concurrency/mysql2_query.rb
203
+ - test/fiber_concurrency/net_http_asleep.rb
204
+ - test/fiber_concurrency/net_http_sleep.rb
205
+ - test/fibered_rainbows/Gemfile
206
+ - test/fibered_rainbows/config.ru
207
+ - test/fibered_rainbows/rainbows.rb
119
208
  - test/monkey_service.rb
209
+ - test/prepare.rb
210
+ - test/thread_concurrency/active_record_execute.rb
211
+ - test/thread_concurrency/monkey.asleep.rb
212
+ - test/thread_concurrency/net_http_asleep.rb
213
+ - test/thread_concurrency/net_http_sleep.rb
214
+ - test/threaded_rainbows/Gemfile
215
+ - test/threaded_rainbows/config.ru
216
+ - test/threaded_rainbows/rainbows.rb
@@ -1,52 +0,0 @@
1
- require 'uri'
2
- require 'em-synchrony'
3
- require 'em-synchrony/em-http'
4
- require 'hessian2'
5
-
6
- module Hessian2
7
- class EmClient
8
- attr_accessor :user, :password
9
- attr_reader :scheme, :host, :port, :path, :proxy
10
-
11
- def initialize(url, proxy = {})
12
- uri = URI.parse(url)
13
- @scheme, @host, @port, @path = uri.scheme, uri.host, uri.port, uri.path.empty? ? '/' : uri.path
14
- @path += "?#{uri.query}" if uri.query
15
- raise "Unsupported Hessian protocol: #{@scheme}" unless @scheme == 'http'
16
- @proxy = proxy
17
- end
18
-
19
-
20
- def method_missing(id, *args)
21
- return invoke(id.id2name, args)
22
- end
23
-
24
-
25
- private
26
-
27
- def invoke(method, args)
28
- result = nil
29
- block = lambda do
30
- EM::Synchrony.sync(
31
- EM::HttpRequest.new("http://#{@host}:#{@port}", :connect_timeout => 5, :inactivity_timeout => 60).post(
32
- path: @path,
33
- head: {'Content-Type' => 'application/binary; charset=utf-8'},
34
- body: Hessian2.call(method, args)
35
- )
36
- )
37
- end
38
-
39
- unless EM.reactor_running?
40
- EM.synchrony do
41
- result = Hessian2.parse_rpc(block.call.response)
42
- EM.stop
43
- end
44
- else
45
- result = Hessian2.parse_rpc(block.call.response)
46
- end
47
-
48
- result
49
- end
50
-
51
- end
52
- end
data/test/client.rb DELETED
@@ -1,9 +0,0 @@
1
- lib_path = File.expand_path('../../lib', __FILE__)
2
- $:.unshift(lib_path)
3
- require 'hessian2'
4
-
5
- client = Hessian2::Client.new('http://localhost:4567')
6
-
7
- puts client.say ARGV.first
8
-
9
- puts client.say2
data/test/config.ru DELETED
@@ -1,2 +0,0 @@
1
- require ::File.expand_path('../app', __FILE__)
2
- run Sinatra::Application