modern_times 0.2.6 → 0.2.7

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.6
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
@@ -1,4 +1,5 @@
1
1
  require 'modern_times/jms/connection'
2
+ require 'modern_times/jms/consumer'
2
3
  require 'modern_times/jms/publisher'
3
4
  require 'modern_times/jms/supervisor_mbean'
4
5
  require 'modern_times/jms/supervisor'
@@ -4,10 +4,10 @@ require 'yaml'
4
4
  module ModernTimes
5
5
  module JMSRequestor
6
6
  class RequestHandle
7
- def initialize(requestor, message, start, timeout, &reconstruct_block)
7
+ def initialize(requestor, jms_message_id, start, timeout, &reconstruct_block)
8
8
  @requestor = requestor
9
9
  @reply_queue = requestor.reply_queue
10
- @message = message
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 = '#{@message.jms_message_id}'" }
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 #{@message.jms_message_id} on queue #{@reply_queue}" unless response
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
- message = publish(object, :jms_reply_to => @reply_queue)
20
- return RequestHandle.new(self, message, start, timeout, &reconstruct_block)
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
@@ -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.register_mbean(mbean, "#{@domain}:worker=#{supervisor.name},type=Worker")
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
- manager = ModernTimes::Manager.new
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 = @config[:persist_file] || File.join(Rails.root, "log", "modern_times.persist")
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 = @config[:worker_file] || File.join(Rails.root, "config", "workers.yml")
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.6
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