em_remote_call 0.0.6 → 0.1.0

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