hessian2 2.0.1 → 2.0.2

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.
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