em_remote_call 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,35 +1,47 @@
1
- module EM::RemoteCall
2
- def remote_method(name, opts={})
3
- unless respond_to? :remote_connection
4
- class << self
5
- define_method(:remote_connection=){ |conn| @remote_connection = conn }
6
- define_method(:remote_connection) { @remote_connection }
7
- end
1
+ class Class
2
+ def has_em_remote_class(remote_class_name, opts)
3
+ extend EM::RemoteCall
4
+ class << self
5
+ attr_accessor :remote_connection
6
+ extend EM::RemoteCall
8
7
  end
9
8
 
10
- define_method name do |*method_opts, &callb|
11
- remote_connection =
12
- (self.class.respond_to?(:remote_connection) && self.class.remote_connection) ||
13
- (self.respond_to?(:remote_connection) && self.remote_connection)
14
- return unless remote_connection
9
+ opts[:name] ||= :default
10
+ opts[:remote_class_name] = remote_class_name
11
+ self.remote_connection = EM::RemoteCall::Client.find(opts[:name]) || EM::RemoteCall::Client.new(opts)
12
+ end
13
+ end
14
+
15
+ module EM::RemoteCall
16
+ def remote_method(method_name, opts={})
17
+ define_method method_name do |*method_args, &callb|
18
+ return unless remote_connection =
19
+ (self.class.respond_to?(:remote_connection) && self.class.remote_connection) ||
20
+ (self.respond_to?(:remote_connection) && self.remote_connection)
15
21
 
16
22
  callback = EM::RemoteCall::Deferrable.new
17
23
  callback.callback(&callb) if callb
18
24
 
19
25
  call = {
20
- :argument => method_opts.first, # evt. other args will get dropped
21
- :instance => {
22
- :class => opts[:class_name] || self.class.to_s, # own class name by default
23
- :id => opts[:find_by] && send(opts[:find_by]) # when it's nil, it's considered a class method.
24
- },
25
- :method => opts[:calls] || name, # same method name by default
26
- :deferrable_id => callback.object_id # store the callbacks object_id to retrieve it later
27
- }
26
+ :deferrable_id => callback.object_id, # store the callbacks object_id to retrieve it later
27
+ :debug => opts[:debug], # debugging on client and server
28
+ :method => opts[:calls] || method_name, # same method name by default
29
+ :arguments => [*method_args], # all the args
30
+ :instance => {
31
+ :class => remote_connection.remote_class_name || self.class.to_s, # own class name by default
32
+ :id => !opts[:server_class_method] && send(remote_connection.instance_finder) # when it's nil, it's considered a class method.
33
+ }}
28
34
 
35
+ puts "On Client: #{call}" if opts[:debug]
29
36
  remote_connection.call call
30
37
  return callback
31
38
  end
32
39
  end
40
+
41
+ # a convinience wrapper for class methods:
42
+ def remote_class_method(method_name, opts={})
43
+ (class << self; self; end).remote_method method_name, opts.merge({:server_class_method => true})
44
+ end
33
45
  end
34
46
 
35
47
  class EM::RemoteCall::Deferrable
@@ -42,17 +54,36 @@ class EM::RemoteCall::Deferrable
42
54
  end
43
55
  end
44
56
 
45
- module EM::RemoteCall::Client
57
+ module EM::RemoteCall::ClientConnection
46
58
  include EM::JsonConnection::Client
47
59
 
48
60
  def json_parsed(hash)
49
- id = hash[:deferrable_id]
50
- deffr = EM::RemoteCall::Deferrable.find(id)
61
+ puts "From server: #{hash}" if hash[:debug]
62
+
63
+ deffr = EM::RemoteCall::Deferrable.find hash[:deferrable_id]
51
64
  deffr.succeed hash[:success] if hash.has_key? :success
52
65
  deffr.fail hash[:error] if hash.has_key? :error
53
66
  end
67
+ end
68
+
69
+ class EM::RemoteCall::Client
70
+ attr_reader :name, :remote_class_name, :instance_finder
71
+ is_a_collection :name
72
+
73
+ def initialize(opts)
74
+ @name = opts[:name] ||= :default
75
+ @remote_class_name = opts[:remote_class_name]
76
+ @socket = opts[:socket]
77
+ @port = opts[:port]
78
+ @instance_finder = opts[:instance_finder] ||= :id
79
+ end
54
80
 
55
81
  def call(call)
56
- send_data call
82
+ unless @connection && @connection.connected?
83
+ @connection = EM::RemoteCall::ClientConnection.connect_to *[@socket, @port].compact
84
+ end
85
+
86
+ @connection.send_data call
57
87
  end
88
+
58
89
  end
@@ -2,15 +2,15 @@ module EM::RemoteCall; end
2
2
 
3
3
  class EM::RemoteCall::Call
4
4
  class Error < StandardError; end
5
- class NoInstanceError < Error ; end
5
+ class NoInstanceError < Error; end
6
6
  class NoMethodGivenError < Error; end
7
7
  class NoMethodOfInstanceError < Error; end
8
8
 
9
- def initialize(instance_opts, method, argument)
10
- @argument = argument
11
- @method = method or raise NoMethodError.new method
12
- @instance = find_instance(instance_opts) or raise NoInstanceError.new instance_opts
13
- @instance.respond_to?(@method) or raise NoMethodOfInstanceError.new "#{@instance}##{method}"
9
+ def initialize(instance_opts, method, arguments)
10
+ @arguments = arguments
11
+ @method = method or raise NoMethodError.new method
12
+ @instance = find_instance(instance_opts) or raise NoInstanceError.new instance_opts
13
+ @instance.respond_to?(@method) or raise NoMethodOfInstanceError.new "#{@instance}##{method}"
14
14
  end
15
15
 
16
16
  def find_instance(args)
@@ -22,8 +22,15 @@ class EM::RemoteCall::Call
22
22
  end
23
23
  end
24
24
 
25
+ def takes_block?
26
+ method = @instance.method(@method)
27
+ return unless method.respond_to?(:parameters)
28
+ params = method.parameters
29
+ params.last && params.last.first == :block
30
+ end
31
+
25
32
  def call(&callb)
26
- @argument ? @instance.__send__(@method, @argument, &callb) : @instance.__send__(@method, &callb)
33
+ @arguments.empty? ? @instance.__send__(@method, &callb) : @instance.__send__(@method, *@arguments, &callb)
27
34
  end
28
35
  end
29
36
 
@@ -31,23 +38,24 @@ module EM::RemoteCall::Server
31
38
  include EM::JsonConnection::Server
32
39
 
33
40
  def json_parsed(hash)
34
- remote_call = EM::RemoteCall::Call.new hash[:instance], hash[:method].to_sym, hash[:argument]
41
+ remote_call = EM::RemoteCall::Call.new hash[:instance], hash[:method].to_sym, hash[:arguments]
42
+ puts "On Server: #{remote_call}: #{hash}" if hash[:debug]
35
43
 
36
- ret = remote_call.call do |result|
37
- send_data({:deferrable_id => hash[:deferrable_id], :success => result})
44
+ if remote_call.takes_block?
45
+ remote_call.call{ |result| send_data :deferrable_id => hash[:deferrable_id], :method_type => :block, :success => result }
46
+ return
38
47
  end
39
48
 
49
+ ret = remote_call.call
40
50
  if ret.is_a? EM::Deferrable
41
- ret.callback do |result|
42
- send_data({:deferrable_id => hash[:deferrable_id], :success => result})
43
- end
44
- ret.errback do |result|
45
- send_data({:deferrable_id => hash[:deferrable_id], :error => result})
46
- end
51
+ ret.callback{ |result| send_data :deferrable_id => hash[:deferrable_id], :debug => hash[:debug], :method_type => :deferrable, :success => result }
52
+ ret.errback { |result| send_data :deferrable_id => hash[:deferrable_id], :debug => hash[:debug], :method_type => :deferrable, :error => result }
53
+ else
54
+ send_data :deferrable_id => hash[:deferrable_id], :success => ret, :method_type => :returned, :debug => hash[:debug]
47
55
  end
48
56
 
49
57
  rescue => e
50
58
  puts "#{e}: #{e.message}"
51
- send_data( { :deferrable_id => hash[:deferrable_id], :error => {:class => e.class.name, :message => e.message} } )
59
+ send_data :deferrable_id => hash[:deferrable_id], :error => {:class => e.class.name, :message => e.message}, :method_type => :rescue, :debug => hash[:debug]
52
60
  end
53
61
  end
@@ -1,3 +1,3 @@
1
1
  module EmRemoteCall
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -15,43 +15,54 @@ class Track
15
15
  end
16
16
  end
17
17
 
18
+ TEST_SOCKET = File.join( File.expand_path(File.dirname(__FILE__)), 'test_socket' )
19
+
18
20
  class ServerTrack < Track
19
21
  is_a_collection
20
22
 
21
- def initialize(opts, &callb)
22
- callb.call
23
+ def initialize(opts={}, &callb)
24
+ callb.call if callb
23
25
  super
24
26
  end
25
27
 
28
+ # takes a block:
26
29
  def play(&callb)
27
30
  callb.call "finished #{id}"
28
31
  "started #{id}"
29
32
  end
33
+
34
+ # raises:
30
35
  def raise_hell
31
36
  raise 'foobar'
32
37
  end
38
+
39
+ # returns a deferrable:
33
40
  def with_deferrable(outcome = 'succeed') # does not take a block
34
41
  d = EventMachine::DefaultDeferrable.new
35
42
  d.send outcome
36
43
  return d
37
44
  end
38
45
 
39
- def self.some_class_meth
40
- yield
46
+ # doesn't take a block, just returns a hash:
47
+ def as_hash
48
+ {:title => title, :artist => artist}
49
+ end
50
+
51
+ # a class method:
52
+ def self.some_class_meth(&blk)
53
+ blk.call
41
54
  end
42
55
  end
43
56
 
44
57
  class ClientTrack < Track
45
- extend EM::RemoteCall
46
- remote_method :init_track_on_server, :class_name => 'ServerTrack', :calls => :new
47
- remote_method :play, :class_name => 'ServerTrack', :find_by => :id
48
- remote_method :raise_hell, :class_name => 'ServerTrack', :find_by => :id
49
- remote_method :with_deferrable, :class_name => 'ServerTrack', :find_by => :id
58
+ has_em_remote_class 'ServerTrack', :socket => TEST_SOCKET
50
59
 
51
- class << self
52
- extend EM::RemoteCall
53
- remote_method :some_class_meth, :class_name => 'ServerTrack'
54
- end
60
+ remote_method :init_track_on_server, :calls => :new, :server_class_method => true
61
+ remote_method :play
62
+ remote_method :raise_hell
63
+ remote_method :with_deferrable
64
+ remote_method :as_hash
65
+ remote_class_method :some_class_meth
55
66
  end
56
67
 
57
68
  class EMController
@@ -60,14 +71,11 @@ class EMController
60
71
  end
61
72
 
62
73
  def test_on_client
63
- socket = File.join( File.expand_path(File.dirname(__FILE__)), 'test_socket' )
64
-
65
74
  server_pid = EM.fork_reactor do
66
- EM::RemoteCall::Server.start_at socket
75
+ EM::RemoteCall::Server.start_at TEST_SOCKET
67
76
  end
68
77
  sleep 0.1
69
78
  EM.run do
70
- ClientTrack.remote_connection = EM::RemoteCall::Client.connect_to socket
71
79
  yield
72
80
  EM.add_timer 0.1 do
73
81
  Process.kill 'HUP', server_pid
@@ -82,39 +90,39 @@ describe EM::RemoteCall do
82
90
  test_on_client do
83
91
  callb = mock(:callb)
84
92
  callb.should_receive(:foo)
85
- ClientTrack.new.init_track_on_server({}){callb.foo}
93
+ ClientTrack.new.init_track_on_server{callb.foo}
86
94
  end
87
95
  end
88
96
  end
89
- describe "instance method callbacks" do
90
- it "should be called" do
97
+ describe "class method callbacks too" do
98
+ it "should work twice" do
91
99
  test_on_client do
92
100
  callb = mock(:callb)
93
- callb.should_receive(:foo).with('finished a - b')
94
- c = ClientTrack.new(:title => 'a', :artist => 'b')
95
- c.init_track_on_server(:title => 'a', :artist => 'b')
96
- c.play{|a| callb.foo a}
101
+ callb.should_receive(:foo).twice
102
+ ClientTrack.new.init_track_on_server{callb.foo}
103
+ ClientTrack.new.init_track_on_server{callb.foo}
97
104
  end
98
105
  end
99
106
  end
100
- describe "errbacks" do
101
- it "should take an errback method" do
107
+ describe "client side class method" do
108
+ it "should work :)" do
102
109
  test_on_client do
103
110
  callb = mock(:callb)
104
- callb.should_receive(:foo).with({:class=>"RuntimeError", :message=>"foobar"})
105
- c = ClientTrack.new(:title => 'a', :artist => 'b')
106
- c.init_track_on_server(:title => 'a', :artist => 'b')
107
- play_call = c.raise_hell
108
- play_call.errback{|a| callb.foo a}
111
+ callb.should_receive(:foo)
112
+ ClientTrack.some_class_meth{callb.foo}
109
113
  end
110
114
  end
111
115
  end
112
- describe "client side class method" do
113
- it "should work :)" do
116
+ describe "without block or deferrable" do
117
+ it "should return just the return value" do
114
118
  test_on_client do
115
119
  callb = mock(:callb)
116
- callb.should_receive(:foo)
117
- ClientTrack.some_class_meth{callb.foo}
120
+ properties = {:artist => 'a', :title => 't'}
121
+ callb.should_receive(:foo).with(properties)
122
+ c = ClientTrack.new properties
123
+ c.init_track_on_server properties do
124
+ c.as_hash{|r| callb.foo(r)}
125
+ end
118
126
  end
119
127
  end
120
128
  end
@@ -124,9 +132,9 @@ describe EM::RemoteCall do
124
132
  it "should use the block as callback" do
125
133
  test_on_client do
126
134
  callb = mock(:callb)
127
- callb.should_receive(:foo).with()
135
+ callb.should_receive(:foo)
128
136
  c = ClientTrack.new
129
- c.init_track_on_server({})
137
+ c.init_track_on_server
130
138
  c.with_deferrable(:succeed){ callb.foo }
131
139
  end
132
140
  end
@@ -135,9 +143,9 @@ describe EM::RemoteCall do
135
143
  it "should use callback" do
136
144
  test_on_client do
137
145
  callb = mock(:callb)
138
- callb.should_receive(:foo).with()
146
+ callb.should_receive(:foo)
139
147
  c = ClientTrack.new
140
- c.init_track_on_server({})
148
+ c.init_track_on_server
141
149
  play_call = c.with_deferrable(:succeed)
142
150
  play_call.callback{ callb.foo }
143
151
  end
@@ -148,9 +156,9 @@ describe EM::RemoteCall do
148
156
  it "should use errback" do
149
157
  test_on_client do
150
158
  callb = mock(:callb)
151
- callb.should_receive(:foo).with()
159
+ callb.should_receive(:foo)
152
160
  c = ClientTrack.new
153
- c.init_track_on_server({})
161
+ c.init_track_on_server
154
162
  play_call = c.with_deferrable(:fail)
155
163
  play_call.errback{ callb.foo }
156
164
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 6
9
- version: 0.0.6
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Niko Dittmann
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-23 00:00:00 +01:00
17
+ date: 2010-12-27 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency