em_remote_call 0.0.1
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.
- data/lib/em_remote_call/client.rb +68 -0
- data/lib/em_remote_call/server.rb +48 -0
- data/lib/em_remote_call/version.rb +3 -0
- data/lib/em_remote_call.rb +9 -0
- data/spec/integration_spec.rb +93 -0
- metadata +106 -0
@@ -0,0 +1,68 @@
|
|
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
|
8
|
+
end
|
9
|
+
|
10
|
+
define_method name do |*method_opts, &callb|
|
11
|
+
return unless self.class.remote_connection
|
12
|
+
|
13
|
+
if !block_given? && method_opts.last.is_a?(Proc)
|
14
|
+
callb = method_opts.pop
|
15
|
+
end
|
16
|
+
if method_opts.last.is_a? Proc
|
17
|
+
return_block = method_opts.pop
|
18
|
+
end
|
19
|
+
argument = method_opts.shift
|
20
|
+
|
21
|
+
remote_method = opts[:calls] || name
|
22
|
+
klass = opts[:class_name] || self.class.to_s
|
23
|
+
id = opts[:find_by] && send(opts[:find_by]) # when it's nil, it's considered a class method.
|
24
|
+
|
25
|
+
call = {:argument => argument, :instance => {:class => klass, :id => id}, :method => remote_method}
|
26
|
+
self.class.remote_connection.call(call, callb, return_block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class EM::RemoteCall::Callback
|
32
|
+
is_a_collection :object_id
|
33
|
+
|
34
|
+
def initialize(&callb)
|
35
|
+
@callback = callb
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(arg)
|
40
|
+
@callback.call arg
|
41
|
+
remove_from_collection
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module EM::RemoteCall::Client
|
46
|
+
include EM::JsonConnection::Client
|
47
|
+
|
48
|
+
def json_parsed(hash)
|
49
|
+
p hash
|
50
|
+
if id = hash[:callback_id]
|
51
|
+
if callb = EM::RemoteCall::Callback.find(id)
|
52
|
+
callb.call hash[:argument]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def call(call, callb, return_block)
|
58
|
+
if callb
|
59
|
+
callb = EM::RemoteCall::Callback.new(&callb)
|
60
|
+
call.merge!({ :callback_id => callb.object_id })
|
61
|
+
end
|
62
|
+
if return_block
|
63
|
+
return_block = EM::RemoteCall::Callback.new(&return_block)
|
64
|
+
call.merge!({ :return_block_id => return_block.object_id })
|
65
|
+
end
|
66
|
+
send_data call
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module EM::RemoteCall; end
|
2
|
+
|
3
|
+
class EM::RemoteCall::Call
|
4
|
+
def initialize(instance_opts, method, argument)
|
5
|
+
klass = instance_opts[:class] or return false
|
6
|
+
|
7
|
+
@method, @argument = method, argument
|
8
|
+
|
9
|
+
if indentifier = instance_opts[:id]
|
10
|
+
klass = Object.const_defined?(klass) && Object.const_get(klass) or return false
|
11
|
+
@instance = klass.find(indentifier)
|
12
|
+
else
|
13
|
+
@instance = Object.const_defined?(klass) && Object.const_get(klass) or return false
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
@instance && @method && @instance.respond_to?(@method)
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(&callb)
|
23
|
+
unless valid?
|
24
|
+
puts "invalid remote call: :instance => #{@instance}, :method => #{@method}, :argument => #{@argument}"
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
if @argument
|
29
|
+
@instance.__send__ @method, @argument, &callb
|
30
|
+
else
|
31
|
+
@instance.__send__ @method, &callb
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module EM::RemoteCall::Server
|
37
|
+
include EM::JsonConnection::Server
|
38
|
+
|
39
|
+
def json_parsed(hash)
|
40
|
+
p hash
|
41
|
+
remote_call = EM::RemoteCall::Call.new hash[:instance], hash[:method].to_sym, hash[:argument]
|
42
|
+
return_value = remote_call.call do |blk_value|
|
43
|
+
send_data({:callback_id => hash[:callback_id], :argument => blk_value}) if hash[:callback_id]
|
44
|
+
end
|
45
|
+
send_data({:callback_id => hash[:return_block_id], :argument => return_value}) if hash[:return_block_id]
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.expand_path(File.dirname(__FILE__)), '../lib')
|
2
|
+
|
3
|
+
require 'em_remote_call'
|
4
|
+
|
5
|
+
class Track
|
6
|
+
attr_reader :title, :artist
|
7
|
+
|
8
|
+
def initialize(opts)
|
9
|
+
@title, @artist = opts[:title], opts[:artist]
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def id
|
14
|
+
"#{title} - #{artist}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ServerTrack < Track
|
19
|
+
is_a_collection
|
20
|
+
|
21
|
+
def initialize(opts, &callb)
|
22
|
+
callb.call
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def play(&callb)
|
27
|
+
callb.call "finished #{id}"
|
28
|
+
"started #{id}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ClientTrack < Track
|
33
|
+
extend EM::RemoteCall
|
34
|
+
remote_method :init_track_on_server, :class_name => 'ServerTrack', :calls => :new
|
35
|
+
remote_method :play, :class_name => 'ServerTrack', :find_by => :id
|
36
|
+
end
|
37
|
+
|
38
|
+
class EMController
|
39
|
+
extend EM::RemoteCall
|
40
|
+
remote_method :stop, :class_name => 'EM', :calls => :stop
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_on_client
|
44
|
+
socket = File.join( File.expand_path(File.dirname(__FILE__)), 'test_socket' )
|
45
|
+
|
46
|
+
server_pid = EM.fork_reactor do
|
47
|
+
EM::RemoteCall::Server.start_at socket
|
48
|
+
end
|
49
|
+
sleep 0.1
|
50
|
+
EM.run do
|
51
|
+
ClientTrack.remote_connection = EM::RemoteCall::Client.connect_to socket
|
52
|
+
yield
|
53
|
+
EM.add_timer 0.1 do
|
54
|
+
Process.kill 'HUP', server_pid
|
55
|
+
EM.stop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe EM::RemoteCall do
|
61
|
+
describe "class method callbacks" do
|
62
|
+
it "should be called" do
|
63
|
+
test_on_client do
|
64
|
+
callb = mock(:callb)
|
65
|
+
callb.should_receive(:foo)
|
66
|
+
ClientTrack.new({}).init_track_on_server({}){callb.foo}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
describe "instance method callbacks" do
|
71
|
+
it "should be called" do
|
72
|
+
test_on_client do
|
73
|
+
callb = mock(:callb)
|
74
|
+
callb.should_receive(:foo).with('finished a - b')
|
75
|
+
c = ClientTrack.new(:title => 'a', :artist => 'b')
|
76
|
+
c.init_track_on_server(:title => 'a', :artist => 'b')
|
77
|
+
c.play{|a| callb.foo a}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
describe "return values" do
|
82
|
+
it "should be passed to the second proc" do
|
83
|
+
test_on_client do
|
84
|
+
callb = mock(:callb)
|
85
|
+
callb.should_receive(:bar).with('started a - b')
|
86
|
+
c = ClientTrack.new(:title => 'a', :artist => 'b')
|
87
|
+
c.init_track_on_server(:title => 'a', :artist => 'b')
|
88
|
+
c.play proc{|a| callb.bar a}, proc{}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em_remote_call
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Niko Dittmann
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-15 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: eventmachine
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: is_a_collection
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: em_json_connection
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
59
|
+
description: Provides an Eventmachine server/client couple which allows the client to call methods within the server process, including local client-callbacks.
|
60
|
+
email: mail+git@niko-dittmann.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files: []
|
66
|
+
|
67
|
+
files:
|
68
|
+
- lib/em_remote_call/client.rb
|
69
|
+
- lib/em_remote_call/server.rb
|
70
|
+
- lib/em_remote_call/version.rb
|
71
|
+
- lib/em_remote_call.rb
|
72
|
+
- spec/integration_spec.rb
|
73
|
+
has_rdoc: true
|
74
|
+
homepage: http://github.com/niko/em_remote_call
|
75
|
+
licenses: []
|
76
|
+
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project: "[none]"
|
101
|
+
rubygems_version: 1.3.7
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Provides an Eventmachine server/client couple which allows the client to call methods within the server process, including local client-callbacks.
|
105
|
+
test_files:
|
106
|
+
- spec/integration_spec.rb
|