qwirk 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/README.md +9 -14
  2. data/lib/qwirk.rb +26 -17
  3. data/lib/qwirk/adapter.rb +3 -45
  4. data/lib/qwirk/adapter/base.rb +2 -0
  5. data/lib/qwirk/adapter/base/expanding_worker_config.rb +133 -0
  6. data/lib/qwirk/adapter/base/worker_config.rb +104 -0
  7. data/lib/qwirk/adapter/in_memory.rb +13 -0
  8. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/factory.rb +2 -2
  9. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/publisher.rb +4 -4
  10. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/queue.rb +3 -2
  11. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/reply_queue.rb +3 -2
  12. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/topic.rb +2 -2
  13. data/lib/qwirk/{queue_adapter/in_mem → adapter/in_memory}/worker.rb +6 -8
  14. data/lib/qwirk/adapter/in_memory/worker_config.rb +50 -0
  15. data/lib/qwirk/adapter/inline.rb +9 -0
  16. data/lib/qwirk/adapter/inline/publisher.rb +86 -0
  17. data/lib/qwirk/adapter/inline/worker.rb +55 -0
  18. data/lib/qwirk/adapter/inline/worker_config.rb +30 -0
  19. data/lib/qwirk/adapter_factory.rb +48 -0
  20. data/lib/qwirk/base_worker.rb +18 -28
  21. data/lib/qwirk/batch/file_worker.rb +4 -4
  22. data/lib/qwirk/manager.rb +11 -8
  23. data/lib/qwirk/marshal_strategy/none.rb +1 -1
  24. data/lib/qwirk/publish_handle.rb +22 -11
  25. data/lib/qwirk/publisher.rb +9 -9
  26. data/lib/qwirk/{request_worker.rb → reply_worker.rb} +3 -3
  27. data/lib/qwirk/worker.rb +27 -29
  28. data/test/jms_fail_test.rb +11 -11
  29. data/test/jms_requestor_block_test.rb +12 -12
  30. data/test/jms_requestor_test.rb +8 -8
  31. data/test/jms_test.rb +10 -10
  32. metadata +104 -185
  33. data/examples/README +0 -1
  34. data/examples/activemq.xml +0 -84
  35. data/examples/advanced_requestor/README.md +0 -15
  36. data/examples/advanced_requestor/base_request_worker.rb +0 -18
  37. data/examples/advanced_requestor/char_count_worker.rb +0 -16
  38. data/examples/advanced_requestor/config.ru +0 -24
  39. data/examples/advanced_requestor/exception_raiser_worker.rb +0 -17
  40. data/examples/advanced_requestor/length_worker.rb +0 -14
  41. data/examples/advanced_requestor/print_worker.rb +0 -14
  42. data/examples/advanced_requestor/publisher.rb +0 -49
  43. data/examples/advanced_requestor/qwirk.yml +0 -16
  44. data/examples/advanced_requestor/reverse_worker.rb +0 -14
  45. data/examples/advanced_requestor/triple_worker.rb +0 -14
  46. data/examples/batch/my_batch_worker.rb +0 -30
  47. data/examples/batch/my_line_worker.rb +0 -8
  48. data/examples/qwirk.yml +0 -20
  49. data/examples/requestor/README.md +0 -13
  50. data/examples/requestor/config.ru +0 -13
  51. data/examples/requestor/qwirk_persist.yml +0 -5
  52. data/examples/requestor/requestor.rb +0 -68
  53. data/examples/requestor/reverse_echo_worker.rb +0 -15
  54. data/examples/setup.rb +0 -13
  55. data/examples/shared/README.md +0 -24
  56. data/examples/shared/config.ru +0 -13
  57. data/examples/shared/publisher.rb +0 -49
  58. data/examples/shared/qwirk_persist.yml +0 -5
  59. data/examples/shared/shared_worker.rb +0 -16
  60. data/examples/simple/README +0 -53
  61. data/examples/simple/bar_worker.rb +0 -10
  62. data/examples/simple/baz_worker.rb +0 -10
  63. data/examples/simple/config.ru +0 -14
  64. data/examples/simple/publisher.rb +0 -49
  65. data/examples/simple/qwirk_persist.yml +0 -4
  66. data/examples/simple/tmp/kahadb/db-1.log +0 -0
  67. data/examples/simple/tmp/kahadb/db.data +0 -0
  68. data/examples/simple/tmp/kahadb/db.redo +0 -0
  69. data/examples/task/README +0 -47
  70. data/examples/task/config.ru +0 -14
  71. data/examples/task/foo_worker.rb +0 -10
  72. data/examples/task/messages.out +0 -1000
  73. data/examples/task/publisher.rb +0 -25
  74. data/examples/task/qwirk_persist.yml +0 -5
  75. data/examples/task/task.rb +0 -36
  76. data/lib/qwirk/queue_adapter.rb +0 -3
  77. data/lib/qwirk/queue_adapter/active_mq.rb +0 -13
  78. data/lib/qwirk/queue_adapter/active_mq/publisher.rb +0 -12
  79. data/lib/qwirk/queue_adapter/active_mq/worker_config.rb +0 -16
  80. data/lib/qwirk/queue_adapter/in_mem.rb +0 -7
  81. data/lib/qwirk/queue_adapter/in_mem/worker_config.rb +0 -59
  82. data/lib/qwirk/queue_adapter/jms.rb +0 -50
  83. data/lib/qwirk/queue_adapter/jms/connection.rb +0 -42
  84. data/lib/qwirk/queue_adapter/jms/consumer.rb +0 -37
  85. data/lib/qwirk/queue_adapter/jms/publisher.rb +0 -126
  86. data/lib/qwirk/queue_adapter/jms/worker.rb +0 -89
  87. data/lib/qwirk/queue_adapter/jms/worker_config.rb +0 -38
  88. data/lib/qwirk/version.rb +0 -3
  89. data/lib/qwirk/worker_config.rb +0 -187
@@ -1,89 +0,0 @@
1
- # Handle Messaging and Queuing using JMS
2
- module Qwirk
3
- module QueueAdapter
4
- module JMS
5
- class Worker
6
- def initialize(worker_config)
7
- @worker_config = worker_config
8
- @name = worker_config.parent.name
9
- @marshaler = worker_config.parent.marshaler
10
- @session = worker_config.connection.create_session
11
- @consumer = @session.consumer(worker_config.destination)
12
- @session.start
13
- end
14
-
15
- def receive_message
16
- @consumer.receive
17
- end
18
-
19
- def acknowledge_message(msg)
20
- msg.acknowledge
21
- end
22
-
23
- def send_response(original_message, marshaled_object)
24
- do_send_response(@marshaler, original_message, marshaled_object)
25
- end
26
-
27
- def send_exception(original_message, e)
28
- @string_marshaler ||= MarshalStrategy.find(:string)
29
- do_send_response(@string_marshaler, original_message, "Exception: #{e.message}") do |reply_message|
30
- reply_message['qwirk:exception'] = Qwirk::RemoteException.new(e).to_hash.to_yaml
31
- end
32
- end
33
-
34
- def message_to_object(msg)
35
- marshaler = Qwirk::MarshalStrategy.find(msg['qwirk:marshal'] || :ruby)
36
- return marshaler.unmarshal(msg.data)
37
- end
38
-
39
- def handle_failure(message, fail_queue_name)
40
- @session.producer(:queue_name => fail_queue_name) do |producer|
41
- # TODO: Can't add attribute to read-only message?
42
- #message['qwirk:exception'] = Qwirk::RemoteException.new(e).to_hash.to_yaml
43
- producer.send(message)
44
- end
45
- end
46
-
47
- def stop
48
- puts "in jms worker stop"
49
- return if @stopped
50
- Qwirk.logger.info "Stopping JMS worker #{@name}"
51
- # Don't clobber the session before a reply
52
- @consumer.close if @consumer
53
- @session.close if @session
54
- @stopped = true
55
- end
56
-
57
- private
58
-
59
- def do_send_response(marshaler, original_message, marshaled_object)
60
- return false unless original_message.reply_to
61
- begin
62
- @session.producer(:destination => original_message.reply_to) do |producer|
63
- # For time_to_live and jms_deliver_mode, first use the local response_options if they're' set, otherwise
64
- # use the value from the original_message attributes if they're' set
65
- time_to_live = @time_to_live || original_message['qwirk:response:time_to_live']
66
- persistent = @persistent
67
- persistent = (original_message['qwirk:response:persistent'] == 'true') if persistent.nil? && original_message['qwirk:response:persistent']
68
- # If persistent isn't set anywhere, then default to true unless time_to_live has been set
69
- persistent = !time_to_live if persistent.nil?
70
- # The reply is persistent if we explicitly set it or if we don't expire
71
- producer.delivery_mode_sym = persistent ? :persistent : :non_persistent
72
- producer.time_to_live = time_to_live.to_i if time_to_live
73
- reply_message = Qwirk::QueueAdapter::JMS.create_message(@session, marshaled_object, marshaler.marshal_type)
74
- reply_message.jms_correlation_id = original_message.jms_message_id
75
- reply_message['qwirk:marshal'] = marshaler.to_sym.to_s
76
- reply_message['qwirk:worker'] = @name
77
- reply_message['QwirkTaskID'] = original_message['QwirkTaskID'] if original_message['QwirkTaskID']
78
- yield reply_message if block_given?
79
- producer.send(reply_message)
80
- end
81
- rescue Exception => e
82
- Qwirk.logger.error {"Error attempting to send response: #{e.message}\n\t#{e.backtrace.join("\n\t")}"}
83
- end
84
- return true
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,38 +0,0 @@
1
- # Handle Messaging and Queuing using JMS
2
- module Qwirk
3
- module QueueAdapter
4
- module JMS
5
- class WorkerConfig
6
- include Rumx::Bean
7
-
8
- #bean_reader :queue_size, :integer, 'Current count of messages in the queue'
9
-
10
- attr_reader :connection, :parent, :destination, :marshaler, :time_to_live, :persistent, :stopped
11
-
12
- def initialize(queue_adapter, parent, queue_name, topic_name, options, response_options)
13
- @connection = queue_adapter.adapter_info
14
- @parent = parent
15
- @destination = {:queue_name => queue_name} if queue_name
16
- @destination = {:topic_name => topic_name} if topic_name
17
- # Time in msec until the message gets discarded, should be more than the timeout on the requestor side
18
- @time_to_live = response_options[:time_to_live]
19
- @persistent = response_options[:persistent]
20
- end
21
-
22
- # Default marshal type for the response
23
- def default_marshal_sym
24
- :ruby
25
- end
26
-
27
- def create_worker
28
- Worker.new(self)
29
- end
30
-
31
- def stop
32
- puts "in jms worker config stop"
33
- @stopped = true
34
- end
35
- end
36
- end
37
- end
38
- end
data/lib/qwirk/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module Qwirk
2
- VERSION = '0.0.1'
3
- end
@@ -1,187 +0,0 @@
1
- require 'rumx'
2
-
3
- module Qwirk
4
- class WorkerConfig
5
- include Rumx::Bean
6
-
7
- attr_reader :name, :marshaler
8
-
9
- bean_reader :count, :integer, 'Current number of workers'
10
- bean_attr_accessor :min_count, :integer, 'Min number of workers allowed', :config_item => true
11
- bean_attr_accessor :max_count, :integer, 'Max number of workers allowed', :config_item => true
12
- bean_attr_accessor :idle_worker_timeout, :integer, 'Timeout where an idle worker will be removed from the worker pool and it\'s resources closed (0 for no removal)', :config_item => true
13
- bean_attr_accessor :max_read_threshold, :float, 'Threshold where a new worker will be added if none of the workers have had to wait this amount of time on a read', :config_item => true
14
- # The adapter refers to the corresponding class in Qwirk::QueueAdapter::<type>::WorkerConfig
15
- bean_attr_reader :adapter, :bean, 'Adapter for worker queue interface'
16
- bean_attr_reader :timer, :bean, 'Track the times for this worker'
17
- bean_attr_accessor :log_times, :boolean, 'Log the times for this worker'
18
-
19
- # Define the default config values for the attributes all workers will share. These will be sent as options to the constructor
20
- def self.initial_default_config
21
- {:min_count => 0, :max_count => 0, :idle_worker_timeout => 60, :max_read_threshold => 1.0}
22
- end
23
-
24
- # Create new WorkerConfig to manage workers of a common class
25
- def initialize(queue_adapter, name, manager, worker_class, default_options, options)
26
- @name = name
27
- @manager = manager
28
- @worker_class = worker_class
29
- @workers = []
30
- @stopped = false
31
- @min_count = 0
32
- @max_count = 0
33
- @index_count = 0
34
- @index_mutex = Mutex.new
35
- @worker_mutex = Mutex.new
36
- @worker_condition = ConditionVariable.new
37
- response_options = worker_class.queue_options[:response] || {}
38
- @adapter = queue_adapter.create_adapter_worker_config(self, worker_class.queue_name(@name), worker_class.topic_name, worker_class.queue_options, response_options)
39
- # Defines how we will marshal the response
40
- marshal_sym = (response_options[:marshal] || @adapter.default_marshal_sym)
41
- @marshaler = MarshalStrategy.find(marshal_sym)
42
- @log_times = queue_adapter.log_times
43
-
44
- #Qwirk.logger.debug { "options=#{options.inspect}" }
45
- default_options.each do |key, value|
46
- begin
47
- send(key.to_s+'=', value)
48
- rescue Exception => e
49
- # Let config_reader's set a default value
50
- begin
51
- instance_variable_set("@#{key}", value)
52
- rescue Exception => e
53
- Qwirk.logger.warn "WARNING: During initialization of #{worker_class.name} config=#{@name}, default assignment of #{key}=#{value} was invalid"
54
- end
55
- end
56
- end
57
- # Run the specified options after the default options, so that codependant options don't get overwritten (like min_count/max_count)
58
- options.each do |key, value|
59
- begin
60
- send(key.to_s+'=', value)
61
- rescue Exception => e
62
- Qwirk.logger.warn "WARNING: During initialization of #{worker_class.name} config=#{@name}, assignment of #{key}=#{value} was invalid"
63
- end
64
- end
65
- end
66
-
67
- def count
68
- @worker_mutex.synchronize { return @workers.size }
69
- end
70
-
71
- def min_count=(new_min_count)
72
- return if @min_count == new_min_count
73
- raise "#{@worker_class.name}-#{@name}: Can't change count since we've been stopped" if @stopped
74
- Qwirk.logger.info "#{@worker_class.name}: Changing min number of workers from #{@min_count} to #{new_min_count}"
75
- self.max_count = new_min_count if @max_count < new_min_count
76
- @worker_mutex.synchronize do
77
- add_worker while @workers.size < new_min_count
78
- @min_count = new_min_count
79
- end
80
- end
81
-
82
- def max_count=(new_max_count)
83
- return if @max_count == new_max_count
84
- raise "#{@worker_class.name}-#{@name}: Can't change count since we've been stopped" if @stopped
85
- Qwirk.logger.info "#{@worker_class.name}: Changing max number of workers from #{@max_count} to #{new_max_count}"
86
- self.min_count = new_max_count if @min_count > new_max_count
87
- @min_count = 1 if @min_count == 0 && new_max_count > 0
88
- @worker_mutex.synchronize do
89
- @timer ||= Rumx::Beans::TimerAndError.new
90
- if @workers.size > new_max_count
91
- @workers[new_max_count..-1].each { |worker| worker.stop }
92
- while @workers.size > new_max_count
93
- @workers.last.stop
94
- @worker_condition.wait(@worker_mutex)
95
- end
96
- end
97
- @max_count = new_max_count
98
- end
99
- end
100
-
101
- def stop
102
- Qwirk.logger.debug { "In Base worker_config stop" }
103
- # First stop the adapter. For InMem, this will not return until all the messages in the queue have
104
- # been processed since these messages are not persistent.
105
- @adapter.stop
106
- @worker_mutex.synchronize do
107
- @workers.each { |worker| worker.stop }
108
- while @workers.size > 0
109
- @worker_condition.wait(@worker_mutex)
110
- end
111
- @stopped = true
112
- end
113
- end
114
-
115
- def worker_stopped(worker)
116
- remove_worker(worker)
117
- end
118
-
119
- # Override rumx bean method
120
- def bean_attributes_changed
121
- super
122
- @manager.save_persist_state
123
- end
124
-
125
- def marshal_response(object)
126
- @marshaler.marshal(object)
127
- end
128
-
129
- def unmarshal_response(marshaled_object)
130
- @marshaler.unmarshal(marshaled_object)
131
- end
132
-
133
- def periodic_call(poll_time)
134
- now = Time.now
135
- add_new_worker = true
136
- worker_stopped = false
137
- @worker_mutex.synchronize do
138
- # reverse_each to remove later workers first
139
- @workers.reverse_each do |worker|
140
- start_worker_time = worker.start_worker_time
141
- start_read_time = worker.start_read_time
142
- if !start_read_time || (now - start_worker_time) < (poll_time + @max_read_threshold)
143
- #Qwirk.logger.debug { "#{self}: Skipping newly created worker" }
144
- add_new_worker = false
145
- next
146
- end
147
- end_read_time = worker.start_processing_time
148
- # If the processing time is actually from the previous processing, then we're probably still waiting for the read to complete.
149
- if !end_read_time || end_read_time < start_read_time
150
- if !worker_stopped && @workers.size > @min_count && (now - start_read_time) > @idle_worker_timeout
151
- worker.stop
152
- worker_stopped = true
153
- end
154
- end_read_time = now
155
- end
156
- #Qwirk.logger.debug { "#{self}: start=#{start_read_time} end=#{end_read_time} thres=#{@max_read_threshold} add_new_worker=#{add_new_worker}" }
157
- add_new_worker = false if (end_read_time - start_read_time) > @max_read_threshold
158
- end
159
- add_worker if add_new_worker && @workers.size < @max_count
160
- end
161
- end
162
-
163
- def to_s
164
- @name
165
- end
166
-
167
- private
168
-
169
- def add_worker
170
- worker = @worker_class.new
171
- worker.start(@index_count, self)
172
- Qwirk.logger.debug {"#{self}: Adding worker #{worker}"}
173
- @index_mutex.synchronize { @index_count += 1 }
174
- @workers << worker
175
- rescue Exception => e
176
- Qwirk.logger.error("Unable to add #{@worker_class} worker: #{e.message}\n\t#{e.backtrace.join("\n\t")}")
177
- end
178
-
179
- def remove_worker(worker)
180
- Qwirk.logger.debug {"#{self}: Deleting worker #{worker}"}
181
- @worker_mutex.synchronize do
182
- @workers.delete(worker)
183
- @worker_condition.broadcast
184
- end
185
- end
186
- end
187
- end