modern_times 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/examples/consumer/consumer.rb +24 -0
- data/lib/modern_times/jms/consumer.rb +76 -0
- data/lib/modern_times/jms/publisher.rb +13 -2
- data/lib/modern_times/jms.rb +1 -0
- data/lib/modern_times/jms_requestor/request_handle.rb +4 -4
- data/lib/modern_times/jms_requestor/requestor.rb +2 -2
- data/lib/modern_times/manager.rb +13 -5
- data/lib/modern_times/railsable.rb +14 -4
- metadata +4 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.7
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Allow examples to be run in-place without requiring a gem install
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'erb'
|
6
|
+
require 'modern_times'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
if ARGV.size < 2
|
10
|
+
$stderr.puts "Usage: {$0} <message> <id>"
|
11
|
+
end
|
12
|
+
|
13
|
+
#ModernTimes::JMS::Publisher.setup_dummy_publishing([])
|
14
|
+
#ModernTimes::JMS::Consumer.setup_dummy_receiving
|
15
|
+
|
16
|
+
config = YAML.load(ERB.new(File.read(File.join(File.dirname(__FILE__), '..', 'jms.yml'))).result(binding))
|
17
|
+
ModernTimes::JMS::Connection.init(config)
|
18
|
+
publisher = ModernTimes::JMS::Publisher.new(:queue_name => 'Foo', :marshal => :string)
|
19
|
+
consumer = ModernTimes::JMS::Consumer.new(:queue_name => 'Foo', :marshal => :string)
|
20
|
+
|
21
|
+
publisher.publish(ARGV[0], :jms_correlation_id => ARGV[1])
|
22
|
+
msg = consumer.receive(:jms_correlation_id => ARGV[1], :timeout => 30000)
|
23
|
+
#msg = consumer.receive(:timeout => 1000)
|
24
|
+
puts "msg=#{msg}"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'jms'
|
2
|
+
|
3
|
+
# Protocol independent class to handle Publishing
|
4
|
+
module ModernTimes
|
5
|
+
module JMS
|
6
|
+
class Consumer
|
7
|
+
attr_reader :consumer_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
|
+
consumer_keys = [:queue_name, :topic_name, :virtual_topic_name, :destination]
|
22
|
+
@consumer_options = options.reject {|k,v| !consumer_keys.include?(k)}
|
23
|
+
raise "One of #{consumer_keys.join(',')} must be given in #{self.class.name}" if @consumer_options.empty?
|
24
|
+
|
25
|
+
# Save our @consumer_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_consumer_options = @consumer_options.dup
|
28
|
+
virtual_topic_name = @real_consumer_options.delete(:virtual_topic_name)
|
29
|
+
@real_consumer_options[:topic_name] = "VirtualTopic.#{virtual_topic_name}" if virtual_topic_name
|
30
|
+
@marshaler = ModernTimes::MarshalStrategy.find(options[:marshal])
|
31
|
+
end
|
32
|
+
|
33
|
+
# Publish the given object to the address.
|
34
|
+
def receive(options={})
|
35
|
+
options = @real_consumer_options.merge(options)
|
36
|
+
correlation_id = options.delete(:jms_correlation_id)
|
37
|
+
options[:selector] = "JMSCorrelationID = '#{correlation_id}'" if correlation_id && !options[:selector]
|
38
|
+
timeout = options.delete(:timeout) || 0
|
39
|
+
obj = nil
|
40
|
+
|
41
|
+
Connection.session_pool.consumer(options) do |session, consumer|
|
42
|
+
message = consumer.get(:timeout => timeout)
|
43
|
+
obj = @marshaler.unmarshal(message.data) if message
|
44
|
+
end
|
45
|
+
return obj
|
46
|
+
end
|
47
|
+
|
48
|
+
# For non-configured Rails projects, The above publish method will be overridden to
|
49
|
+
# call this publish method instead which calls all the JMS workers that
|
50
|
+
# operate on the given address.
|
51
|
+
def dummy_receive(options={})
|
52
|
+
if correlation_id = options.delete(:jms_correlation_id)
|
53
|
+
return Publisher.dummy_cache(correlation_id)
|
54
|
+
else
|
55
|
+
# TODO: Pop off if no correlation id given
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"#{self.class.name}:#{@real_consumer_options.inspect}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.setup_dummy_receiving
|
64
|
+
alias_method :real_receive, :receive
|
65
|
+
alias_method :receive, :dummy_receive
|
66
|
+
end
|
67
|
+
|
68
|
+
# For testing
|
69
|
+
def self.clear_dummy_receiving
|
70
|
+
alias_method :dummy_receive, :receive
|
71
|
+
alias_method :receive, :real_receive
|
72
|
+
#remove_method :real_receive
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -47,19 +47,24 @@ module ModernTimes
|
|
47
47
|
#producer.send_with_retry(message)
|
48
48
|
producer.send(message)
|
49
49
|
end
|
50
|
-
return message
|
50
|
+
return message.jms_message_id
|
51
51
|
end
|
52
52
|
|
53
53
|
# For non-configured Rails projects, The above publish method will be overridden to
|
54
54
|
# call this publish method instead which calls all the JMS workers that
|
55
55
|
# operate on the given address.
|
56
|
-
def dummy_publish(object)
|
56
|
+
def dummy_publish(object, props={})
|
57
|
+
@@message_id += 1
|
57
58
|
@@worker_instances.each do |worker|
|
58
59
|
if worker.kind_of?(Worker) && ModernTimes::JMS.same_destination?(@producer_options, worker.class.destination_options)
|
59
60
|
ModernTimes.logger.debug "Dummy publishing #{object} to #{worker}"
|
60
61
|
worker.perform(object)
|
61
62
|
end
|
62
63
|
end
|
64
|
+
if correlation_id = props[:jms_correlation_id]
|
65
|
+
@@dummy_cache[correlation_id] = object
|
66
|
+
end
|
67
|
+
return @@message_id
|
63
68
|
end
|
64
69
|
|
65
70
|
def to_s
|
@@ -67,6 +72,8 @@ module ModernTimes
|
|
67
72
|
end
|
68
73
|
|
69
74
|
def self.setup_dummy_publishing(workers)
|
75
|
+
@@message_id = 0
|
76
|
+
@@dummy_cache = {}
|
70
77
|
@@worker_instances = workers.map {|worker| worker.new}
|
71
78
|
alias_method :real_publish, :publish
|
72
79
|
alias_method :publish, :dummy_publish
|
@@ -78,6 +85,10 @@ module ModernTimes
|
|
78
85
|
alias_method :publish, :real_publish
|
79
86
|
#remove_method :real_publish
|
80
87
|
end
|
88
|
+
|
89
|
+
def self.dummy_cache(correlation_id)
|
90
|
+
@@dummy_cache.delete(correlation_id)
|
91
|
+
end
|
81
92
|
end
|
82
93
|
end
|
83
94
|
end
|
data/lib/modern_times/jms.rb
CHANGED
@@ -4,10 +4,10 @@ require 'yaml'
|
|
4
4
|
module ModernTimes
|
5
5
|
module JMSRequestor
|
6
6
|
class RequestHandle
|
7
|
-
def initialize(requestor,
|
7
|
+
def initialize(requestor, jms_message_id, start, timeout, &reconstruct_block)
|
8
8
|
@requestor = requestor
|
9
9
|
@reply_queue = requestor.reply_queue
|
10
|
-
@
|
10
|
+
@jms_message_id = jms_message_id
|
11
11
|
@start = start
|
12
12
|
@timeout = timeout
|
13
13
|
@reconstruct_block = reconstruct_block
|
@@ -15,7 +15,7 @@ module ModernTimes
|
|
15
15
|
|
16
16
|
def read_response
|
17
17
|
response = nil
|
18
|
-
opts = { :destination => @reply_queue, :selector => "JMSCorrelationID = '#{@
|
18
|
+
opts = { :destination => @reply_queue, :selector => "JMSCorrelationID = '#{@jms_message_id}'" }
|
19
19
|
#opts = { :destination => @reply_queue }
|
20
20
|
#opts = {:queue_name => 'foobarzulu'}
|
21
21
|
ModernTimes::JMS::Connection.session_pool.consumer(opts) do |session, consumer|
|
@@ -27,7 +27,7 @@ module ModernTimes
|
|
27
27
|
response = consumer.receive(100)
|
28
28
|
end
|
29
29
|
end
|
30
|
-
raise Timeout::Error, "Timeout waiting for for response from message #{@
|
30
|
+
raise Timeout::Error, "Timeout waiting for for response from message #{@jms_message_id} on queue #{@reply_queue}" unless response
|
31
31
|
if error_yaml = response['Exception']
|
32
32
|
raise ModernTimes::RemoteException.from_hash(YAML.load(error_yaml))
|
33
33
|
end
|
@@ -16,8 +16,8 @@ module ModernTimes
|
|
16
16
|
|
17
17
|
def request(object, timeout, &reconstruct_block)
|
18
18
|
start = Time.now
|
19
|
-
|
20
|
-
return RequestHandle.new(self,
|
19
|
+
jms_message_id = publish(object, :jms_reply_to => @reply_queue)
|
20
|
+
return RequestHandle.new(self, jms_message_id, start, timeout, &reconstruct_block)
|
21
21
|
end
|
22
22
|
|
23
23
|
# For non-configured Rails projects, The above request method will be overridden to
|
data/lib/modern_times/manager.rb
CHANGED
@@ -11,11 +11,17 @@ module ModernTimes
|
|
11
11
|
@config = config
|
12
12
|
@domain = config[:domain] || ModernTimes::DEFAULT_DOMAIN
|
13
13
|
@supervisors = []
|
14
|
-
@jmx_server = JMX::MBeanServer.new
|
15
|
-
bean = ManagerMBean.new(@domain, self)
|
16
|
-
@jmx_server.register_mbean(bean, ModernTimes.manager_mbean_object_name(@domain))
|
17
14
|
self.persist_file = config[:persist_file]
|
18
15
|
self.worker_file = config[:worker_file]
|
16
|
+
@allowed_workers = config[:allowed_workers]
|
17
|
+
stop_on_signal if config[:stop_on_signal]
|
18
|
+
@dummy_host = config[:dummy_host]
|
19
|
+
# Unless specifically unconfigured (i.e., Rails.env == test), then enable jmx
|
20
|
+
if config[:jmx] != false
|
21
|
+
@jmx_server = JMX::MBeanServer.new
|
22
|
+
bean = ManagerMBean.new(@domain, self)
|
23
|
+
@jmx_server.register_mbean(bean, ModernTimes.manager_mbean_object_name(@domain))
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
def add(worker_klass, num_workers, worker_options={})
|
@@ -32,10 +38,12 @@ module ModernTimes
|
|
32
38
|
end
|
33
39
|
supervisor = worker_klass.create_supervisor(self, worker_options)
|
34
40
|
raise "A supervisor with name #{supervisor.name} already exists" if find_supervisor(supervisor.name)
|
35
|
-
mbean = supervisor.create_mbean(@domain)
|
36
41
|
@supervisors << supervisor
|
37
42
|
supervisor.worker_count = num_workers
|
38
|
-
@jmx_server
|
43
|
+
if @jmx_server
|
44
|
+
mbean = supervisor.create_mbean(@domain)
|
45
|
+
@jmx_server.register_mbean(mbean, "#{@domain}:worker=#{supervisor.name},type=Worker")
|
46
|
+
end
|
39
47
|
ModernTimes.logger.info "Started #{worker_klass.name} named #{supervisor.name} with #{num_workers} workers"
|
40
48
|
rescue Exception => e
|
41
49
|
ModernTimes.logger.error "Exception trying to add #{worker_klass}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
@@ -47,20 +47,30 @@ module ModernTimes
|
|
47
47
|
Rails.logger.info "Messaging disabled"
|
48
48
|
@is_jms_enabled = false
|
49
49
|
ModernTimes::JMS::Publisher.setup_dummy_publishing(rails_workers)
|
50
|
+
ModernTimes::JMS::Consumer.setup_dummy_receiving
|
50
51
|
ModernTimes::JMSRequestor::Requestor.setup_dummy_requesting(rails_workers)
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
def create_rails_manager
|
55
|
+
def create_rails_manager(manager_config={})
|
55
56
|
# Take advantage of nil and false values for boolean
|
56
57
|
raise 'init_rails has not been called, modify your config/environment.rb to include this call' if @is_jms_enabled.nil?
|
57
58
|
raise 'Messaging is not enabled, modify your config/jms.yml file' unless @is_jms_enabled
|
58
|
-
|
59
|
+
default_config = {
|
60
|
+
:persist_file => File.join(Rails.root, "log", "modern_times.persist"),
|
61
|
+
:worker_file => File.join(Rails.root, "config", "workers.yml"),
|
62
|
+
:jmx => Rails.env != 'test',
|
63
|
+
:stop_on_signal => true,
|
64
|
+
:dummy_host => Rails.env,
|
65
|
+
:allowed_workers => rails_workers,
|
66
|
+
}
|
67
|
+
|
68
|
+
manager = ModernTimes::Manager.new(default_config.merge(manager_config))
|
59
69
|
manager.stop_on_signal
|
60
70
|
manager.allowed_workers = rails_workers
|
61
|
-
manager.persist_file =
|
71
|
+
manager.persist_file = manager_config[:persist_file] || File.join(Rails.root, "log", "modern_times.persist")
|
62
72
|
manager.dummy_host = Rails.env
|
63
|
-
manager.worker_file =
|
73
|
+
manager.worker_file = manager_config[:worker_file] || File.join(Rails.root, "config", "workers.yml")
|
64
74
|
return manager
|
65
75
|
end
|
66
76
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: modern_times
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.7
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Brad Pardee
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- Rakefile
|
54
54
|
- VERSION
|
55
55
|
- examples/README
|
56
|
+
- examples/consumer/consumer.rb
|
56
57
|
- examples/jms.yml
|
57
58
|
- examples/requestor/.gitignore
|
58
59
|
- examples/requestor/README
|
@@ -72,6 +73,7 @@ files:
|
|
72
73
|
- lib/modern_times/base/worker.rb
|
73
74
|
- lib/modern_times/jms.rb
|
74
75
|
- lib/modern_times/jms/connection.rb
|
76
|
+
- lib/modern_times/jms/consumer.rb
|
75
77
|
- lib/modern_times/jms/publisher.rb
|
76
78
|
- lib/modern_times/jms/supervisor.rb
|
77
79
|
- lib/modern_times/jms/supervisor_mbean.rb
|
@@ -130,6 +132,7 @@ signing_key:
|
|
130
132
|
specification_version: 3
|
131
133
|
summary: Asynchronous task library
|
132
134
|
test_files:
|
135
|
+
- examples/consumer/consumer.rb
|
133
136
|
- examples/exception_test/bar_worker.rb
|
134
137
|
- examples/exception_test/base_worker.rb
|
135
138
|
- examples/exception_test/manager.rb
|