rjr 0.7.0 → 0.8.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/README.md +144 -0
- data/Rakefile +5 -5
- data/bin/rjr-server +2 -1
- data/lib/rjr.rb +3 -0
- data/lib/rjr/amqp_node.rb +103 -52
- data/lib/rjr/common.rb +19 -3
- data/lib/rjr/dispatcher.rb +103 -7
- data/lib/rjr/errors.rb +5 -3
- data/lib/rjr/local_node.rb +38 -12
- data/lib/rjr/message.rb +56 -1
- data/lib/rjr/multi_node.rb +31 -4
- data/lib/rjr/node.rb +57 -8
- data/lib/rjr/tcp_node.rb +65 -11
- data/lib/rjr/thread_pool.rb +33 -9
- data/lib/rjr/web_node.rb +72 -20
- data/lib/rjr/ws_node.rb +54 -12
- metadata +35 -2
- data/README.rdoc +0 -73
data/lib/rjr/ws_node.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# RJR WebSockets Endpoint
|
2
2
|
#
|
3
|
+
# Implements the RJR::Node interface to satisty JSON-RPC requests over the websockets protocol
|
4
|
+
#
|
3
5
|
# Copyright (C) 2012 Mohammed Morsi <mo@morsi.org>
|
4
6
|
# Licensed under the Apache License, Version 2.0
|
5
7
|
|
6
|
-
# establish client connection w/ specified args and invoke block w/
|
7
|
-
# newly created client, returning it after block terminates
|
8
|
-
|
9
8
|
require 'em-websocket'
|
10
9
|
require 'rjr/web_socket'
|
11
10
|
|
@@ -14,14 +13,23 @@ require 'rjr/message'
|
|
14
13
|
|
15
14
|
module RJR
|
16
15
|
|
17
|
-
# Web Socket
|
18
|
-
#
|
16
|
+
# Web Socket node callback interface, used to invoke json-rpc methods
|
17
|
+
# against a remote node via a web socket connection previously established
|
18
|
+
#
|
19
|
+
# After a node sends a json-rpc request to another, the either node may send
|
20
|
+
# additional requests to each other via the socket already established until
|
21
|
+
# it is closed on either end
|
19
22
|
class WSNodeCallback
|
23
|
+
# WSNodeCallback initializer
|
24
|
+
# @param [Hash] args the options to create the websocket node callback with
|
25
|
+
# @option args [Socket] :socket socket connection used to send/receive messages
|
26
|
+
# @option args [Hash] :headers hash of rjr message headers present in client request when callback is established
|
20
27
|
def initialize(args = {})
|
21
28
|
@socket = args[:socket]
|
22
29
|
@message_headers = args[:headers]
|
23
30
|
end
|
24
31
|
|
32
|
+
# Implementation of {RJR::NodeCallback#invoke}
|
25
33
|
def invoke(callback_method, *data)
|
26
34
|
#msg = CallbackMessage.new(:data => data)
|
27
35
|
msg = RequestMessage.new :method => callback_method, :args => data, :headers => @message_headers
|
@@ -31,11 +39,37 @@ class WSNodeCallback
|
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
34
|
-
# Web node definition, listen for and invoke json-rpc requests via web sockets
|
42
|
+
# Web socket node definition, listen for and invoke json-rpc requests via web sockets
|
43
|
+
#
|
44
|
+
# Clients should specify the hostname / port when listening for and invoking requests.
|
45
|
+
#
|
46
|
+
# *note* the RJR javascript client also supports sending / receiving json-rpc
|
47
|
+
# messages over web sockets
|
48
|
+
#
|
49
|
+
# @example Listening for json-rpc requests over tcp
|
50
|
+
# # register rjr dispatchers (see RJR::Dispatcher)
|
51
|
+
# RJR::Dispatcher.add_handler('hello') { |name|
|
52
|
+
# "Hello #{name}!"
|
53
|
+
# }
|
54
|
+
#
|
55
|
+
# # initialize node, listen, and block
|
56
|
+
# server = RJR::WSNode.new :node_id => 'server', :host => 'localhost', :port => '7777'
|
57
|
+
# server.listen
|
58
|
+
# server.join
|
59
|
+
#
|
60
|
+
# @example Invoking json-rpc requests over web sockets using rjr
|
61
|
+
# client = RJR::WsNode.new :node_id => 'client'
|
62
|
+
# puts client.invoke_request('ws://localhost:7777', 'hello', 'mo')
|
63
|
+
#
|
35
64
|
class WSNode < RJR::Node
|
36
65
|
RJR_NODE_TYPE = :websockets
|
37
66
|
|
38
67
|
private
|
68
|
+
# Initialize the ws subsystem
|
69
|
+
def init_node
|
70
|
+
end
|
71
|
+
|
72
|
+
# Internal helper, handle request message received
|
39
73
|
def handle_request(socket, message)
|
40
74
|
client_port, client_ip = Socket.unpack_sockaddr_in(socket.get_peername)
|
41
75
|
msg = RequestMessage.new(:message => message, :headers => @message_headers)
|
@@ -56,7 +90,10 @@ class WSNode < RJR::Node
|
|
56
90
|
end
|
57
91
|
|
58
92
|
public
|
59
|
-
#
|
93
|
+
# WSNode initializer
|
94
|
+
# @param [Hash] args the options to create the web socket node with
|
95
|
+
# @option args [String] :host the hostname/ip which to listen on
|
96
|
+
# @option args [Integer] :port the port which to listen on
|
60
97
|
def initialize(args = {})
|
61
98
|
super(args)
|
62
99
|
@host = args[:host]
|
@@ -65,18 +102,19 @@ class WSNode < RJR::Node
|
|
65
102
|
@connection_event_handlers = {:closed => [], :error => []}
|
66
103
|
end
|
67
104
|
|
68
|
-
#
|
105
|
+
# Register connection event handler
|
106
|
+
# @param [:error, :close] event the event to register the handler for
|
107
|
+
# @param [Callable] handler block param to be added to array of handlers that are called when event occurs
|
108
|
+
# @yield [WSNode] self is passed to each registered handler when event occurs
|
69
109
|
def on(event, &handler)
|
70
110
|
if @connection_event_handlers.keys.include?(event)
|
71
111
|
@connection_event_handlers[event] << handler
|
72
112
|
end
|
73
113
|
end
|
74
114
|
|
75
|
-
# Initialize the ws subsystem
|
76
|
-
def init_node
|
77
|
-
end
|
78
|
-
|
79
115
|
# Instruct Node to start listening for and dispatching rpc requests
|
116
|
+
#
|
117
|
+
# Implementation of {RJR::Node#listen}
|
80
118
|
def listen
|
81
119
|
em_run do
|
82
120
|
init_node
|
@@ -100,6 +138,10 @@ class WSNode < RJR::Node
|
|
100
138
|
end
|
101
139
|
|
102
140
|
# Instructs node to send rpc request, and wait for / return response
|
141
|
+
# @param [String] uri location of node to send request to, should be
|
142
|
+
# in format of ws://hostname:port
|
143
|
+
# @param [String] rpc_method json-rpc method to invoke on destination
|
144
|
+
# @param [Array] args array of arguments to convert to json and invoke remote method wtih
|
103
145
|
def invoke_request(uri, rpc_method, *args)
|
104
146
|
init_node
|
105
147
|
message = RequestMessage.new :method => rpc_method,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rjr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.3.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: eventmachine
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: json
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
30
62
|
description: Ruby Json Rpc library
|
31
63
|
email: mo@morsi.org
|
32
64
|
executables:
|
@@ -61,7 +93,7 @@ files:
|
|
61
93
|
- specs/message_spec.rb
|
62
94
|
- LICENSE
|
63
95
|
- Rakefile
|
64
|
-
- README.
|
96
|
+
- README.md
|
65
97
|
- bin/rjr-server
|
66
98
|
homepage: http://github.com/movitto/rjr
|
67
99
|
licenses: []
|
@@ -88,3 +120,4 @@ signing_key:
|
|
88
120
|
specification_version: 3
|
89
121
|
summary: JSON RPC server and client library over amqp, websockets, http, etc
|
90
122
|
test_files: []
|
123
|
+
has_rdoc:
|
data/README.rdoc
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
== RJR - Ruby Json Rpc Library
|
2
|
-
|
3
|
-
Copyright (C) 2012 Mo Morsi <mo@morsi.org>
|
4
|
-
|
5
|
-
RJR is made available under the GNU AFFERO GENERAL PUBLIC LICENSE
|
6
|
-
as published by the Free Software Foundation, either version 3
|
7
|
-
of the License, or (at your option) any later version.
|
8
|
-
|
9
|
-
=== Intro
|
10
|
-
To install rjr simply run:
|
11
|
-
gem install rjr
|
12
|
-
|
13
|
-
Source code is available via:
|
14
|
-
git clone http://github.com/movitto/rjr
|
15
|
-
|
16
|
-
=== Using
|
17
|
-
|
18
|
-
Simply require rubygems and the rjr library
|
19
|
-
|
20
|
-
require 'rubygems'
|
21
|
-
require 'rjr'
|
22
|
-
|
23
|
-
server.rb:
|
24
|
-
|
25
|
-
# define a rpc method called 'hello' which takes
|
26
|
-
# one argument and returns it in upper case
|
27
|
-
RJR::Dispatcher.add_handler("hello") { |arg|
|
28
|
-
arg.upcase
|
29
|
-
}
|
30
|
-
|
31
|
-
# listen for this method via amqp, websockets, http, and via local calls
|
32
|
-
amqp_node = RJR::AMQPNode.new :node_id => 'server', :broker => 'localhost'
|
33
|
-
ws_node = RJR::WSNode.new :node_id => 'server', :host => 'localhost', :port => 8080
|
34
|
-
www_node = RJR::WebNode.new :node_id => 'server', :host => 'localhost', :port => 8888
|
35
|
-
local_node = RJR::LocalNode.new :node_id => 'server'
|
36
|
-
|
37
|
-
# start the server and block
|
38
|
-
multi_node = RJR::MultiNode.new :nodes => [amqp_node, ws_node, www_node, local_node]
|
39
|
-
multi_node.listen
|
40
|
-
multi_node.join
|
41
|
-
|
42
|
-
|
43
|
-
amqp_client.rb:
|
44
|
-
|
45
|
-
# invoke the method over amqp
|
46
|
-
amqp_node = RJR::AMQPNode.new :node_id => 'client', :broker => 'localhost'
|
47
|
-
puts amqp_node.invoke_request('server-queue', 'hello', 'world')
|
48
|
-
|
49
|
-
|
50
|
-
ws_client.js:
|
51
|
-
|
52
|
-
// use the js client to invoke the method via a websocket
|
53
|
-
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
|
54
|
-
<script type="text/javascript" src="site/json.js" />
|
55
|
-
<script type="text/javascript" src="site/jrw.js" />
|
56
|
-
<script type="text/javascript">
|
57
|
-
var node = new WSNode('127.0.0.1', '8080');
|
58
|
-
node.onopen = function(){
|
59
|
-
node.invoke_request('hello', 'rjr');
|
60
|
-
};
|
61
|
-
node.onsuccess = function(result){
|
62
|
-
alert(result);
|
63
|
-
};
|
64
|
-
node.open();
|
65
|
-
</script>
|
66
|
-
|
67
|
-
Generate documentation via
|
68
|
-
rake rdoc
|
69
|
-
|
70
|
-
Also see specs for detailed usage.
|
71
|
-
|
72
|
-
=== Authors
|
73
|
-
Mo Morsi <mo@morsi.org>
|