modern_times 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +24 -12
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/examples/README +4 -0
- data/examples/jms.yml +9 -0
- data/examples/requestor/README +4 -2
- data/examples/requestor/manager.rb +3 -2
- data/examples/requestor/request.rb +5 -4
- data/examples/requestor/reverse_echo_worker.rb +3 -2
- data/examples/simple/README +7 -4
- data/examples/simple/bar_worker.rb +4 -1
- data/examples/simple/baz_worker.rb +4 -3
- data/examples/simple/manager.rb +3 -2
- data/examples/simple/publish.rb +6 -5
- data/lib/modern_times.rb +20 -2
- data/lib/modern_times/base/supervisor.rb +14 -21
- data/lib/modern_times/base/supervisor_mbean.rb +4 -6
- data/lib/modern_times/base/worker.rb +17 -26
- data/lib/modern_times/jms.rb +23 -0
- data/lib/modern_times/{hornetq/client.rb → jms/connection.rb} +19 -12
- data/lib/modern_times/jms/publisher.rb +91 -0
- data/lib/modern_times/jms/supervisor.rb +19 -0
- data/lib/modern_times/jms/supervisor_mbean.rb +11 -0
- data/lib/modern_times/jms/worker.rb +166 -0
- data/lib/modern_times/jms_requestor.rb +10 -0
- data/lib/modern_times/jms_requestor/request_handle.rb +33 -0
- data/lib/modern_times/jms_requestor/requestor.rb +45 -0
- data/lib/modern_times/jms_requestor/supervisor.rb +45 -0
- data/lib/modern_times/jms_requestor/supervisor_mbean.rb +21 -0
- data/lib/modern_times/jms_requestor/worker.rb +78 -0
- data/lib/modern_times/manager.rb +14 -9
- data/lib/modern_times/manager_mbean.rb +14 -7
- data/lib/modern_times/marshal_strategy.rb +47 -0
- data/lib/modern_times/marshal_strategy/bson.rb +31 -0
- data/lib/modern_times/marshal_strategy/json.rb +30 -0
- data/lib/modern_times/marshal_strategy/ruby.rb +20 -0
- data/lib/modern_times/marshal_strategy/string.rb +19 -0
- data/lib/modern_times/railsable.rb +17 -74
- data/test/base_test.rb +248 -0
- data/test/jms.yml +8 -0
- data/test/jms_requestor_test.rb +263 -0
- data/test/jms_test.rb +296 -0
- data/test/marshal_strategy_test.rb +39 -0
- metadata +49 -46
- data/examples/requestor/hornetq.yml +0 -14
- data/examples/simple/hornetq.yml +0 -14
- data/lib/modern_times/hornetq.rb +0 -11
- data/lib/modern_times/hornetq/marshal_strategy.rb +0 -3
- data/lib/modern_times/hornetq/marshal_strategy/json.rb +0 -17
- data/lib/modern_times/hornetq/marshal_strategy/ruby.rb +0 -17
- data/lib/modern_times/hornetq/marshal_strategy/string.rb +0 -17
- data/lib/modern_times/hornetq/publisher.rb +0 -65
- data/lib/modern_times/hornetq/supervisor.rb +0 -22
- data/lib/modern_times/hornetq/supervisor_mbean.rb +0 -12
- data/lib/modern_times/hornetq/worker.rb +0 -127
- data/lib/modern_times/hornetq_requestor.rb +0 -9
- data/lib/modern_times/hornetq_requestor/request_handle.rb +0 -49
- data/lib/modern_times/hornetq_requestor/requestor.rb +0 -48
- data/lib/modern_times/hornetq_requestor/worker.rb +0 -29
- data/lib/modern_times/thread.rb +0 -16
- data/test/base/worker_test.rb +0 -38
- data/test/messaging/worker_manager_test.rb +0 -58
- data/test/messaging/worker_test.rb +0 -58
- data/test/worker_manager_test.rb +0 -48
@@ -1,14 +0,0 @@
|
|
1
|
-
server:
|
2
|
-
:uri: hornetq://localhost
|
3
|
-
:data_directory: ./data
|
4
|
-
:persistence_enabled: true
|
5
|
-
:security_enabled: true
|
6
|
-
:cluster_user: myuser
|
7
|
-
:cluster_password: mypassword
|
8
|
-
|
9
|
-
client:
|
10
|
-
:connection:
|
11
|
-
:uri: hornetq://localhost
|
12
|
-
:session:
|
13
|
-
:username: myuser
|
14
|
-
:password: mypassword
|
data/examples/simple/hornetq.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
server:
|
2
|
-
:uri: hornetq://localhost
|
3
|
-
:data_directory: ./data
|
4
|
-
:persistence_enabled: true
|
5
|
-
:security_enabled: true
|
6
|
-
:cluster_user: myuser
|
7
|
-
:cluster_password: mypassword
|
8
|
-
|
9
|
-
client:
|
10
|
-
:connection:
|
11
|
-
:uri: hornetq://localhost
|
12
|
-
:session:
|
13
|
-
:username: myuser
|
14
|
-
:password: mypassword
|
data/lib/modern_times/hornetq.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'modern_times/hornetq/client'
|
2
|
-
require 'modern_times/hornetq/marshal_strategy'
|
3
|
-
require 'modern_times/hornetq/publisher'
|
4
|
-
require 'modern_times/hornetq/supervisor_mbean'
|
5
|
-
require 'modern_times/hornetq/supervisor'
|
6
|
-
require 'modern_times/hornetq/worker'
|
7
|
-
|
8
|
-
module ModernTimes
|
9
|
-
module HornetQ
|
10
|
-
end
|
11
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQ
|
3
|
-
module MarshalStrategy
|
4
|
-
module JSON
|
5
|
-
def marshal(session, object, durable)
|
6
|
-
message = session.create_message(::HornetQ::Client::Message::TEXT_TYPE, durable)
|
7
|
-
message.body = object.to_json
|
8
|
-
message
|
9
|
-
end
|
10
|
-
|
11
|
-
def unmarshal(msg)
|
12
|
-
JSON::Parser.new(msg.body).parse
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQ
|
3
|
-
module MarshalStrategy
|
4
|
-
module Ruby
|
5
|
-
def marshal(session, object, durable)
|
6
|
-
message = session.create_message(::HornetQ::Client::Message::BYTES_TYPE, durable)
|
7
|
-
message.body = ::Marshal.dump(object)
|
8
|
-
message
|
9
|
-
end
|
10
|
-
|
11
|
-
def unmarshal(msg)
|
12
|
-
::Marshal.load(msg.body)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQ
|
3
|
-
module MarshalStrategy
|
4
|
-
module String
|
5
|
-
def marshal(session, object, durable)
|
6
|
-
message = session.create_message(::HornetQ::Client::Message::TEXT_TYPE, durable)
|
7
|
-
message.body = object.to_s
|
8
|
-
message
|
9
|
-
end
|
10
|
-
|
11
|
-
def unmarshal(msg)
|
12
|
-
msg.body
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'hornetq'
|
2
|
-
|
3
|
-
# Protocol independent class to handle Publishing
|
4
|
-
module ModernTimes
|
5
|
-
module HornetQ
|
6
|
-
class Publisher
|
7
|
-
attr_reader :address
|
8
|
-
|
9
|
-
# TODO: Possible performance enhancements on producer
|
10
|
-
# setDisableMessageID()
|
11
|
-
# setDisableMessageTimeStamp()
|
12
|
-
# See http://hornetq.sourceforge.net/docs/hornetq-2.1.2.Final/user-manual/en/html/perf-tuning.html
|
13
|
-
# Create producer pool as per above section 46.6?
|
14
|
-
def initialize(address, options={})
|
15
|
-
@address = address
|
16
|
-
@durable = !!options[:durable]
|
17
|
-
if options[:marshal].nil?
|
18
|
-
marshal_module = MarshalStrategy::Ruby
|
19
|
-
elsif options[:marshal].kind_of? Symbol
|
20
|
-
marshal_module = case options[:marshal]
|
21
|
-
when :ruby then MarshalStrategy::Ruby
|
22
|
-
when :string then MarshalStrategy::String
|
23
|
-
when :json then MarshalStrategy::JSON
|
24
|
-
else raise "Invalid marshal strategy: #{options[:marshal]}"
|
25
|
-
end
|
26
|
-
elsif options[:marshal].kind_of? Module
|
27
|
-
marshal_module = options[:marshal]
|
28
|
-
else
|
29
|
-
raise "Invalid marshal strategy: #{options[:marshal]}"
|
30
|
-
end
|
31
|
-
self.extend marshal_module
|
32
|
-
end
|
33
|
-
|
34
|
-
# Publish the given object to the address.
|
35
|
-
def publish(object, user_id=nil, props={})
|
36
|
-
Client.session_pool.producer(@address) do |session, producer|
|
37
|
-
message = marshal(session, object, @durable)
|
38
|
-
message.user_id = user_id if user_id
|
39
|
-
props.each do |key, value|
|
40
|
-
message.putStringProperty(key, value)
|
41
|
-
end
|
42
|
-
producer.send_with_retry(message)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# For non-configured Rails projects, The above publish method will be overridden to
|
47
|
-
# call this publish method instead which calls all the HornetQ workers that
|
48
|
-
# operate on the given address.
|
49
|
-
def dummy_publish(object)
|
50
|
-
@@worker_instances.each do |worker|
|
51
|
-
if worker.kind_of?(Worker) && worker.address_name == @address
|
52
|
-
ModernTimes.logger.debug "Dummy publishing #{object} to #{worker}"
|
53
|
-
worker.perform(object)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.setup_dummy_publishing(workers)
|
59
|
-
@@worker_instances = workers.map {|worker| worker.new}
|
60
|
-
alias_method :real_publish, :publish
|
61
|
-
alias_method :publish, :dummy_publish
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQ
|
3
|
-
class Supervisor < ModernTimes::Base::Supervisor
|
4
|
-
# Make HornetQ::SupervisorMBean our mbean
|
5
|
-
mbean SupervisorMBean
|
6
|
-
|
7
|
-
attr_reader :message_count
|
8
|
-
|
9
|
-
def initialize(manager, worker_name, supervisor_options, worker_options)
|
10
|
-
super
|
11
|
-
@message_count = 0
|
12
|
-
@message_count_mutex = Mutex.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def incr_message_count
|
16
|
-
@message_count_mutex.synchronize do
|
17
|
-
@message_count += 1
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,127 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQ
|
3
|
-
|
4
|
-
# Base Worker Class for any class that will be processing messages from queues
|
5
|
-
class Worker < ModernTimes::Base::Worker
|
6
|
-
# Default to ruby marshaling, but extenders can override as necessary
|
7
|
-
include MarshalStrategy::Ruby
|
8
|
-
|
9
|
-
# Make HornetQ::Supervisor our supervisor
|
10
|
-
supervisor Supervisor
|
11
|
-
|
12
|
-
attr_reader :session, :message_count
|
13
|
-
|
14
|
-
def initialize(opts={})
|
15
|
-
super
|
16
|
-
@status = 'initialized'
|
17
|
-
@message_count = 0
|
18
|
-
end
|
19
|
-
|
20
|
-
def setup
|
21
|
-
session = Client.create_consumer_session
|
22
|
-
session.create_queue_ignore_exists(address_name, queue_name, false)
|
23
|
-
session.close
|
24
|
-
end
|
25
|
-
|
26
|
-
def status
|
27
|
-
@status || "Processing message #{message_count}"
|
28
|
-
end
|
29
|
-
|
30
|
-
def on_message(message)
|
31
|
-
object = unmarshal(message)
|
32
|
-
ModernTimes.logger.debug "#{self}: Received Object: #{object}" if ModernTimes.logger.debug?
|
33
|
-
perform(object)
|
34
|
-
ModernTimes.logger.debug "#{self}: Finished processing message" if ModernTimes.logger.debug?
|
35
|
-
ModernTimes.logger.flush if ModernTimes.logger.respond_to?(:flush)
|
36
|
-
rescue Exception => e
|
37
|
-
ModernTimes.logger.error "#{self}: Messaging Exception: #{e.inspect}\n#{e.backtrace.inspect}"
|
38
|
-
rescue java.lang.Exception => e
|
39
|
-
ModernTimes.logger.error "#{self}: Java Messaging Exception: #{e.inspect}\n#{e.backtrace.inspect}"
|
40
|
-
end
|
41
|
-
|
42
|
-
def perform(object)
|
43
|
-
raise "#{self}: Need to override perform method in #{self.class.name} in order to act on #{object}"
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.address_name
|
47
|
-
@address_name ||= default_name
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.queue_name
|
51
|
-
@queue_name ||= default_name
|
52
|
-
end
|
53
|
-
|
54
|
-
def address_name
|
55
|
-
self.class.address_name
|
56
|
-
end
|
57
|
-
|
58
|
-
def queue_name
|
59
|
-
self.class.queue_name
|
60
|
-
end
|
61
|
-
|
62
|
-
def to_s
|
63
|
-
"#{address_name}:#{queue_name}:#{index}"
|
64
|
-
end
|
65
|
-
|
66
|
-
# Start the event loop for handling messages off the queue
|
67
|
-
def start
|
68
|
-
session_init
|
69
|
-
ModernTimes.logger.debug "#{self}: Starting receive loop"
|
70
|
-
@status = nil
|
71
|
-
while msg = @consumer.receive
|
72
|
-
@message_count += 1
|
73
|
-
supervisor.incr_message_count
|
74
|
-
on_message(msg)
|
75
|
-
msg.acknowledge
|
76
|
-
end
|
77
|
-
@status = 'Exited'
|
78
|
-
ModernTimes.logger.info "Exiting #{self}"
|
79
|
-
rescue Java::org.hornetq.api.core.HornetQException => e
|
80
|
-
if e.cause.code == Java::org.hornetq.api.core.HornetQException::OBJECT_CLOSED
|
81
|
-
# Normal exit
|
82
|
-
@status = 'Exited'
|
83
|
-
ModernTimes.logger.info "#{self}: Exiting due to close"
|
84
|
-
else
|
85
|
-
@status = "Exited with HornetQ exception #{e.message}"
|
86
|
-
ModernTImes.logger.error "#{self} HornetQException: #{e.message}\n#{e.backtrace.join("\n")}"
|
87
|
-
end
|
88
|
-
rescue Exception => e
|
89
|
-
@status = "Exited with exception #{e.message}"
|
90
|
-
ModernTimes.logger.error "#{self}: Exception, thread terminating: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
91
|
-
rescue java.lang.Exception => e
|
92
|
-
@status = "Exited with java exception #{e.message}"
|
93
|
-
ModernTimes.logger.error "#{self}: Java exception, thread terminating: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
94
|
-
end
|
95
|
-
|
96
|
-
def stop
|
97
|
-
@session.close if @session
|
98
|
-
end
|
99
|
-
|
100
|
-
#########
|
101
|
-
protected
|
102
|
-
#########
|
103
|
-
|
104
|
-
# Create session information and allow extenders to initialize anything necessary prior to the event loop
|
105
|
-
def session_init
|
106
|
-
@session = Client.create_consumer_session
|
107
|
-
@consumer = @session.create_consumer(queue_name)
|
108
|
-
@session.start
|
109
|
-
end
|
110
|
-
|
111
|
-
# Create a queue, assigned to the specified address
|
112
|
-
# Every time a message arrives, the perform instance method
|
113
|
-
# will be called. The parameter to the method is the Ruby
|
114
|
-
# object supplied when the message was sent
|
115
|
-
def self.address(address_name, opts={})
|
116
|
-
@address_name = address_name.to_s
|
117
|
-
#Messaging::Client.on_message(address, queue_name) do |object|
|
118
|
-
# self.send(method.to_sym, object)
|
119
|
-
#end
|
120
|
-
end
|
121
|
-
|
122
|
-
def self.queue(queue_name, opts={})
|
123
|
-
@queue_name = queue_name.to_s
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'timeout'
|
2
|
-
|
3
|
-
module ModernTimes
|
4
|
-
module HornetQRequestor
|
5
|
-
class RequestHandle
|
6
|
-
def initialize(requestor, message_id, start, timeout)
|
7
|
-
@requestor = requestor
|
8
|
-
@reply_queue = requestor.reply_queue
|
9
|
-
@message_id = message_id
|
10
|
-
@start = start
|
11
|
-
@timeout = timeout
|
12
|
-
end
|
13
|
-
|
14
|
-
def read_response
|
15
|
-
message = nil
|
16
|
-
leftover_timeout = ((@start + @timeout - Time.now) * 1000).to_i
|
17
|
-
ModernTimes::HornetQ::Client.session_pool.session do |s|
|
18
|
-
consumer = nil
|
19
|
-
begin
|
20
|
-
consumer = s.create_consumer(@reply_queue, "#{MESSAGE_ID}='#{@message_id}'")
|
21
|
-
if leftover_timeout > 0
|
22
|
-
message = consumer.receive(leftover_timeout)
|
23
|
-
else
|
24
|
-
message = consumer.receive(1)
|
25
|
-
end
|
26
|
-
puts "funked at #{Time.now.to_f}" unless message
|
27
|
-
consumer.receive_immediate unless message
|
28
|
-
ensure
|
29
|
-
consumer.close if consumer
|
30
|
-
end
|
31
|
-
end
|
32
|
-
raise Timeout::Error, "Timeout waiting for message #{@message_id} on queue #{@reply_queue}" unless message
|
33
|
-
return @requestor.unmarshal(message)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
#handle = Intercept::Client.async_cair(bank_account_array, tracking_number, timeout)
|
40
|
-
#... do other stuff ...
|
41
|
-
#begin
|
42
|
-
# # Following call will block until the queue receives the reply or what's left of the timeout expires
|
43
|
-
# intercept_statuses = handle.read_response
|
44
|
-
# ... process intercept statuses ...
|
45
|
-
#rescue Timeout::Error => e
|
46
|
-
# Rails.logger.warn "We didn't receive a reply back on the queue in time"
|
47
|
-
#rescue Intercept::Error => e
|
48
|
-
# Rails.logger.warn "Error during intercept call: #{e.message}"
|
49
|
-
#end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module ModernTimes
|
2
|
-
module HornetQRequestor
|
3
|
-
class Requestor < ModernTimes::HornetQ::Publisher
|
4
|
-
attr_reader :reply_queue
|
5
|
-
|
6
|
-
def initialize(address, options={})
|
7
|
-
super
|
8
|
-
@reply_queue = "#{address}.#{Java::java.util::UUID.randomUUID.toString}"
|
9
|
-
@reply_queue_simple = Java::org.hornetq.api.core.SimpleString.new(@reply_queue)
|
10
|
-
ModernTimes::HornetQ::Client.session_pool.session do |session|
|
11
|
-
session.create_temporary_queue(@reply_queue, @reply_queue)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def request(object, timeout)
|
16
|
-
start = Time.now
|
17
|
-
message_id = Java::org.hornetq.utils.UUIDGenerator.instance.generateUUID.toString
|
18
|
-
publish(object,
|
19
|
-
nil,
|
20
|
-
MESSAGE_ID => message_id,
|
21
|
-
Java::OrgHornetqCoreClientImpl::ClientMessageImpl::REPLYTO_HEADER_NAME => @reply_queue_simple)
|
22
|
-
#HornetQMessage.CORRELATIONID_HEADER_NAME
|
23
|
-
#REPLY_QUEUE => @reply_queue,
|
24
|
-
#MESSAGE_ID => message_id)
|
25
|
-
return RequestHandle.new(self, message_id, start, timeout)
|
26
|
-
end
|
27
|
-
|
28
|
-
# For non-configured Rails projects, The above request method will be overridden to
|
29
|
-
# call this request method instead which calls all the HornetQ workers that
|
30
|
-
# operate on the given address.
|
31
|
-
def dummy_request(object)
|
32
|
-
@@worker_instances.each do |worker|
|
33
|
-
if worker.kind_of?(Worker) && worker.address_name == address
|
34
|
-
ModernTimes.logger.debug "Dummy requesting #{object} to #{worker}"
|
35
|
-
return new OpenStruct(:read_response => worker.request(object))
|
36
|
-
end
|
37
|
-
end
|
38
|
-
raise "No worker to handle #{address} request of #{object}"
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.setup_dummy_requesting(workers)
|
42
|
-
@@worker_instances = workers.map {|worker| worker.new}
|
43
|
-
alias_method :real_request, :request
|
44
|
-
alias_method :request, :dummy_request
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|