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.
@@ -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,3 @@
1
+ module EmRemoteCall
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'eventmachine'
2
+ require 'fiber'
3
+
4
+ require 'em_json_connection'
5
+ require 'is_a_collection'
6
+
7
+ require 'em_remote_call/client'
8
+ require 'em_remote_call/server'
9
+
@@ -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