qwirk 0.0.1
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/History.md +7 -0
- data/LICENSE.txt +201 -0
- data/README.md +180 -0
- data/Rakefile +34 -0
- data/examples/README +1 -0
- data/examples/activemq.xml +84 -0
- data/examples/advanced_requestor/README.md +15 -0
- data/examples/advanced_requestor/base_request_worker.rb +18 -0
- data/examples/advanced_requestor/char_count_worker.rb +16 -0
- data/examples/advanced_requestor/config.ru +24 -0
- data/examples/advanced_requestor/exception_raiser_worker.rb +17 -0
- data/examples/advanced_requestor/length_worker.rb +14 -0
- data/examples/advanced_requestor/print_worker.rb +14 -0
- data/examples/advanced_requestor/publisher.rb +49 -0
- data/examples/advanced_requestor/qwirk.yml +16 -0
- data/examples/advanced_requestor/reverse_worker.rb +14 -0
- data/examples/advanced_requestor/triple_worker.rb +14 -0
- data/examples/batch/my_batch_worker.rb +30 -0
- data/examples/batch/my_line_worker.rb +8 -0
- data/examples/qwirk.yml +20 -0
- data/examples/requestor/README.md +13 -0
- data/examples/requestor/config.ru +13 -0
- data/examples/requestor/qwirk_persist.yml +5 -0
- data/examples/requestor/requestor.rb +68 -0
- data/examples/requestor/reverse_echo_worker.rb +15 -0
- data/examples/setup.rb +13 -0
- data/examples/shared/README.md +24 -0
- data/examples/shared/config.ru +13 -0
- data/examples/shared/publisher.rb +49 -0
- data/examples/shared/qwirk_persist.yml +5 -0
- data/examples/shared/shared_worker.rb +16 -0
- data/examples/simple/README +53 -0
- data/examples/simple/bar_worker.rb +10 -0
- data/examples/simple/baz_worker.rb +10 -0
- data/examples/simple/config.ru +14 -0
- data/examples/simple/publisher.rb +49 -0
- data/examples/simple/qwirk_persist.yml +4 -0
- data/examples/simple/tmp/kahadb/db-1.log +0 -0
- data/examples/simple/tmp/kahadb/db.data +0 -0
- data/examples/simple/tmp/kahadb/db.redo +0 -0
- data/examples/task/README +47 -0
- data/examples/task/config.ru +14 -0
- data/examples/task/foo_worker.rb +10 -0
- data/examples/task/messages.out +1000 -0
- data/examples/task/publisher.rb +25 -0
- data/examples/task/qwirk_persist.yml +5 -0
- data/examples/task/task.rb +36 -0
- data/lib/qwirk.rb +63 -0
- data/lib/qwirk/adapter.rb +45 -0
- data/lib/qwirk/base_worker.rb +96 -0
- data/lib/qwirk/batch.rb +4 -0
- data/lib/qwirk/batch/acquire_file_strategy.rb +47 -0
- data/lib/qwirk/batch/active_record.rb +3 -0
- data/lib/qwirk/batch/active_record/batch_job.rb +111 -0
- data/lib/qwirk/batch/active_record/failed_record.rb +5 -0
- data/lib/qwirk/batch/active_record/outstanding_record.rb +6 -0
- data/lib/qwirk/batch/file_status_strategy.rb +86 -0
- data/lib/qwirk/batch/file_worker.rb +228 -0
- data/lib/qwirk/batch/job_status.rb +29 -0
- data/lib/qwirk/batch/parse_file_strategy.rb +48 -0
- data/lib/qwirk/engine.rb +9 -0
- data/lib/qwirk/loggable.rb +23 -0
- data/lib/qwirk/manager.rb +140 -0
- data/lib/qwirk/marshal_strategy.rb +74 -0
- data/lib/qwirk/marshal_strategy/bson.rb +37 -0
- data/lib/qwirk/marshal_strategy/json.rb +37 -0
- data/lib/qwirk/marshal_strategy/none.rb +26 -0
- data/lib/qwirk/marshal_strategy/ruby.rb +26 -0
- data/lib/qwirk/marshal_strategy/string.rb +25 -0
- data/lib/qwirk/marshal_strategy/yaml.rb +25 -0
- data/lib/qwirk/publish_handle.rb +170 -0
- data/lib/qwirk/publisher.rb +67 -0
- data/lib/qwirk/queue_adapter.rb +3 -0
- data/lib/qwirk/queue_adapter/active_mq.rb +13 -0
- data/lib/qwirk/queue_adapter/active_mq/publisher.rb +12 -0
- data/lib/qwirk/queue_adapter/active_mq/worker_config.rb +16 -0
- data/lib/qwirk/queue_adapter/in_mem.rb +7 -0
- data/lib/qwirk/queue_adapter/in_mem/factory.rb +45 -0
- data/lib/qwirk/queue_adapter/in_mem/publisher.rb +98 -0
- data/lib/qwirk/queue_adapter/in_mem/queue.rb +88 -0
- data/lib/qwirk/queue_adapter/in_mem/reply_queue.rb +56 -0
- data/lib/qwirk/queue_adapter/in_mem/topic.rb +48 -0
- data/lib/qwirk/queue_adapter/in_mem/worker.rb +63 -0
- data/lib/qwirk/queue_adapter/in_mem/worker_config.rb +59 -0
- data/lib/qwirk/queue_adapter/jms.rb +50 -0
- data/lib/qwirk/queue_adapter/jms/connection.rb +42 -0
- data/lib/qwirk/queue_adapter/jms/consumer.rb +37 -0
- data/lib/qwirk/queue_adapter/jms/publisher.rb +126 -0
- data/lib/qwirk/queue_adapter/jms/worker.rb +89 -0
- data/lib/qwirk/queue_adapter/jms/worker_config.rb +38 -0
- data/lib/qwirk/remote_exception.rb +42 -0
- data/lib/qwirk/request_worker.rb +62 -0
- data/lib/qwirk/task.rb +177 -0
- data/lib/qwirk/task.rb.sav +194 -0
- data/lib/qwirk/version.rb +3 -0
- data/lib/qwirk/worker.rb +222 -0
- data/lib/qwirk/worker_config.rb +187 -0
- data/lib/rails/generators/qwirk/qwirk_generator.rb +82 -0
- data/lib/rails/generators/qwirk/templates/initializer.rb +6 -0
- data/lib/rails/generators/qwirk/templates/migration.rb +9 -0
- data/lib/rails/generators/qwirk/templates/schema.rb +28 -0
- data/lib/rails/railties/tasks.rake +8 -0
- data/lib/tasks/qwirk_tasks.rake +4 -0
- data/test/base_test.rb +248 -0
- data/test/database.yml +14 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +45 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +22 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +26 -0
- data/test/dummy/config/environments/production.rb +49 -0
- data/test/dummy/config/environments/test.rb +35 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/log/production.log +0 -0
- data/test/dummy/log/server.log +0 -0
- data/test/dummy/log/test.log +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/javascripts/application.js +2 -0
- data/test/dummy/public/javascripts/controls.js +965 -0
- data/test/dummy/public/javascripts/dragdrop.js +974 -0
- data/test/dummy/public/javascripts/effects.js +1123 -0
- data/test/dummy/public/javascripts/prototype.js +6001 -0
- data/test/dummy/public/javascripts/rails.js +191 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +7 -0
- data/test/jms.yml +9 -0
- data/test/jms_fail_test.rb +149 -0
- data/test/jms_requestor_block_test.rb +278 -0
- data/test/jms_requestor_test.rb +238 -0
- data/test/jms_test.rb +287 -0
- data/test/marshal_strategy_test.rb +62 -0
- data/test/support/integration_case.rb +5 -0
- data/test/test_helper.rb +7 -0
- data/test/test_helper.rbold +22 -0
- data/test/test_helper_active_record.rb +61 -0
- data/test/unit/qwirk/batch/acquire_file_strategy_test.rb +101 -0
- data/test/unit/qwirk/batch/active_record/batch_job_test.rb +35 -0
- data/test/unit/qwirk/batch/parse_file_strategy_test.rb +49 -0
- metadata +366 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
require 'qwirk'
|
|
2
|
+
require 'shoulda'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'erb'
|
|
6
|
+
|
|
7
|
+
# NOTE: This test requires a running ActiveMQ server
|
|
8
|
+
|
|
9
|
+
module HashTest
|
|
10
|
+
def self.create_obj(i)
|
|
11
|
+
{
|
|
12
|
+
'foo' => 1,
|
|
13
|
+
'bar' => {
|
|
14
|
+
'message' => i,
|
|
15
|
+
'dummy' => "Message #{i}"
|
|
16
|
+
},
|
|
17
|
+
# Only YAML will maintain symbols
|
|
18
|
+
:zulu => :rugger
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.parse_obj(obj)
|
|
23
|
+
obj['answer']
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.request(obj)
|
|
27
|
+
{
|
|
28
|
+
'answer' => obj['bar']['message']
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module RubyTest
|
|
34
|
+
|
|
35
|
+
class MyClass
|
|
36
|
+
attr_reader :i
|
|
37
|
+
def initialize(i)
|
|
38
|
+
@i = i
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.create_obj(i)
|
|
43
|
+
MyClass.new(i)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.parse_obj(obj)
|
|
47
|
+
obj.i-10
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.request(obj)
|
|
51
|
+
return MyClass.new(obj.i+10)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
module StringTest
|
|
56
|
+
def self.create_obj(i)
|
|
57
|
+
"Message #{i}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.parse_obj(obj)
|
|
61
|
+
if obj =~ /^Returning (\d+)$/
|
|
62
|
+
$1.to_i
|
|
63
|
+
else
|
|
64
|
+
raise "Unknown message: #{obj}"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.request(str)
|
|
69
|
+
if str =~ /^Message (\d+)$/
|
|
70
|
+
"Returning #{$1}"
|
|
71
|
+
else
|
|
72
|
+
raise "Unknown message: #{str}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class DefaultWorker
|
|
78
|
+
include Qwirk::QueueAdapter::JMS::RequestWorker
|
|
79
|
+
response :marshal => :yaml
|
|
80
|
+
|
|
81
|
+
def request(obj)
|
|
82
|
+
options[:tester].request(obj)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class SleepWorker
|
|
87
|
+
include Qwirk::QueueAdapter::JMS::RequestWorker
|
|
88
|
+
response :marshal => :string
|
|
89
|
+
|
|
90
|
+
def request(i)
|
|
91
|
+
sleep i.to_i
|
|
92
|
+
return i
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class JMSRequestorTest < Test::Unit::TestCase
|
|
97
|
+
|
|
98
|
+
@@server = JMX.simple_server
|
|
99
|
+
@@client = JMX.connect
|
|
100
|
+
|
|
101
|
+
context 'jms request' do
|
|
102
|
+
setup do
|
|
103
|
+
config = YAML.load(ERB.new(File.read(File.join(File.dirname(__FILE__), 'jms.yml'))).result(binding))
|
|
104
|
+
Qwirk::QueueAdapter::JMS::Connection.init(config)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
teardown do
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
:bson => HashTest,
|
|
112
|
+
:json => HashTest,
|
|
113
|
+
:ruby => RubyTest,
|
|
114
|
+
:string => StringTest,
|
|
115
|
+
:yaml => HashTest
|
|
116
|
+
}.each do |marshal, tester|
|
|
117
|
+
|
|
118
|
+
context "marshaling with #{marshal}" do
|
|
119
|
+
setup do
|
|
120
|
+
@domain = "Uniquize_#{marshal}"
|
|
121
|
+
@manager = Qwirk::Manager.new(:domain => @domain)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
teardown do
|
|
125
|
+
if @manager
|
|
126
|
+
@manager.stop
|
|
127
|
+
@manager.join
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
should "reply correctly with multiple threads" do
|
|
132
|
+
DefaultWorker.response(:marshal => marshal, :time_to_live => 10000)
|
|
133
|
+
@manager.add(DefaultWorker, 10, :tester => tester)
|
|
134
|
+
|
|
135
|
+
sleep 1
|
|
136
|
+
|
|
137
|
+
publisher = Qwirk::QueueAdapter::JMS::Publisher.new(:queue_name => 'Default', :marshal => marshal, :response_time_to_live => 10000)
|
|
138
|
+
threads = []
|
|
139
|
+
start = Time.now
|
|
140
|
+
(0..9).each do |i|
|
|
141
|
+
threads << Thread.new(i) do |i|
|
|
142
|
+
start = i*10
|
|
143
|
+
range = start..(start+9)
|
|
144
|
+
range.each do |x|
|
|
145
|
+
obj = tester.create_obj(x)
|
|
146
|
+
handle = publisher.publish(obj)
|
|
147
|
+
reply_obj = handle.read_response(2)
|
|
148
|
+
val = tester.parse_obj(reply_obj)
|
|
149
|
+
assert x == val, "#{x} does not equal #{val}"
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
threads.each {|t| t.join}
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context 'timed requesting' do
|
|
159
|
+
setup do
|
|
160
|
+
@domain = "TimedQwirk"
|
|
161
|
+
@manager = Qwirk::Manager.new(:domain => @domain)
|
|
162
|
+
@manager.add(SleepWorker, 10)
|
|
163
|
+
sleep 1
|
|
164
|
+
@producer = Qwirk::QueueAdapter::JMS::Publisher.new(:queue_name => 'Sleep', :marshal => :string, :response_time_to_live => 10000)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
teardown do
|
|
168
|
+
if @manager
|
|
169
|
+
@manager.stop
|
|
170
|
+
@manager.join
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
should "work correctly if request is complete before the timeout" do
|
|
175
|
+
[[1,0,2,0.8,1.2], [2,1,3,1.8,2.2], [1,2,3,0.8,1.2], [3,1,2,2.8,3.2]].each do |info|
|
|
176
|
+
work_sleep_time, publish_sleep_time, timeout_time, min_time, max_time = info
|
|
177
|
+
threads = []
|
|
178
|
+
start_time = Time.now
|
|
179
|
+
(0..9).each do |i|
|
|
180
|
+
threads << Thread.new(i) do |i|
|
|
181
|
+
handle = @producer.publish(work_sleep_time)
|
|
182
|
+
sleep publish_sleep_time
|
|
183
|
+
if work_sleep_time < timeout_time
|
|
184
|
+
response = handle.read_response(timeout_time).to_i
|
|
185
|
+
assert work_sleep_time == response, "#{work_sleep_time} does not equal #{response}"
|
|
186
|
+
else
|
|
187
|
+
assert handle.read_response(timeout_time).nil?
|
|
188
|
+
actual_time = Time.now - start_time
|
|
189
|
+
assert timeout_time-0.1 < actual_time, "Bad timeout #{actual_time}"
|
|
190
|
+
assert timeout_time+0.3 > actual_time, "Bad timeout #{actual_time}"
|
|
191
|
+
|
|
192
|
+
# Give the requests time to complete
|
|
193
|
+
sleep work_sleep_time - timeout_time + 1
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
threads.each {|t| t.join}
|
|
198
|
+
total_time = Time.now - start_time
|
|
199
|
+
bean = @@client[Qwirk.supervisor_mbean_object_name(@domain, 'Sleep')]
|
|
200
|
+
bean_avg = bean.average_response_time
|
|
201
|
+
bean_min = bean.min_response_time
|
|
202
|
+
bean_max = bean.max_response_time
|
|
203
|
+
puts "total=#{total_time} avg=#{bean_avg} min=#{bean_min} max=#{bean_max}"
|
|
204
|
+
all_times = [bean_avg, bean_min, bean_max]
|
|
205
|
+
all_times << total_time if work_sleep_time > publish_sleep_time && work_sleep_time < timeout_time
|
|
206
|
+
all_times.each do |time_val|
|
|
207
|
+
assert min_time < time_val, "#{time_val} is not between #{min_time} and #{max_time}"
|
|
208
|
+
assert max_time > time_val, "#{time_val} is not between #{min_time} and #{max_time}"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
context 'dummy requesting' do
|
|
215
|
+
setup do
|
|
216
|
+
@tester = RubyTest
|
|
217
|
+
workers = [
|
|
218
|
+
DefaultWorker.new(:tester => @tester)
|
|
219
|
+
]
|
|
220
|
+
Qwirk::QueueAdapter::JMS::Publisher.setup_dummy_publishing(workers)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
teardown do
|
|
224
|
+
Qwirk::QueueAdapter::JMS::Publisher.clear_dummy_publishing
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
should "directly call applicable workers" do
|
|
228
|
+
x=9999
|
|
229
|
+
obj = @tester.create_obj(x)
|
|
230
|
+
publisher = Qwirk::QueueAdapter::JMS::Publisher.new(:queue_name => 'Default', :marshal => :ruby, :response => true)
|
|
231
|
+
handle = publisher.publish(obj)
|
|
232
|
+
reply_obj = handle.read_response(2)
|
|
233
|
+
val = @tester.parse_obj(reply_obj)
|
|
234
|
+
assert x == val, "#{x} does not equal #{val}"
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
data/test/jms_test.rb
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
require 'qwirk'
|
|
2
|
+
require 'shoulda'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'erb'
|
|
6
|
+
|
|
7
|
+
# NOTE: This test requires a running ActiveMQ server
|
|
8
|
+
|
|
9
|
+
module WorkerHelper
|
|
10
|
+
@@workers = {}
|
|
11
|
+
@@mutex = Mutex.new
|
|
12
|
+
def initialize(opts={})
|
|
13
|
+
super
|
|
14
|
+
@tester = opts[:tester]
|
|
15
|
+
@@mutex.synchronize do
|
|
16
|
+
@@workers[self.name] ||= []
|
|
17
|
+
@@workers[self.name] << self
|
|
18
|
+
end
|
|
19
|
+
@hash = Hash.new(0)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def perform(obj)
|
|
23
|
+
add_message(@tester.translate(obj))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.workers(names)
|
|
27
|
+
workers = []
|
|
28
|
+
names.each {|name| workers += @@workers[name]}
|
|
29
|
+
workers
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.reset_workers
|
|
33
|
+
@@workers = {}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def add_message(i)
|
|
37
|
+
@hash[i] += 1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def call_count
|
|
41
|
+
puts "hash=#{@hash.inspect}"
|
|
42
|
+
@hash.values.reduce(:+)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def messages
|
|
46
|
+
@hash.keys
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module HashTest
|
|
51
|
+
def self.create_obj(i)
|
|
52
|
+
{
|
|
53
|
+
'foo' => 1,
|
|
54
|
+
'bar' => {
|
|
55
|
+
'message' => i,
|
|
56
|
+
'dummy' => "Message #{i}"
|
|
57
|
+
},
|
|
58
|
+
# Only YAML will maintain symbols
|
|
59
|
+
:zulu => :rugger
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.translate(obj)
|
|
64
|
+
obj['bar']['message']
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
module RubyTest
|
|
69
|
+
class MyClass
|
|
70
|
+
attr_reader :i
|
|
71
|
+
def initialize(i)
|
|
72
|
+
@i = i
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.create_obj(i)
|
|
77
|
+
MyClass.new(i)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.translate(obj)
|
|
81
|
+
obj.i
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
module StringTest
|
|
86
|
+
def self.create_obj(i)
|
|
87
|
+
"Message #{i}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.translate(str)
|
|
91
|
+
if str =~ /^Message (\d+)$/
|
|
92
|
+
$1.to_i
|
|
93
|
+
else
|
|
94
|
+
raise "Unknown message: #{str}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class DefaultWorker
|
|
100
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
101
|
+
include WorkerHelper
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
module Dummy
|
|
105
|
+
class DefaultWorker
|
|
106
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
107
|
+
include WorkerHelper
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class SpecifiedQueueWorker
|
|
112
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
113
|
+
queue 'MyQueueName'
|
|
114
|
+
include WorkerHelper
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
class SpecifiedQueue2Worker
|
|
118
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
119
|
+
queue 'MyQueueName'
|
|
120
|
+
include WorkerHelper
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class SpecifiedTopicWorker
|
|
124
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
125
|
+
virtual_topic 'MyTopicName'
|
|
126
|
+
include WorkerHelper
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class SpecifiedTopic2Worker
|
|
130
|
+
include Qwirk::QueueAdapter::JMS::Worker
|
|
131
|
+
virtual_topic 'MyTopicName'
|
|
132
|
+
include WorkerHelper
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class JMSTest < Test::Unit::TestCase
|
|
136
|
+
|
|
137
|
+
@@server = JMX.simple_server
|
|
138
|
+
@@client = JMX.connect
|
|
139
|
+
|
|
140
|
+
def publish(marshal, tester, range, options)
|
|
141
|
+
publisher = Qwirk::QueueAdapter::JMS::Publisher.new(options.merge(:marshal => marshal))
|
|
142
|
+
puts "Publishing #{range} to #{publisher} via #{marshal}"
|
|
143
|
+
range.each do |i|
|
|
144
|
+
obj = tester.create_obj(i)
|
|
145
|
+
publisher.publish(obj)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def assert_worker(domain, names, worker_count, range, min, max, instance_count)
|
|
150
|
+
puts "Checking #{names.inspect}"
|
|
151
|
+
names = [names] unless names.kind_of?(Array)
|
|
152
|
+
workers = WorkerHelper.workers(names)
|
|
153
|
+
|
|
154
|
+
assert_equal worker_count, workers.size
|
|
155
|
+
all_messages = []
|
|
156
|
+
workers.each do |worker|
|
|
157
|
+
msg_count = worker.call_count
|
|
158
|
+
assert msg_count
|
|
159
|
+
assert msg_count >= min, "#{msg_count} is not between #{min} and #{max}"
|
|
160
|
+
assert msg_count <= max, "#{msg_count} is not between #{min} and #{max}"
|
|
161
|
+
# Make sure no duplicate messages
|
|
162
|
+
assert msg_count == worker.messages.size, "#{msg_count} is not == #{worker.messages.size}"
|
|
163
|
+
all_messages.concat(worker.messages)
|
|
164
|
+
end
|
|
165
|
+
all_messages.sort!
|
|
166
|
+
assert_equal all_messages, (range.to_a*instance_count).sort
|
|
167
|
+
|
|
168
|
+
if domain
|
|
169
|
+
total_count = 0
|
|
170
|
+
names.each do |name|
|
|
171
|
+
bean = @@client[Qwirk.supervisor_mbean_object_name(domain, name)]
|
|
172
|
+
bean.message_counts.each do |msg_count|
|
|
173
|
+
total_count += msg_count
|
|
174
|
+
assert msg_count >= min, "#{msg_count} is not between #{min} and #{max}"
|
|
175
|
+
assert msg_count <= max, "#{msg_count} is not between #{min} and #{max}"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
assert_equal all_messages.size, total_count
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
context 'jms' do
|
|
183
|
+
setup do
|
|
184
|
+
config = YAML.load(ERB.new(File.read(File.join(File.dirname(__FILE__), 'jms.yml'))).result(binding))
|
|
185
|
+
Qwirk::QueueAdapter::JMS::Connection.init(config)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
teardown do
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
{
|
|
192
|
+
:bson => HashTest,
|
|
193
|
+
:json => HashTest,
|
|
194
|
+
:ruby => RubyTest,
|
|
195
|
+
:string => StringTest,
|
|
196
|
+
:yaml => HashTest
|
|
197
|
+
}.each do |marshal, tester|
|
|
198
|
+
|
|
199
|
+
context "marshaling with #{marshal}" do
|
|
200
|
+
setup do
|
|
201
|
+
@domain = "Uniquize_#{marshal}"
|
|
202
|
+
@manager = Qwirk::Manager.new(:domain => @domain)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
teardown do
|
|
206
|
+
if @manager
|
|
207
|
+
@manager.stop
|
|
208
|
+
@manager.join
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
should "operate on queues and topics" do
|
|
213
|
+
WorkerHelper.reset_workers
|
|
214
|
+
@manager.add(DefaultWorker, 3, :tester => tester)
|
|
215
|
+
@manager.add(DefaultWorker, 2, :name => 'DefaultClone', :tester => tester)
|
|
216
|
+
@manager.add(Dummy::DefaultWorker, 4, :tester => tester)
|
|
217
|
+
@manager.add(SpecifiedQueueWorker, 3, :tester => tester)
|
|
218
|
+
@manager.add(SpecifiedQueueWorker, 2, :name => 'SpecifiedQueueClone', :tester => tester)
|
|
219
|
+
@manager.add(SpecifiedQueue2Worker, 2, :tester => tester)
|
|
220
|
+
@manager.add(SpecifiedTopicWorker, 3, :tester => tester)
|
|
221
|
+
@manager.add(SpecifiedTopicWorker, 2, :name => 'SpecifiedTopicClone', :tester => tester)
|
|
222
|
+
@manager.add(SpecifiedTopic2Worker, 2, :tester => tester)
|
|
223
|
+
|
|
224
|
+
sleep 1
|
|
225
|
+
|
|
226
|
+
publish(marshal, tester, 100..199, :queue_name => 'Default')
|
|
227
|
+
publish(marshal, tester, 200..299, :queue_name => 'DefaultClone')
|
|
228
|
+
publish(marshal, tester, 300..399, :queue_name => 'Dummy_Default')
|
|
229
|
+
publish(marshal, tester, 400..599, :queue_name => 'MyQueueName')
|
|
230
|
+
publish(marshal, tester, 600..699, :virtual_topic_name => 'MyTopicName')
|
|
231
|
+
|
|
232
|
+
# Let the workers do their thing
|
|
233
|
+
sleep 5
|
|
234
|
+
|
|
235
|
+
# DefaultWorker should have 5 instances running with each worker handling between 10-30 messages in the range 100.199
|
|
236
|
+
assert_worker(@domain, 'Default', 3, 100..199, 30, 36, 1)
|
|
237
|
+
assert_worker(@domain, 'DefaultClone', 2, 200..299, 45, 55, 1)
|
|
238
|
+
assert_worker(@domain, 'Dummy_Default', 4, 300..399, 20, 30, 1)
|
|
239
|
+
assert_worker(@domain, ['SpecifiedQueue', 'SpecifiedQueueClone', 'SpecifiedQueue2'], 7, 400..599, 20, 40, 1)
|
|
240
|
+
assert_worker(@domain, ['SpecifiedTopic', 'SpecifiedTopicClone'], 5, 600..699, 30, 60, 2)
|
|
241
|
+
assert_worker(@domain, 'SpecifiedTopic2', 2, 600..699, 35, 65, 1)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
context 'dummy publishing' do
|
|
247
|
+
setup do
|
|
248
|
+
WorkerHelper.reset_workers
|
|
249
|
+
workers = [
|
|
250
|
+
DefaultWorker.new(:tester => RubyTest),
|
|
251
|
+
DefaultWorker.new(:tester => RubyTest, :name => 'DefaultClone'),
|
|
252
|
+
Dummy::DefaultWorker.new(:tester => RubyTest),
|
|
253
|
+
SpecifiedQueueWorker.new(:tester => RubyTest),
|
|
254
|
+
SpecifiedQueueWorker.new(:tester => RubyTest, :name => 'SpecifiedQueueClone'),
|
|
255
|
+
SpecifiedQueue2Worker.new(:tester => RubyTest),
|
|
256
|
+
SpecifiedTopicWorker.new(:tester => RubyTest),
|
|
257
|
+
SpecifiedTopicWorker.new(:tester => RubyTest, :name => 'SpecifiedTopicClone'),
|
|
258
|
+
SpecifiedTopic2Worker.new(:tester => RubyTest),
|
|
259
|
+
]
|
|
260
|
+
Qwirk::QueueAdapter::JMS::Publisher.setup_dummy_publishing(workers)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
teardown do
|
|
264
|
+
Qwirk::QueueAdapter::JMS::Publisher.clear_dummy_publishing
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
should "directly call applicable workers" do
|
|
268
|
+
publish(:ruby, RubyTest, 100..199, :queue_name => 'Default')
|
|
269
|
+
publish(:ruby, RubyTest, 200..299, :queue_name => 'DefaultClone')
|
|
270
|
+
publish(:ruby, RubyTest, 300..399, :queue_name => 'Dummy_Default')
|
|
271
|
+
publish(:ruby, RubyTest, 400..599, :queue_name => 'MyQueueName')
|
|
272
|
+
publish(:ruby, RubyTest, 600..699, :virtual_topic_name => 'MyTopicName')
|
|
273
|
+
|
|
274
|
+
# The single instance of each class will be called so everyone will have all messages.
|
|
275
|
+
assert_worker(nil, 'Default', 1, 100..199, 100, 100, 1)
|
|
276
|
+
assert_worker(nil, 'DefaultClone', 1, 200..299, 100, 100, 1)
|
|
277
|
+
assert_worker(nil, 'Dummy_Default', 1, 300..399, 100, 100, 1)
|
|
278
|
+
assert_worker(nil, 'SpecifiedQueue', 1, 400..599, 200, 200, 1)
|
|
279
|
+
assert_worker(nil, 'SpecifiedQueueClone', 1, 400..599, 200, 200, 1)
|
|
280
|
+
assert_worker(nil, 'SpecifiedQueue2', 1, 400..599, 200, 200, 1)
|
|
281
|
+
assert_worker(nil, 'SpecifiedTopic', 1, 600..699, 100, 100, 1)
|
|
282
|
+
assert_worker(nil, 'SpecifiedTopicClone', 1, 600..699, 100, 100, 1)
|
|
283
|
+
assert_worker(nil, 'SpecifiedTopic2', 1, 600..699, 100, 100, 1)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|