rjr 0.11.7 → 0.12.2

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/bin/rjr-client CHANGED
@@ -67,7 +67,7 @@ optparse = OptionParser.new do |opts|
67
67
  end
68
68
 
69
69
  opts.on('--message ID', 'Message to send to server (rand to select random)') do |mid|
70
- config[:msg_id] = mid
70
+ config[:msg_id] = mid.intern
71
71
  end
72
72
 
73
73
  opts.on('--interval seconds', 'Number of seconds after which to wait between requests (or rand)') do |s|
@@ -8,12 +8,12 @@ ID_OFFSET = ARGV.shift.to_i || 100
8
8
 
9
9
  NUM_CLIENTS = 5
10
10
  NUM_MSGS = 20 # per client
11
+ MSG_ID = :rand
11
12
  NODE_ID = 'rjr_test_launcher-'
12
- MSG_IDS = ['stress', 'stress_callback']
13
- TRANSPORTS = {#:amqp => 'rjr_test_server-queue',
14
- #:tcp => 'jsonrpc://localhost:8181',
13
+ TRANSPORTS = {:amqp => 'rjr_test_server-queue',
14
+ :tcp => 'jsonrpc://localhost:8181',
15
15
  :ws => 'jsonrpc://localhost:8080',
16
- #:www => 'http://localhost:8888'
16
+ :www => 'http://localhost:8888'
17
17
  }
18
18
  BROKER = 'localhost' # only used for amqp
19
19
  MSG_INTERVAL= 3
@@ -27,11 +27,10 @@ threads = []
27
27
  dst = TRANSPORTS[transport]
28
28
  mode = rand(2) == 0 ? :msg : :rand
29
29
  node_id = NODE_ID + (i + ID_OFFSET).to_s
30
- msg_id = MSG_IDS[rand(MSG_IDS.size)]
31
30
 
32
31
  threads <<
33
32
  Thread.new{
34
- system("#{CLIENT} -m #{mode} -t #{transport} -i #{node_id} -b #{BROKER} --dst #{dst} -n #{NUM_MSGS} --message #{msg_id} --interval #{MSG_INTERVAL}")
33
+ system(ENV, "#{CLIENT} -m #{mode} -t #{transport} -i #{node_id} -b #{BROKER} --dst #{dst} -n #{NUM_MSGS} --message #{MSG_ID} --interval #{MSG_INTERVAL}")
35
34
  }
36
35
  }
37
36
 
data/lib/rjr/amqp_node.rb CHANGED
@@ -21,6 +21,7 @@ else
21
21
  require 'rjr/node'
22
22
  require 'rjr/message'
23
23
  require 'rjr/dispatcher'
24
+ require 'rjr/errors'
24
25
  require 'rjr/thread_pool2'
25
26
 
26
27
  module RJR
@@ -309,17 +310,18 @@ class AMQPNode < RJR::Node
309
310
  published_l = Mutex.new
310
311
  published_c = ConditionVariable.new
311
312
 
313
+ invoked = false
312
314
  message = NotificationMessage.new :method => rpc_method,
313
315
  :args => args,
314
316
  :headers => @message_headers
315
317
  em_run do
316
318
  init_node {
317
319
  publish(message.to_s, :routing_key => routing_key, :reply_to => @queue_name){
318
- published_l.synchronize { published_c.signal }
320
+ published_l.synchronize { invoked = true ; published_c.signal }
319
321
  }
320
322
  }
321
323
  end
322
- published_l.synchronize { published_c.wait published_l }
324
+ published_l.synchronize { published_c.wait published_l unless invoked }
323
325
  nil
324
326
  end
325
327
 
data/lib/rjr/inspect.rb CHANGED
@@ -52,9 +52,8 @@ rjr_method \
52
52
  {
53
53
  # event machine
54
54
  :event_machine => { :running => EMAdapter.running?,
55
- :has_jobs => EMAdapter.has_jobs?,
56
55
  :thread_status => EMAdapter.reactor_thread.status,
57
- :jobs => EMAdapter.em_jobs },
56
+ :connections => EventMachine.connection_count },
58
57
 
59
58
  # thread pool
60
59
  :thread_pool => { :running => ThreadPool2Manager.thread_pool.running?,
@@ -8,6 +8,7 @@
8
8
  require 'rjr/node'
9
9
  require 'rjr/message'
10
10
  require 'rjr/dispatcher'
11
+ require 'rjr/errors'
11
12
 
12
13
  module RJR
13
14
 
@@ -23,8 +24,11 @@ class LocalNodeCallback
23
24
  # Implementation of {RJR::NodeCallback#invoke}
24
25
  def invoke(callback_method, *data)
25
26
  # TODO any exceptions from handler will propagate here, surround w/ begin/rescue block
26
- @node.invoke_request(callback_method, *data)
27
- # TODO support local_node 'disconnections'
27
+ # TODO support local_node 'disconnections' via RJR::ConnectionError & triggering mechanism
28
+ ThreadPool2Manager <<
29
+ ThreadPool2Job.new(callback_method, data) { |m|
30
+ @node.local_dispatch(callback_method, *data)
31
+ }
28
32
  end
29
33
  end
30
34
 
@@ -50,6 +54,43 @@ class LocalNode < RJR::Node
50
54
  # allows clients to override the node type for the local node
51
55
  attr_accessor :node_type
52
56
 
57
+ # Helper method to locally dispatch method/args
58
+ #
59
+ # TODO would like to make private but needed in LocalNodeCallback
60
+ def local_dispatch(rpc_method, *args)
61
+ # create request from args
62
+ 0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
63
+ message = RequestMessage.new :method => rpc_method,
64
+ :args => args,
65
+ :headers => @message_headers
66
+
67
+ # here we serialize / unserialze messages to/from json to
68
+ # ensure local node complies to same json-rpc restrictions as other nodes
69
+ message = RequestMessage.new :message => message.to_s,
70
+ :headers => @message_headers
71
+
72
+ result = Dispatcher.dispatch_request(message.jr_method,
73
+ :method_args => message.jr_args,
74
+ :headers => @message_headers,
75
+ :rjr_node => self,
76
+ :rjr_node_id => @node_id,
77
+ :rjr_node_type => @node_type,
78
+ :rjr_callback =>
79
+ LocalNodeCallback.new(:node => self,
80
+ :headers => @message_headers))
81
+
82
+ # create response message from result
83
+ response = ResponseMessage.new(:id => message.msg_id,
84
+ :result => result,
85
+ :headers => @message_headers)
86
+
87
+ # same comment on serialization/unserialization as above
88
+ response = ResponseMessage.new(:message => response.to_s,
89
+ :headers => @message_headers)
90
+
91
+ response
92
+ end
93
+
53
94
  # LocalNode initializer
54
95
  # @param [Hash] args the options to create the local node with
55
96
  def initialize(args = {})
@@ -71,44 +112,39 @@ class LocalNode < RJR::Node
71
112
  #
72
113
  # Currently does nothing as method handlers can be invoked directly upon invoke_request
73
114
  def listen
74
- em_run do
75
- end
76
115
  end
77
116
 
78
117
  # Instructs node to send rpc request, and wait for and return response
118
+ #
119
+ # If strictly confirming to other nodes, use event machine to launch
120
+ # a thread pool job to dispatch request and block on result.
121
+ # Optimized for performance reasons but recognize the semantics of using
122
+ # the local node will be somewhat different.
123
+ #
79
124
  # @param [String] rpc_method json-rpc method to invoke on destination
80
125
  # @param [Array] args array of arguments to convert to json and invoke remote method wtih
81
126
  # @return [Object] the json result retrieved from destination converted to a ruby object
82
127
  # @raise [Exception] if the destination raises an exception, it will be converted to json and re-raised here
83
128
  def invoke_request(rpc_method, *args)
84
- 0.upto(args.size).each { |i| args[i] = args[i].to_s if args[i].is_a?(Symbol) }
85
- message = RequestMessage.new :method => rpc_method,
86
- :args => args,
87
- :headers => @message_headers
88
-
89
- # we serialize / unserialze messages to ensure local node complies
90
- # to same json-rpc restrictions as other nodes
91
- message = RequestMessage.new :message => message.to_s,
92
- :headers => @message_headers
93
-
94
- result = Dispatcher.dispatch_request(message.jr_method,
95
- :method_args => message.jr_args,
96
- :headers => @message_headers,
97
- :rjr_node => self,
98
- :rjr_node_id => @node_id,
99
- :rjr_node_type => @node_type,
100
- :rjr_callback =>
101
- LocalNodeCallback.new(:node => self,
102
- :headers => @message_headers))
103
- response = ResponseMessage.new(:id => message.msg_id,
104
- :result => result,
105
- :headers => @message_headers)
129
+ res = local_dispatch(rpc_method, *args)
130
+ return Dispatcher.handle_response(res.result)
131
+ end
106
132
 
107
- # same comment on serialization/unserialization as above
108
- response = ResponseMessage.new(:message => response.to_s,
109
- :headers => @message_headers)
110
- return Dispatcher.handle_response(response.result)
133
+ # Instructs node to send rpc notification (immediately returns / no response is generated)
134
+ #
135
+ # Same performance comment as invoke_request above
136
+ #
137
+ # @param [String] rpc_method json-rpc method to invoke on destination
138
+ # @param [Array] args array of arguments to convert to json and invoke remote method wtih
139
+ def send_notification(rpc_method, *args)
140
+ # TODO run in thread & immediately return?
141
+ begin
142
+ local_dispatch(rpc_method, *args)
143
+ rescue
144
+ end
145
+ nil
111
146
  end
112
147
 
148
+
113
149
  end
114
150
  end
data/lib/rjr/message.rb CHANGED
@@ -176,7 +176,7 @@ class ResponseMessage
176
176
  json.has_key?('result') || json.has_key?('error')
177
177
  rescue Exception => e
178
178
  # FIXME log error
179
- #puts e.to_s
179
+ puts e.to_s
180
180
  false
181
181
  end
182
182
  end
data/lib/rjr/tcp_node.rb CHANGED
@@ -13,6 +13,7 @@ require 'rjr/node'
13
13
  require 'rjr/message'
14
14
  require 'rjr/message'
15
15
  require 'rjr/dispatcher'
16
+ require 'rjr/errors'
16
17
  require 'rjr/thread_pool2'
17
18
 
18
19
  module RJR
@@ -37,7 +38,7 @@ class TCPNodeCallback
37
38
  # Implementation of {RJR::NodeCallback#invoke}
38
39
  def invoke(callback_method, *data)
39
40
  msg = NotificationMessage.new :method => callback_method, :args => data, :headers => @message_headers
40
- # TODO surround w/ begin/rescue block incase of socket errors
41
+ # TODO surround w/ begin/rescue block incase of socket errors / raise RJR::ConnectionError
41
42
  @endpoint.safe_send msg.to_s
42
43
  end
43
44
  end
@@ -298,6 +299,7 @@ class TCPNode < RJR::Node
298
299
  uri = URI.parse(uri)
299
300
  host,port = uri.host, uri.port
300
301
 
302
+ invoked = false
301
303
  conn = nil
302
304
  message = NotificationMessage.new :method => rpc_method,
303
305
  :args => args,
@@ -309,10 +311,10 @@ class TCPNode < RJR::Node
309
311
  c.safe_send message.to_s
310
312
  # XXX big bug w/ tcp node, this should be invoked only when
311
313
  # we are sure event machine sent message
312
- published_l.synchronize { published_c.signal }
314
+ published_l.synchronize { invoked = true ; published_c.signal }
313
315
  }
314
316
  }
315
- published_l.synchronize { published_c.wait published_l }
317
+ published_l.synchronize { published_c.wait published_l unless invoked }
316
318
  #sleep 0.01 until conn.get_outbound_data_size == 0
317
319
  nil
318
320
  end
@@ -213,6 +213,7 @@ to#{@timeout}"
213
213
  # Add work to the pool
214
214
  # @param [ThreadPool2Job] work job to execute in first available thread
215
215
  def <<(work)
216
+ # TODO option to increase worker threads if work queue gets saturated
216
217
  @work_queue.push work
217
218
  end
218
219
 
data/lib/rjr/util.rb CHANGED
@@ -32,7 +32,7 @@ module Definitions
32
32
  }
33
33
  nil
34
34
  else
35
- RJR::Definitions.message(args)
35
+ RJR::Definitions.message(args.to_s)
36
36
  end
37
37
  end
38
38
 
data/lib/rjr/web_node.rb CHANGED
@@ -247,16 +247,17 @@ class WebNode < RJR::Node
247
247
  published_l = Mutex.new
248
248
  published_c = ConditionVariable.new
249
249
 
250
+ invoked = false
250
251
  message = NotificationMessage.new :method => rpc_method,
251
252
  :args => args,
252
253
  :headers => @message_headers
253
- cb = lambda { |arg| published_l.synchronize { published_c.signal }}
254
+ cb = lambda { |arg| published_l.synchronize { invoked = true ; published_c.signal }}
254
255
  em_run do
255
256
  http = EventMachine::HttpRequest.new(uri).post :body => message.to_s
256
257
  http.errback &cb
257
258
  http.callback &cb
258
259
  end
259
- published_l.synchronize { published_c.wait published_l }
260
+ published_l.synchronize { published_c.wait published_l unless invoked }
260
261
  nil
261
262
  end
262
263
  end
data/lib/rjr/ws_node.rb CHANGED
@@ -23,6 +23,7 @@ require 'socket'
23
23
  require 'rjr/node'
24
24
  require 'rjr/message'
25
25
  require 'rjr/dispatcher'
26
+ require 'rjr/errors'
26
27
  require 'rjr/thread_pool2'
27
28
 
28
29
  module RJR
@@ -265,6 +266,7 @@ class WSNode < RJR::Node
265
266
  published_l = Mutex.new
266
267
  published_c = ConditionVariable.new
267
268
 
269
+ invoked = false
268
270
  message = NotificationMessage.new :method => rpc_method,
269
271
  :args => args,
270
272
  :headers => @message_headers
@@ -275,10 +277,10 @@ class WSNode < RJR::Node
275
277
  # XXX same bug w/ tcp node, due to nature of event machine
276
278
  # we aren't guaranteed that message is actually written to socket
277
279
  # here, process must be kept alive until data is sent or will be lost
278
- published_l.synchronize { published_c.signal }
280
+ published_l.synchronize { invoked = true ; published_c.signal }
279
281
  end
280
282
  }
281
- published_l.synchronize { published_c.wait published_l }
283
+ published_l.synchronize { published_c.wait published_l unless invoked }
282
284
  nil
283
285
  end
284
286
  end
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.11.7
4
+ version: 0.12.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-12 00:00:00.000000000 Z
12
+ date: 2013-04-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec