rjr 0.11.7 → 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
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