rexec 1.2.6 → 1.3.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.
- data/lib/rexec/connection.rb +68 -1
- data/lib/rexec/version.rb +2 -2
- data/test/client.rb +8 -0
- data/test/remote_server_test.rb +39 -26
- metadata +4 -4
data/lib/rexec/connection.rb
CHANGED
@@ -4,8 +4,61 @@
|
|
4
4
|
# This class is as small and independant as possible as it will get sent to clients for execution.
|
5
5
|
|
6
6
|
require 'thread'
|
7
|
+
require 'monitor'
|
7
8
|
|
8
9
|
module RExec
|
10
|
+
|
11
|
+
# A wrapper for sending method invocations over a Connection
|
12
|
+
class Invocation
|
13
|
+
def initialize(name, arguments)
|
14
|
+
@name = name
|
15
|
+
@arguments = arguments
|
16
|
+
end
|
17
|
+
|
18
|
+
def apply(object)
|
19
|
+
object.send(@name, *@arguments)
|
20
|
+
end
|
21
|
+
|
22
|
+
class Result
|
23
|
+
def initialize(value)
|
24
|
+
@value = value
|
25
|
+
end
|
26
|
+
|
27
|
+
attr :value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# A proxy class to create and send Invocation objects via a Connection, and receive a result.
|
32
|
+
class Proxy
|
33
|
+
def initialize(connection)
|
34
|
+
@connection = connection
|
35
|
+
|
36
|
+
@method_mutex = Mutex.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, *arguments)
|
40
|
+
invocation = Invocation.new(name, arguments)
|
41
|
+
result = nil
|
42
|
+
|
43
|
+
# Connection provides no transaction support. This means that
|
44
|
+
# if multiple threads are sending and receiving arbirary objects
|
45
|
+
# via the connection, the Proxy object may fail due to out of
|
46
|
+
# line objects.
|
47
|
+
@method_mutex.synchronize do
|
48
|
+
# Send the invocation.
|
49
|
+
@connection.send_object(invocation)
|
50
|
+
|
51
|
+
# Wait for the result.
|
52
|
+
result = @connection.receive_object
|
53
|
+
end
|
54
|
+
|
55
|
+
if Invocation::Result === result
|
56
|
+
return result.value
|
57
|
+
else
|
58
|
+
raise InvalidResponse.new("Invalid response received: #{result}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
9
62
|
|
10
63
|
# This class represents an abstract connection to another ruby process. The interface does not impose
|
11
64
|
# any structure on the way this communication link works, except for the fact you can send and receive
|
@@ -44,8 +97,17 @@ module RExec
|
|
44
97
|
|
45
98
|
@receive_mutex = Mutex.new
|
46
99
|
@send_mutex = Mutex.new
|
100
|
+
|
101
|
+
@proxy = Proxy.new(self)
|
102
|
+
@handler = nil
|
47
103
|
end
|
48
104
|
|
105
|
+
# The object that will handle remote proxy invocations.
|
106
|
+
attr :handler, true
|
107
|
+
|
108
|
+
# The proxy object that will dispatch RPCs.
|
109
|
+
attr :proxy
|
110
|
+
|
49
111
|
# The pipe used for reading data
|
50
112
|
def input
|
51
113
|
@input
|
@@ -89,7 +151,12 @@ module RExec
|
|
89
151
|
end
|
90
152
|
|
91
153
|
begin
|
92
|
-
|
154
|
+
if @handler && Invocation === object
|
155
|
+
result = object.apply(@handler)
|
156
|
+
send_object(Invocation::Result.new(result))
|
157
|
+
else
|
158
|
+
yield object
|
159
|
+
end
|
93
160
|
rescue Exception => ex
|
94
161
|
send_object(ex)
|
95
162
|
end
|
data/lib/rexec/version.rb
CHANGED
data/test/client.rb
CHANGED
@@ -18,6 +18,14 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
|
+
module RemoteProxy
|
22
|
+
def self.foo
|
23
|
+
return :bar
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
$connection.handler = RemoteProxy
|
28
|
+
|
21
29
|
$connection.run do |object|
|
22
30
|
case(object[0])
|
23
31
|
when :bounce
|
data/test/remote_server_test.rb
CHANGED
@@ -39,30 +39,43 @@ end
|
|
39
39
|
BOUNCE = "Apples and Oranges"
|
40
40
|
|
41
41
|
class RemoteServerTest < Test::Unit::TestCase
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
42
|
+
def test_block_execution
|
43
|
+
code = Pathname.new(__FILE__).dirname + "./client.rb"
|
44
|
+
|
45
|
+
RExec::start_server(code.read, COMMAND) do |conn, pid|
|
46
|
+
conn.send_object([:bounce, BOUNCE])
|
47
|
+
|
48
|
+
assert_equal BOUNCE, conn.receive_object
|
49
|
+
|
50
|
+
conn.dump_errors
|
51
|
+
|
52
|
+
conn.stop
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_result_execution
|
57
|
+
code = Pathname.new(__FILE__).dirname + "./client.rb"
|
58
|
+
|
59
|
+
conn, pid = RExec::start_server(code.read, COMMAND)
|
60
|
+
|
61
|
+
conn.send_object([:bounce, BOUNCE])
|
62
|
+
assert_equal BOUNCE, conn.receive_object
|
63
|
+
|
64
|
+
conn.dump_errors
|
65
|
+
|
66
|
+
conn.stop
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_proxy
|
70
|
+
code = Pathname.new(__FILE__).dirname + "./client.rb"
|
71
|
+
|
72
|
+
conn, pid = RExec::start_server(code.read, COMMAND)
|
73
|
+
|
74
|
+
assert_equal conn.proxy.foo, :bar
|
75
|
+
|
76
|
+
conn.dump_errors
|
77
|
+
|
78
|
+
conn.stop
|
79
|
+
end
|
68
80
|
end
|
81
|
+
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 1.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 1.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Samuel Williams
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-07-
|
17
|
+
date: 2011-07-31 00:00:00 +12:00
|
18
18
|
default_executable: daemon-exec
|
19
19
|
dependencies: []
|
20
20
|
|