modern_times 0.1.1 → 0.1.2

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/Rakefile CHANGED
@@ -10,8 +10,9 @@ begin
10
10
  gemspec.authors = ['Brad Pardee', 'Reid Morrison']
11
11
  gemspec.email = ['bradpardee@gmail.com', 'rubywmq@gmail.com']
12
12
  gemspec.homepage = 'http://github.com/ClarityServices/modern_times'
13
- gemspec.add_dependency 'jruby-hornetq', ['>= 0.3.2']
14
- gemspec.add_dependency 'ClarityServices-jmxjr'
13
+ gemspec.add_dependency 'jruby-hornetq', ['>= 0.3.3']
14
+ gemspec.add_dependency 'jmx', ['>= 0.6']
15
+ gemspec.add_dependency 'json'
15
16
  end
16
17
  rescue LoadError
17
18
  puts 'Jeweler not available. Install it with: gem install jeweler'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -0,0 +1,2 @@
1
+ data
2
+ *.state
@@ -0,0 +1,11 @@
1
+ # Step 1
2
+ # Start a hornetq server (gem install jruby-hornetq if necessary)
3
+ hornetq_server hornetq.yml server
4
+
5
+ # Step 2
6
+ # Start up the manager
7
+ jruby manager.rb
8
+
9
+ # Step 3
10
+ # Request 'my string' get reversed
11
+ jruby request.rb 'my string'
@@ -0,0 +1,14 @@
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
@@ -0,0 +1,15 @@
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 'modern_times'
6
+ require 'yaml'
7
+ require 'reverse_echo_worker'
8
+
9
+ config = YAML.load_file('hornetq.yml')
10
+ ModernTimes::HornetQ::Client.init(config['client'])
11
+
12
+ manager = ModernTimes::Manager.new
13
+ manager.stop_on_signal
14
+ manager.add(ReverseEchoWorker, 1, {})
15
+ manager.join
@@ -0,0 +1,45 @@
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 'modern_times'
6
+ require 'yaml'
7
+ require 'reverse_echo_worker'
8
+
9
+ if ARGV.size < 1
10
+ $stderr.puts "Usage: {$0} <reverse-echo-string> [<timeout>] [<sleep-time>] [<simultaneous-count>]"
11
+ exit 1
12
+ end
13
+
14
+ $echo_string = ARGV[0]
15
+ $timeout = (ARGV[1] || 4).to_f
16
+ $sleep_time = (ARGV[2] || 2).to_i
17
+ $sim_count = (ARGV[3] || 1).to_i
18
+
19
+ config = YAML.load_file('hornetq.yml')
20
+ ModernTimes::HornetQ::Client.init(config['client'])
21
+ $requestor = ModernTimes::HornetQRequestor::Requestor.new(ReverseEchoWorker.address_name, :marshal => :string)
22
+
23
+ def make_request(ident='')
24
+ puts "#{ident}Making request at #{Time.now.to_f}"
25
+ handle = $requestor.request("#{ident}#{$echo_string}", $timeout)
26
+ # Here's where we'd go off and do other work
27
+ sleep $sleep_time
28
+ puts "#{ident}Finished sleeping at #{Time.now.to_f}"
29
+ response = handle.read_response
30
+ puts "#{ident}Received at #{Time.now.to_f}: #{response}"
31
+ rescue Exception => e
32
+ puts "#{ident}Exception: #{e.message}"
33
+ end
34
+
35
+ if $sim_count == 1
36
+ make_request
37
+ else
38
+ threads = []
39
+ (1..$sim_count).each do |i|
40
+ threads << Thread.new(i) do |i|
41
+ make_request("Thread ##{i}: ")
42
+ end
43
+ end
44
+ threads.each {|t| t.join}
45
+ end
@@ -0,0 +1,12 @@
1
+ class ReverseEchoWorker < ModernTimes::HornetQRequestor::Worker
2
+ include ModernTimes::HornetQ::MarshalStrategy::String
3
+
4
+ def request(obj)
5
+ puts "#{self}: Received #{obj} at #{Time.now}"
6
+ if obj =~ /^sleep (.*)/
7
+ sleep $1.to_f
8
+ puts "#{self}: Finished sleeping at #{Time.now}"
9
+ end
10
+ obj.reverse
11
+ end
12
+ end
@@ -1,15 +1,20 @@
1
1
  module ModernTimes
2
2
  module Base
3
3
  class Supervisor
4
- attr_reader :manager, :worker_klass
4
+ attr_reader :manager, :worker_klass, :name, :worker_options
5
5
 
6
- def initialize(manager, worker_klass, options)
7
- @stopped = false
8
- @manager = manager
9
- @worker_klass = worker_klass
10
- @workers = []
11
- @worker_mutex = Mutex.new
12
- @failure_mutex = Mutex.new
6
+ # Create new supervisor to manage a number of similar workers
7
+ # supervisor_options are those options defined on the Worker's Supervisor line
8
+ # worker_options are options passed in when creating a new instance
9
+ def initialize(manager, worker_klass, supervisor_options, worker_options)
10
+ @stopped = false
11
+ @manager = manager
12
+ @worker_klass = worker_klass
13
+ @name = worker_options.delete(:name) || worker_klass.default_name
14
+ @worker_options = worker_options
15
+ @workers = []
16
+ @worker_mutex = Mutex.new
17
+ @failure_mutex = Mutex.new
13
18
  end
14
19
 
15
20
  def worker_count
@@ -23,7 +28,7 @@ module ModernTimes
23
28
  curr_count = @workers.size
24
29
  if curr_count < count
25
30
  (curr_count...count).each do |index|
26
- worker = @worker_klass.new
31
+ worker = @worker_klass.new(@worker_options)
27
32
  worker.supervisor = self
28
33
  worker.index = index
29
34
  if index == 0
@@ -1,7 +1,9 @@
1
+ require 'json'
2
+
1
3
  module ModernTimes
2
4
  module Base
3
5
  class Worker
4
- attr_accessor :name, :index, :supervisor, :thread
6
+ attr_accessor :index, :supervisor, :thread
5
7
 
6
8
  def self.supervisor(klass, options={})
7
9
  # self.class_eval do
@@ -12,8 +14,8 @@ module ModernTimes
12
14
  # end
13
15
  # TODO: This is nasty but I'm not sure how to create a dynamic class method within a scope
14
16
  eval <<-EOS
15
- def self.create_supervisor(manager)
16
- #{klass.name}.new(manager, self, #{options.inspect})
17
+ def self.create_supervisor(manager, worker_options)
18
+ #{klass.name}.new(manager, self, #{options.to_json}, worker_options)
17
19
  end
18
20
  EOS
19
21
  end
@@ -22,11 +24,6 @@ module ModernTimes
22
24
  supervisor Supervisor
23
25
 
24
26
  def initialize(opts={})
25
- @name = opts[:name] || self.class.default_name
26
- end
27
-
28
- def name
29
- @name
30
27
  end
31
28
 
32
29
  # One time initialization prior to first thread
@@ -4,6 +4,7 @@ require 'hornetq'
4
4
  module ModernTimes
5
5
  module HornetQ
6
6
  class Publisher
7
+ attr_reader :address
7
8
 
8
9
  # TODO: Possible performance enhancements on producer
9
10
  # setDisableMessageID()
@@ -31,22 +32,14 @@ module ModernTimes
31
32
  end
32
33
 
33
34
  # Publish the given object to the address.
34
- def publish(object)
35
+ def publish(object, user_id=nil, props={})
35
36
  Client.session_pool.producer(@address) do |session, producer|
36
37
  message = marshal(session, object, @durable)
37
- first_time = true
38
- begin
39
- producer.send(message)
40
- rescue Java::org.hornetq.api.core.HornetQException => e
41
- ModernTimes.logger.warn "Received producer exception: #{e.message} with code=#{e.cause.code}"
42
- if first_time && e.cause.code == Java::org.hornetq.api.core.HornetQException::UNBLOCKED
43
- ModernTimes.logger.info "Retrying the send"
44
- first_time = false
45
- retry
46
- else
47
- raise
48
- end
38
+ message.user_id = user_id if user_id
39
+ props.each do |key, value|
40
+ message.putStringProperty(key, value)
49
41
  end
42
+ producer.send_with_retry(message)
50
43
  end
51
44
  end
52
45
 
@@ -6,13 +6,16 @@ module ModernTimes
6
6
 
7
7
  attr_reader :message_count
8
8
 
9
- def initialize(manager, worker_name, opts={})
10
- super(manager, worker_name, opts)
9
+ def initialize(manager, worker_name, supervisor_options, worker_options)
10
+ super
11
11
  @message_count = 0
12
+ @message_count_mutex = Mutex.new
12
13
  end
13
14
 
14
15
  def incr_message_count
15
- @message_count += 1
16
+ @message_count_mutex.synchronize do
17
+ @message_count += 1
18
+ end
16
19
  end
17
20
  end
18
21
  end
@@ -1,12 +1,12 @@
1
1
  module ModernTimes
2
2
  module HornetQ
3
3
  class SupervisorMBean < ModernTimes::Base::SupervisorMBean
4
+ r_attribute :message_count, :int, 'Total message count', :message_count
4
5
 
5
- operation 'Total message count'
6
- returns :int
7
6
  def message_count
8
7
  supervisor.message_count
9
8
  end
9
+
10
10
  end
11
11
  end
12
12
  end
@@ -11,7 +11,8 @@ module ModernTimes
11
11
 
12
12
  attr_reader :session, :message_count
13
13
 
14
- def initialize
14
+ def initialize(opts={})
15
+ super
15
16
  @status = 'initialized'
16
17
  @message_count = 0
17
18
  end
@@ -64,9 +65,7 @@ module ModernTimes
64
65
 
65
66
  # Start the event loop for handling messages off the queue
66
67
  def start
67
- @session = Client.create_consumer_session
68
- @consumer = @session.create_consumer(queue_name)
69
- @session.start
68
+ session_init
70
69
  ModernTimes.logger.debug "#{self}: Starting receive loop"
71
70
  @status = nil
72
71
  while msg = @consumer.receive
@@ -102,6 +101,13 @@ module ModernTimes
102
101
  protected
103
102
  #########
104
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
+
105
111
  # Create a queue, assigned to the specified address
106
112
  # Every time a message arrives, the perform instance method
107
113
  # will be called. The parameter to the method is the Ruby
@@ -0,0 +1,49 @@
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
@@ -0,0 +1,48 @@
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
@@ -0,0 +1,29 @@
1
+ module ModernTimes
2
+ module HornetQRequestor
3
+
4
+ # Base Worker Class for any class that will be processing messages from queues
5
+ class Worker < ModernTimes::HornetQ::Worker
6
+ # Make HornetQRequestor::Supervisor our supervisor
7
+ #supervisor Supervisor
8
+
9
+ def on_message(message)
10
+ @reply_queue = message.get_string_property(Java::OrgHornetqCoreClientImpl::ClientMessageImpl::REPLYTO_HEADER_NAME)
11
+ @message_id = message.get_string_property(MESSAGE_ID)
12
+ super
13
+ end
14
+
15
+ def perform(object)
16
+ response = request(object)
17
+ session.producer(@reply_queue) do |producer|
18
+ reply_message = marshal(session, response, false)
19
+ reply_message.put_string_property(MESSAGE_ID, @message_id)
20
+ producer.send_with_retry(reply_message)
21
+ end
22
+ end
23
+
24
+ def request(object)
25
+ raise "#{self}: Need to override request method in #{self.class.name} in order to act on #{object}"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'modern_times/hornetq_requestor/request_handle'
2
+ require 'modern_times/hornetq_requestor/requestor'
3
+ require 'modern_times/hornetq_requestor/worker'
4
+
5
+ module ModernTimes
6
+ module HornetQRequestor
7
+ MESSAGE_ID = 'ModernTimesMessageId'
8
+ end
9
+ end
@@ -3,13 +3,14 @@ module ModernTimes
3
3
  attr_accessor :allowed_workers
4
4
 
5
5
  def initialize(config={})
6
+ @stopped = false
6
7
  @config = config
7
8
  @domain = config[:domain] || 'ModernTimes'
8
9
  @supervisors = []
9
10
  @jmx_server = JMX::MBeanServer.new
10
11
  bean = ManagerMBean.new("#{@domain}.Manager", "Manager", self)
11
12
  @jmx_server.register_mbean(bean, "#{@domain}:type=Manager")
12
- persist_file = config[:persist_file]
13
+ self.persist_file = config[:persist_file]
13
14
  end
14
15
 
15
16
  def add(worker_klass, num_workers, worker_options)
@@ -24,11 +25,11 @@ module ModernTimes
24
25
  if @allowed_workers && !@allowed_workers.include?(worker_klass)
25
26
  raise ModernTimes::Exception.new("Error: #{worker_klass.name} is not an allowed worker")
26
27
  end
27
- supervisor = worker_klass.create_supervisor(self)
28
+ supervisor = worker_klass.create_supervisor(self, worker_options)
28
29
  mbean = supervisor.create_mbean(@domain)
29
30
  @supervisors << supervisor
30
31
  supervisor.worker_count = num_workers
31
- @jmx_server.register_mbean(mbean, "#{@domain}:worker=#{worker_klass.name},type=Worker")
32
+ @jmx_server.register_mbean(mbean, "#{@domain}:worker=#{supervisor.name},type=Worker")
32
33
  ModernTimes.logger.info "Started #{worker_klass.name} with #{num_workers} workers"
33
34
  rescue Exception => e
34
35
  ModernTimes.logger.error "Exception trying to add #{worker_klass.name}: #{e.message}\n\t#{e.backtrace.join("\n\t")}"
@@ -69,8 +70,12 @@ module ModernTimes
69
70
  @persist_file = file
70
71
  if File.exist?(file)
71
72
  hash = YAML.load_file(file)
72
- hash.each do |worker_klass, count|
73
- add(worker_klass, count)
73
+ hash.each do |worker_name, worker_hash|
74
+ klass = worker_hash[:klass]
75
+ count = worker_hash[:count]
76
+ options = worker_hash[:options]
77
+ options[:name] = worker_name
78
+ add(klass, count, options)
74
79
  end
75
80
  end
76
81
  end
@@ -79,9 +84,10 @@ module ModernTimes
79
84
  return unless @persist_file
80
85
  hash = {}
81
86
  @supervisors.each do |supervisor|
82
- hash[supervisor.worker_name] = {
83
- :worker_count => supervisor.worker_count,
84
- :options => supervisor.worker_options
87
+ hash[supervisor.name] = {
88
+ :klass => supervisor.worker_klass.name,
89
+ :count => supervisor.worker_count,
90
+ :options => supervisor.worker_options
85
91
  }
86
92
  end
87
93
  File.open(@persist_file, 'w') do |out|
@@ -3,18 +3,17 @@ require 'jmx'
3
3
  module ModernTimes
4
4
  class ManagerMBean < RubyDynamicMBean
5
5
  attr_reader :manager
6
- rw_attribute :foobar, :int, "Number of workers"
6
+ r_attribute :allowed_workers, :list, 'Allowed workers'
7
7
 
8
8
  def initialize(name, description, manager)
9
9
  super(name, description)
10
10
  @manager = manager
11
11
  end
12
12
 
13
- operation 'Allowed workers'
14
- returns :list
15
13
  def allowed_workers
16
14
  all = manager.allowed_workers || ['No Restrictions']
17
- all.map {|worker_klass| worker_klass.name }
15
+ all = all.map {|worker_klass| worker_klass.name }
16
+ java.util.ArrayList.new(all)
18
17
  end
19
18
 
20
19
  operation 'Start worker'
@@ -23,7 +22,7 @@ module ModernTimes
23
22
  returns :string
24
23
  def start_worker(worker, count)
25
24
  ModernTimes.logger.debug "Attempting to start #{worker} with count=#{count}"
26
- manager.add(worker, count)
25
+ manager.add(worker, count, {})
27
26
  return 'Successfuly started'
28
27
  rescue Exception => e
29
28
  ModernTimes.logger.error "Exception starting worker #{worker}: {e.message}\n\t#{e.backtrace.join("\n\t")}"
data/lib/modern_times.rb CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'modern_times/exception'
3
3
  require 'modern_times/base'
4
4
  require 'modern_times/hornetq'
5
+ require 'modern_times/hornetq_requestor'
5
6
  require 'modern_times/manager_mbean'
6
7
  require 'modern_times/manager'
7
8
  require 'modern_times/loggable'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: modern_times
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: 0.1.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Brad Pardee
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-03-14 00:00:00 -04:00
14
+ date: 2011-03-24 00:00:00 -04:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -22,20 +22,31 @@ dependencies:
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 0.3.2
25
+ version: 0.3.3
26
26
  type: :runtime
27
27
  version_requirements: *id001
28
28
  - !ruby/object:Gem::Dependency
29
- name: ClarityServices-jmxjr
29
+ name: jmx
30
30
  prerelease: false
31
31
  requirement: &id002 !ruby/object:Gem::Requirement
32
32
  none: false
33
33
  requirements:
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: "0"
36
+ version: "0.6"
37
37
  type: :runtime
38
38
  version_requirements: *id002
39
+ - !ruby/object:Gem::Dependency
40
+ name: json
41
+ prerelease: false
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id003
39
50
  description: Generic asynchronous task library
40
51
  email:
41
52
  - bradpardee@gmail.com
@@ -52,6 +63,12 @@ files:
52
63
  - README.rdoc
53
64
  - Rakefile
54
65
  - VERSION
66
+ - examples/requestor/.gitignore
67
+ - examples/requestor/README
68
+ - examples/requestor/hornetq.yml
69
+ - examples/requestor/manager.rb
70
+ - examples/requestor/request.rb
71
+ - examples/requestor/reverse_echo_worker.rb
55
72
  - examples/simple/.gitignore
56
73
  - examples/simple/README
57
74
  - examples/simple/bar_worker.rb
@@ -75,6 +92,10 @@ files:
75
92
  - lib/modern_times/hornetq/supervisor.rb
76
93
  - lib/modern_times/hornetq/supervisor_mbean.rb
77
94
  - lib/modern_times/hornetq/worker.rb
95
+ - lib/modern_times/hornetq_requestor.rb
96
+ - lib/modern_times/hornetq_requestor/request_handle.rb
97
+ - lib/modern_times/hornetq_requestor/requestor.rb
98
+ - lib/modern_times/hornetq_requestor/worker.rb
78
99
  - lib/modern_times/loggable.rb
79
100
  - lib/modern_times/manager.rb
80
101
  - lib/modern_times/manager_mbean.rb
@@ -113,6 +134,9 @@ signing_key:
113
134
  specification_version: 3
114
135
  summary: Asynchronous task library
115
136
  test_files:
137
+ - examples/requestor/manager.rb
138
+ - examples/requestor/request.rb
139
+ - examples/requestor/reverse_echo_worker.rb
116
140
  - examples/simple/bar_worker.rb
117
141
  - examples/simple/baz_worker.rb
118
142
  - examples/simple/manager.rb