modern_times 0.1.2 → 0.2.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.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
|