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
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'modern_times/jms/connection'
|
2
|
+
require 'modern_times/jms/publisher'
|
3
|
+
require 'modern_times/jms/supervisor_mbean'
|
4
|
+
require 'modern_times/jms/supervisor'
|
5
|
+
require 'modern_times/jms/worker'
|
6
|
+
|
7
|
+
module ModernTimes
|
8
|
+
module JMS
|
9
|
+
def self.same_destination?(options1, options2)
|
10
|
+
if options1[:queue_name]
|
11
|
+
return options1[:queue_name] == options2[:queue_name]
|
12
|
+
elsif options1[:topic_name]
|
13
|
+
return options1[:topic_name] == options2[:topic_name]
|
14
|
+
elsif options1[:virtual_topic_name]
|
15
|
+
return options1[:virtual_topic_name] == options2[:virtual_topic_name]
|
16
|
+
elsif options1[:destination]
|
17
|
+
return options1[:destination] == options2[:destination]
|
18
|
+
else
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,16 +1,18 @@
|
|
1
|
-
require '
|
1
|
+
require 'jms'
|
2
2
|
|
3
3
|
# Handle Messaging and Queuing
|
4
4
|
module ModernTimes
|
5
|
-
module
|
6
|
-
module
|
5
|
+
module JMS
|
6
|
+
module Connection
|
7
7
|
# Singleton-ize
|
8
8
|
extend self
|
9
9
|
|
10
10
|
# Initialize the messaging system and connection pool for this VM
|
11
11
|
def init(config)
|
12
12
|
@config = config
|
13
|
-
@
|
13
|
+
@inited = true
|
14
|
+
@connection = ::JMS::Connection.new(config)
|
15
|
+
@connection.start
|
14
16
|
# Let's not create a session_pool unless we're going to use it
|
15
17
|
@session_pool_mutex = Mutex.new
|
16
18
|
|
@@ -19,13 +21,13 @@ module ModernTimes
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
23
|
-
@
|
24
|
+
def inited?
|
25
|
+
@inited
|
24
26
|
end
|
25
27
|
|
26
28
|
# Create a session targeted for a consumer (producers should use the session_pool)
|
27
29
|
def create_consumer_session
|
28
|
-
|
30
|
+
connection.create_session(@config || {})
|
29
31
|
end
|
30
32
|
|
31
33
|
def session_pool
|
@@ -34,19 +36,24 @@ module ModernTimes
|
|
34
36
|
@session_pool_mutex.synchronize do
|
35
37
|
# if it's been created in between the above call and now, return it
|
36
38
|
return @session_pool if @session_pool
|
37
|
-
return @session_pool =
|
39
|
+
return @session_pool = connection.create_session_pool(@config)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
def close
|
44
|
+
return if @closed
|
42
45
|
ModernTimes.logger.info "Closing #{self.name}"
|
43
46
|
@session_pool.close if @session_pool
|
44
|
-
|
47
|
+
if @connection
|
48
|
+
@connection.stop
|
49
|
+
@connection.close
|
50
|
+
end
|
51
|
+
@closed = true
|
45
52
|
end
|
46
53
|
|
47
|
-
def
|
48
|
-
raise "#{self.name} never had it's init method called" unless @
|
49
|
-
@
|
54
|
+
def connection
|
55
|
+
raise "#{self.name} never had it's init method called" unless @connection
|
56
|
+
@connection
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'jms'
|
2
|
+
|
3
|
+
# Protocol independent class to handle Publishing
|
4
|
+
module ModernTimes
|
5
|
+
module JMS
|
6
|
+
class Publisher
|
7
|
+
attr_reader :producer_options, :persistent, :marshaler
|
8
|
+
|
9
|
+
# Parameters:
|
10
|
+
# One of the following must be specified
|
11
|
+
# :queue_name => String: Name of the Queue to publish to
|
12
|
+
# :topic_name => String: Name of the Topic to publish to
|
13
|
+
# :virtual_topic_name => String: Name of the Virtual Topic to publish to
|
14
|
+
# (ActiveMQ only, see http://activemq.apache.org/virtual-destinations.html
|
15
|
+
# :destination=> Explicit javax::Jms::Destination to use
|
16
|
+
# Optional:
|
17
|
+
# :persistent => true or false (defaults to false)
|
18
|
+
# :marshal => Symbol: One of :ruby, :string, or :json
|
19
|
+
# => Module: Module that defines marshal and unmarshal method
|
20
|
+
def initialize(options)
|
21
|
+
producer_keys = [:queue_name, :topic_name, :virtual_topic_name, :destination]
|
22
|
+
@producer_options = options.reject {|k,v| !producer_keys.include?(k)}
|
23
|
+
raise "One of #{producer_keys.join(',')} must be given in #{self.class.name}" if @producer_options.empty?
|
24
|
+
|
25
|
+
# Save our @producer_options for destination comparison when doing dummy_publish,
|
26
|
+
# but create the real options by translating virtual_topic_name to a real topic_name.
|
27
|
+
@real_producer_options = @producer_options.dup
|
28
|
+
virtual_topic_name = @real_producer_options.delete(:virtual_topic_name)
|
29
|
+
@real_producer_options[:topic_name] = "VirtualTopic.#{virtual_topic_name}" if virtual_topic_name
|
30
|
+
|
31
|
+
# If we're in dummy mode, this probably won't be defined
|
32
|
+
#@persistent = options[:persistent] ? ::JMS::DeliveryMode::PERSISTENT : ::JMS::DeliveryMode::NON_PERSISTENT
|
33
|
+
@persistent = options[:persistent] ? :persistent : :non_persistent
|
34
|
+
@marshaler = ModernTimes::MarshalStrategy.find(options[:marshal])
|
35
|
+
end
|
36
|
+
|
37
|
+
# Publish the given object to the address.
|
38
|
+
def publish(object, props={})
|
39
|
+
message = nil
|
40
|
+
Connection.session_pool.producer(@real_producer_options) do |session, producer|
|
41
|
+
message = case @marshaler.marshal_type
|
42
|
+
when :text
|
43
|
+
session.create_text_message(@marshaler.marshal(object))
|
44
|
+
when :bytes
|
45
|
+
msg = session.create_bytes_message()
|
46
|
+
msg.data = @marshaler.marshal(object)
|
47
|
+
msg
|
48
|
+
else raise "Invalid marshal type: #{@marshaler.marshal_type}"
|
49
|
+
end
|
50
|
+
message.jms_delivery_mode_sym = @persistent
|
51
|
+
props.each do |key, value|
|
52
|
+
message.send("#{key}=", value)
|
53
|
+
end
|
54
|
+
# TODO: Is send_with_retry possible?
|
55
|
+
#producer.send_with_retry(message)
|
56
|
+
producer.send(message)
|
57
|
+
end
|
58
|
+
return message
|
59
|
+
end
|
60
|
+
|
61
|
+
# For non-configured Rails projects, The above publish method will be overridden to
|
62
|
+
# call this publish method instead which calls all the JMS workers that
|
63
|
+
# operate on the given address.
|
64
|
+
def dummy_publish(object)
|
65
|
+
@@worker_instances.each do |worker|
|
66
|
+
if worker.kind_of?(Worker) && ModernTimes::JMS.same_destination?(@producer_options, worker.class.destination_options)
|
67
|
+
ModernTimes.logger.debug "Dummy publishing #{object} to #{worker}"
|
68
|
+
worker.perform(object)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
"#{self.class.name}:#{@real_producer_options.inspect}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.setup_dummy_publishing(workers)
|
78
|
+
@@worker_instances = workers.map {|worker| worker.new}
|
79
|
+
alias_method :real_publish, :publish
|
80
|
+
alias_method :publish, :dummy_publish
|
81
|
+
end
|
82
|
+
|
83
|
+
# For testing
|
84
|
+
def self.clear_dummy_publishing
|
85
|
+
alias_method :dummy_publish, :publish
|
86
|
+
alias_method :publish, :real_publish
|
87
|
+
#remove_method :real_publish
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ModernTimes
|
2
|
+
module JMS
|
3
|
+
class Supervisor < ModernTimes::Base::Supervisor
|
4
|
+
|
5
|
+
def initialize(manager, worker_name, supervisor_options, worker_options)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def message_counts
|
10
|
+
workers.map { |w| w.message_count }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Make JMS::SupervisorMBean our mbean
|
14
|
+
def create_mbean(domain)
|
15
|
+
SupervisorMBean.new(mbean_name(domain), mbean_description, self, {})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module ModernTimes
|
2
|
+
module JMS
|
3
|
+
class SupervisorMBean < ModernTimes::Base::SupervisorMBean
|
4
|
+
r_attribute :message_counts, :list, 'Message counts for the workers', :message_counts
|
5
|
+
|
6
|
+
def message_counts
|
7
|
+
java.util.ArrayList.new(supervisor.message_counts)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module ModernTimes
|
2
|
+
module JMS
|
3
|
+
|
4
|
+
# Base Worker Class for any class that will be processing messages from topics or queues
|
5
|
+
# By default, it will consume messages from a queue with the class name minus the Worker postfix.
|
6
|
+
# For example, the queue call is unneccessary as it will default to a value of 'Foo' anyways:
|
7
|
+
# class FooWorker < ModernTimes::JMS::Worker
|
8
|
+
# queue 'Foo'
|
9
|
+
# def perform(obj)
|
10
|
+
# # Perform work on obj
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# A topic can be specified using virtual_topic as follows (ActiveMQ only). Multiple separate workers can
|
15
|
+
# subscribe to the same topic (under ActiveMQ - see http://activemq.apache.org/virtual-destinations.html):
|
16
|
+
# class FooWorker < ModernTimes::JMS::Worker
|
17
|
+
# virtual_topic 'Zulu'
|
18
|
+
# def perform(obj)
|
19
|
+
# # Perform work on obj
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Filters can also be specified within the class:
|
24
|
+
# class FooWorker < ModernTimes::JMS::Worker
|
25
|
+
# filter 'age > 30'
|
26
|
+
# def perform(obj)
|
27
|
+
# # Perform work on obj
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
#
|
32
|
+
module Worker
|
33
|
+
include ModernTimes::Base::Worker
|
34
|
+
|
35
|
+
attr_reader :session, :message, :message_count
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def create_supervisor(manager, worker_options)
|
39
|
+
Supervisor.new(manager, self, {}, worker_options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def marshal(option)
|
43
|
+
@marshaler = ModernTimes::MarshalStrategy.find(option)
|
44
|
+
end
|
45
|
+
|
46
|
+
def destination_options
|
47
|
+
options = dest_options.dup
|
48
|
+
# Default the queue name to the Worker name if a destinations hasn't been specified
|
49
|
+
if options.keys.select {|k| [:virtual_topic_name, :queue_name, :destination].include?(k)}.empty?
|
50
|
+
options[:queue_name] = default_name
|
51
|
+
end
|
52
|
+
return options
|
53
|
+
end
|
54
|
+
|
55
|
+
def virtual_topic(name, opts={})
|
56
|
+
# ActiveMQ only
|
57
|
+
dest_options[:virtual_topic_name] = name.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def queue(name, opts={})
|
61
|
+
dest_options[:queue_name] = name.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def dest_options
|
65
|
+
@dest_options ||= {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def marshaler
|
69
|
+
# Default to ruby marshaling, but extenders can override as necessary
|
70
|
+
@marshaler ||= ModernTimes::MarshalStrategy::Ruby
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.included(base)
|
75
|
+
base.extend(ModernTimes::Base::Worker::ClassMethods)
|
76
|
+
base.extend(ClassMethods)
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize(opts={})
|
80
|
+
super
|
81
|
+
@status = 'initialized'
|
82
|
+
@message_count = 0
|
83
|
+
end
|
84
|
+
|
85
|
+
def setup
|
86
|
+
end
|
87
|
+
|
88
|
+
def status
|
89
|
+
@status || "Processing message #{message_count}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def real_destination_options
|
93
|
+
options = self.class.destination_options
|
94
|
+
virtual_topic_name = options.delete(:virtual_topic_name)
|
95
|
+
options[:queue_name] = "Consumer.#{name}.VirtualTopic.#{virtual_topic_name}" if virtual_topic_name
|
96
|
+
return options
|
97
|
+
end
|
98
|
+
|
99
|
+
def on_message(message)
|
100
|
+
@message = message
|
101
|
+
object = self.class.marshaler.unmarshal(message.data)
|
102
|
+
ModernTimes.logger.debug "#{self}: Received Object: #{object}" if ModernTimes.logger.debug?
|
103
|
+
perform(object)
|
104
|
+
ModernTimes.logger.debug "#{self}: Finished processing message" if ModernTimes.logger.debug?
|
105
|
+
ModernTimes.logger.flush if ModernTimes.logger.respond_to?(:flush)
|
106
|
+
rescue Exception => e
|
107
|
+
ModernTimes.logger.error "#{self}: Messaging Exception: #{e.inspect}\n#{e.backtrace.inspect}"
|
108
|
+
rescue java.lang.Exception => e
|
109
|
+
ModernTimes.logger.error "#{self}: Java Messaging Exception: #{e.inspect}\n#{e.backtrace.inspect}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def perform(object)
|
113
|
+
raise "#{self}: Need to override perform method in #{self.class.name} in order to act on #{object}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_s
|
117
|
+
"#{real_destination_options.to_a.join('=>')}:#{index}"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Start the event loop for handling messages off the queue
|
121
|
+
def start
|
122
|
+
@session = Connection.create_consumer_session
|
123
|
+
@consumer = @session.consumer(real_destination_options)
|
124
|
+
@session.start
|
125
|
+
|
126
|
+
ModernTimes.logger.debug "#{self}: Starting receive loop"
|
127
|
+
@status = nil
|
128
|
+
while msg = @consumer.receive
|
129
|
+
@message_count += 1
|
130
|
+
on_message(msg)
|
131
|
+
msg.acknowledge
|
132
|
+
end
|
133
|
+
@status = 'Exited'
|
134
|
+
ModernTimes.logger.info "#{self}: Exiting"
|
135
|
+
rescue javax.jms.IllegalStateException => e
|
136
|
+
#if e.cause.code == Java::org.jms.api.core.JMSException::OBJECT_CLOSED
|
137
|
+
# Normal exit
|
138
|
+
@status = 'Exited'
|
139
|
+
ModernTimes.logger.info "#{self}: Exiting due to close"
|
140
|
+
#else
|
141
|
+
# @status = "Exited with JMS exception #{e.message}"
|
142
|
+
# ModernTImes.logger.error "#{self} JMSException: #{e.message}\n#{e.backtrace.join("\n")}"
|
143
|
+
#end
|
144
|
+
rescue Exception => e
|
145
|
+
@status = "Exited with exception #{e.message}"
|
146
|
+
ModernTimes.logger.error "#{self}: Exception, thread terminating: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
147
|
+
rescue java.lang.Exception => e
|
148
|
+
@status = "Exited with java exception #{e.message}"
|
149
|
+
ModernTimes.logger.error "#{self}: Java exception, thread terminating: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
150
|
+
end
|
151
|
+
|
152
|
+
def stop
|
153
|
+
@consumer.close if @consumer
|
154
|
+
@session.close if @session
|
155
|
+
end
|
156
|
+
|
157
|
+
#########
|
158
|
+
protected
|
159
|
+
#########
|
160
|
+
|
161
|
+
# Create session information and allow extenders to initialize anything necessary prior to the event loop
|
162
|
+
def session_init
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'modern_times/jms_requestor/request_handle'
|
2
|
+
require 'modern_times/jms_requestor/requestor'
|
3
|
+
require 'modern_times/jms_requestor/supervisor_mbean'
|
4
|
+
require 'modern_times/jms_requestor/supervisor'
|
5
|
+
require 'modern_times/jms_requestor/worker'
|
6
|
+
|
7
|
+
module ModernTimes
|
8
|
+
module JMSRequestor
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module ModernTimes
|
4
|
+
module JMSRequestor
|
5
|
+
class RequestHandle
|
6
|
+
def initialize(requestor, message, start, timeout)
|
7
|
+
@requestor = requestor
|
8
|
+
@reply_queue = requestor.reply_queue
|
9
|
+
@message = message
|
10
|
+
@start = start
|
11
|
+
@timeout = timeout
|
12
|
+
end
|
13
|
+
|
14
|
+
def read_response
|
15
|
+
response = nil
|
16
|
+
opts = { :destination => @reply_queue, :selector => "JMSCorrelationID = '#{@message.jms_message_id}'" }
|
17
|
+
#opts = { :destination => @reply_queue }
|
18
|
+
#opts = {:queue_name => 'foobarzulu'}
|
19
|
+
ModernTimes::JMS::Connection.session_pool.consumer(opts) do |session, consumer|
|
20
|
+
leftover_timeout = ((@start + @timeout - Time.now) * 1000).to_i
|
21
|
+
if leftover_timeout > 100
|
22
|
+
response = consumer.receive(leftover_timeout)
|
23
|
+
else
|
24
|
+
#response = consumer.receive_no_wait
|
25
|
+
response = consumer.receive(100)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
raise Timeout::Error, "Timeout waiting for for response from message #{@message.jms_message_id} on queue #{@reply_queue}" unless response
|
29
|
+
return @requestor.marshaler.unmarshal(response.data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ModernTimes
|
2
|
+
module JMSRequestor
|
3
|
+
class Requestor < ModernTimes::JMS::Publisher
|
4
|
+
attr_reader :reply_queue
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
super
|
8
|
+
ModernTimes::JMS::Connection.session_pool.session do |session|
|
9
|
+
@reply_queue = session.create_destination(:queue_name => :temporary)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def request(object, timeout)
|
14
|
+
start = Time.now
|
15
|
+
message = publish(object, :jms_reply_to => @reply_queue)
|
16
|
+
return RequestHandle.new(self, message, start, timeout)
|
17
|
+
end
|
18
|
+
|
19
|
+
# For non-configured Rails projects, The above request method will be overridden to
|
20
|
+
# call this request method instead which calls all the JMS workers that
|
21
|
+
# operate on the given address.
|
22
|
+
def dummy_request(object, timeout)
|
23
|
+
@@worker_instances.each do |worker|
|
24
|
+
if worker.kind_of?(Worker) && ModernTimes::JMS.same_destination?(producer_options, worker.destination_options)
|
25
|
+
ModernTimes.logger.debug "Dummy requesting #{object} to #{worker}"
|
26
|
+
return new OpenStruct(:read_response => worker.request(object))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
raise "No worker to handle #{address} request of #{object}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.setup_dummy_requesting(workers)
|
33
|
+
@@worker_instances = workers.map {|worker| worker.new}
|
34
|
+
alias_method :real_request, :request
|
35
|
+
alias_method :request, :dummy_request
|
36
|
+
end
|
37
|
+
|
38
|
+
# For testing
|
39
|
+
def self.clear_dummy_requesting
|
40
|
+
alias_method :dummy_request, :request
|
41
|
+
alias_method :request, :real_request
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|