qs 0.6.1 → 0.7.0
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.
- checksums.yaml +4 -4
- data/bench/config.qs +1 -0
- data/bench/dispatcher.qs +1 -0
- data/bench/report.rb +2 -0
- data/bench/setup.rb +1 -1
- data/lib/qs.rb +95 -41
- data/lib/qs/client.rb +5 -5
- data/lib/qs/config_file.rb +1 -1
- data/lib/qs/daemon.rb +133 -99
- data/lib/qs/daemon_data.rb +22 -21
- data/lib/qs/message_handler.rb +1 -0
- data/lib/qs/process.rb +20 -10
- data/lib/qs/qs_runner.rb +13 -21
- data/lib/qs/runner.rb +4 -0
- data/lib/qs/test_runner.rb +12 -2
- data/lib/qs/version.rb +1 -1
- data/qs.gemspec +6 -7
- data/test/helper.rb +11 -0
- data/test/support/app_queue.rb +104 -0
- data/test/support/client_spy.rb +2 -2
- data/test/support/config.qs +9 -2
- data/test/support/factory.rb +1 -1
- data/test/system/daemon_tests.rb +117 -36
- data/test/system/queue_tests.rb +1 -1
- data/test/unit/cli_tests.rb +2 -2
- data/test/unit/client_tests.rb +11 -11
- data/test/unit/config_file_tests.rb +2 -2
- data/test/unit/daemon_data_tests.rb +53 -48
- data/test/unit/daemon_tests.rb +221 -214
- data/test/unit/message_handler_tests.rb +14 -1
- data/test/unit/process_tests.rb +50 -25
- data/test/unit/qs_runner_tests.rb +120 -34
- data/test/unit/qs_tests.rb +180 -75
- data/test/unit/queue_tests.rb +5 -5
- data/test/unit/runner_tests.rb +9 -1
- data/test/unit/test_runner_tests.rb +12 -1
- metadata +13 -23
- data/test/support/app_daemon.rb +0 -143
data/test/system/queue_tests.rb
CHANGED
data/test/unit/cli_tests.rb
CHANGED
@@ -123,8 +123,8 @@ class Qs::CLI
|
|
123
123
|
end
|
124
124
|
|
125
125
|
should "output the error with the help" do
|
126
|
-
|
127
|
-
assert_includes
|
126
|
+
exp = "#{@command.inspect} is not a valid command"
|
127
|
+
assert_includes exp, @kernel_spy.output
|
128
128
|
assert_includes "Usage: qs", @kernel_spy.output
|
129
129
|
end
|
130
130
|
|
data/test/unit/client_tests.rb
CHANGED
@@ -15,7 +15,7 @@ module Qs::Client
|
|
15
15
|
ENV['QS_TEST_MODE'] = 'yes'
|
16
16
|
Qs.init
|
17
17
|
|
18
|
-
@
|
18
|
+
@redis_connect_hash = Qs.redis_connect_hash
|
19
19
|
@queue = Qs::Queue.new{ name Factory.string }
|
20
20
|
@job_name = Factory.string
|
21
21
|
@job_params = { Factory.string => Factory.string }
|
@@ -30,12 +30,12 @@ module Qs::Client
|
|
30
30
|
|
31
31
|
should "return a qs client using `new`" do
|
32
32
|
ENV.delete('QS_TEST_MODE')
|
33
|
-
client = subject.new(@
|
33
|
+
client = subject.new(@redis_connect_hash)
|
34
34
|
assert_instance_of Qs::QsClient, client
|
35
35
|
end
|
36
36
|
|
37
37
|
should "return a test client using `new` in test mode" do
|
38
|
-
client = subject.new(@
|
38
|
+
client = subject.new(@redis_connect_hash)
|
39
39
|
assert_instance_of Qs::TestClient, client
|
40
40
|
end
|
41
41
|
|
@@ -43,11 +43,11 @@ module Qs::Client
|
|
43
43
|
|
44
44
|
class MixinTests < UnitTests
|
45
45
|
setup do
|
46
|
-
@client = FakeClient.new(@
|
46
|
+
@client = FakeClient.new(@redis_connect_hash)
|
47
47
|
end
|
48
48
|
subject{ @client }
|
49
49
|
|
50
|
-
should have_readers :
|
50
|
+
should have_readers :redis_connect_hash, :redis
|
51
51
|
should have_imeths :enqueue, :publish, :publish_as, :push
|
52
52
|
should have_imeths :block_dequeue
|
53
53
|
should have_imeths :append, :prepend
|
@@ -56,7 +56,7 @@ module Qs::Client
|
|
56
56
|
should have_imeths :event_subscribers
|
57
57
|
|
58
58
|
should "know its redis config" do
|
59
|
-
assert_equal @
|
59
|
+
assert_equal @redis_connect_hash, subject.redis_connect_hash
|
60
60
|
end
|
61
61
|
|
62
62
|
should "not have a redis connection" do
|
@@ -122,7 +122,7 @@ module Qs::Client
|
|
122
122
|
|
123
123
|
class RedisCallTests < MixinTests
|
124
124
|
setup do
|
125
|
-
@connection_spy = HellaRedis::ConnectionSpy.new(@client.
|
125
|
+
@connection_spy = HellaRedis::ConnectionSpy.new(@client.redis_connect_hash)
|
126
126
|
Assert.stub(@client, :redis){ @connection_spy }
|
127
127
|
|
128
128
|
@queue_redis_key = Factory.string
|
@@ -284,13 +284,13 @@ module Qs::Client
|
|
284
284
|
@connection_spy = HellaRedis::ConnectionSpy.new(*args)
|
285
285
|
end
|
286
286
|
|
287
|
-
@client = @client_class.new(@
|
287
|
+
@client = @client_class.new(@redis_connect_hash)
|
288
288
|
end
|
289
289
|
subject{ @client }
|
290
290
|
|
291
291
|
should "build a redis connection" do
|
292
292
|
assert_not_nil @connection_spy
|
293
|
-
assert_equal @connection_spy.config, subject.
|
293
|
+
assert_equal @connection_spy.config, subject.redis_connect_hash
|
294
294
|
assert_equal @connection_spy, subject.redis
|
295
295
|
end
|
296
296
|
|
@@ -338,7 +338,7 @@ module Qs::Client
|
|
338
338
|
@serialized_job = nil
|
339
339
|
Assert.stub(Qs::Payload, :serialize){ |job| @serialized_job = job }
|
340
340
|
|
341
|
-
@client = @client_class.new(@
|
341
|
+
@client = @client_class.new(@redis_connect_hash)
|
342
342
|
end
|
343
343
|
subject{ @client }
|
344
344
|
|
@@ -347,7 +347,7 @@ module Qs::Client
|
|
347
347
|
|
348
348
|
should "build a redis connection spy" do
|
349
349
|
assert_instance_of HellaRedis::ConnectionSpy, subject.redis
|
350
|
-
assert_equal @
|
350
|
+
assert_equal @redis_connect_hash, subject.redis.config
|
351
351
|
end
|
352
352
|
|
353
353
|
should "default its pushed items" do
|
@@ -15,7 +15,7 @@ class Qs::ConfigFile
|
|
15
15
|
should have_imeths :run
|
16
16
|
|
17
17
|
should "know its daemon" do
|
18
|
-
assert_instance_of
|
18
|
+
assert_instance_of ConfigFileTestDaemon, subject.daemon
|
19
19
|
end
|
20
20
|
|
21
21
|
should "define constants in the file at the top-level binding" do
|
@@ -35,7 +35,7 @@ class Qs::ConfigFile
|
|
35
35
|
assert_nothing_raised do
|
36
36
|
config_file = Qs::ConfigFile.new(file_path)
|
37
37
|
end
|
38
|
-
assert_instance_of
|
38
|
+
assert_instance_of ConfigFileTestDaemon, config_file.daemon
|
39
39
|
end
|
40
40
|
|
41
41
|
should "raise no config file error when the file doesn't exist" do
|
@@ -13,23 +13,27 @@ class Qs::DaemonData
|
|
13
13
|
ENV['QS_PROCESS_LABEL'] = Factory.string
|
14
14
|
|
15
15
|
@current_env_debug = ENV['QS_DEBUG']
|
16
|
-
ENV
|
16
|
+
ENV.delete('QS_DEBUG')
|
17
|
+
|
18
|
+
@queues = Factory.integer(3).times.map do
|
19
|
+
Qs::Queue.new{ name Factory.string }
|
20
|
+
end
|
17
21
|
|
18
|
-
@routes =
|
22
|
+
@routes = Factory.integer(3).times.map do
|
19
23
|
Qs::Route.new(Factory.string, TestHandler.to_s).tap(&:validate!)
|
20
24
|
end
|
21
25
|
|
22
26
|
@config_hash = {
|
23
27
|
:name => Factory.string,
|
24
28
|
:pid_file => Factory.file_path,
|
29
|
+
:shutdown_timeout => Factory.integer,
|
25
30
|
:worker_class => Class.new,
|
26
31
|
:worker_params => { Factory.string => Factory.string },
|
27
32
|
:num_workers => Factory.integer,
|
33
|
+
:error_procs => Factory.integer(3).times.map{ proc{} },
|
28
34
|
:logger => Factory.string,
|
35
|
+
:queues => @queues,
|
29
36
|
:verbose_logging => Factory.boolean,
|
30
|
-
:shutdown_timeout => Factory.integer,
|
31
|
-
:error_procs => [ proc{ Factory.string } ],
|
32
|
-
:queue_redis_keys => Factory.integer(3).times.map{ Factory.string },
|
33
37
|
:routes => @routes
|
34
38
|
}
|
35
39
|
@daemon_data = Qs::DaemonData.new(@config_hash)
|
@@ -40,31 +44,40 @@ class Qs::DaemonData
|
|
40
44
|
end
|
41
45
|
subject{ @daemon_data }
|
42
46
|
|
43
|
-
should have_readers :name, :
|
47
|
+
should have_readers :name, :pid_file, :shutdown_timeout
|
44
48
|
should have_readers :worker_class, :worker_params, :num_workers
|
45
|
-
should have_readers :
|
46
|
-
should have_readers :
|
47
|
-
should have_readers :
|
49
|
+
should have_readers :error_procs, :logger, :queue_redis_keys
|
50
|
+
should have_readers :verbose_logging
|
51
|
+
should have_readers :debug, :dwp_logger, :routes, :process_label
|
48
52
|
should have_imeths :route_for
|
49
53
|
|
50
|
-
should "know its
|
54
|
+
should "know its attrs" do
|
51
55
|
h = @config_hash
|
52
|
-
assert_equal h[:name],
|
53
|
-
assert_equal h[:pid_file],
|
54
|
-
|
55
|
-
assert_equal h[:worker_params], subject.worker_params
|
56
|
-
assert_equal h[:num_workers], subject.num_workers
|
57
|
-
assert_equal h[:logger], subject.logger
|
58
|
-
assert_equal h[:verbose_logging], subject.verbose_logging
|
56
|
+
assert_equal h[:name], subject.name
|
57
|
+
assert_equal h[:pid_file], subject.pid_file
|
58
|
+
|
59
59
|
assert_equal h[:shutdown_timeout], subject.shutdown_timeout
|
60
|
-
|
61
|
-
assert_equal h[:
|
60
|
+
|
61
|
+
assert_equal h[:worker_class], subject.worker_class
|
62
|
+
assert_equal h[:worker_params], subject.worker_params
|
63
|
+
assert_equal h[:num_workers], subject.num_workers
|
64
|
+
assert_equal h[:error_procs], subject.error_procs
|
65
|
+
assert_equal h[:logger], subject.logger
|
66
|
+
|
67
|
+
exp = @queues.map(&:redis_key)
|
68
|
+
assert_equal exp, subject.queue_redis_keys
|
69
|
+
|
70
|
+
assert_equal h[:verbose_logging], subject.verbose_logging
|
71
|
+
|
72
|
+
assert_false subject.debug
|
73
|
+
assert_nil subject.dwp_logger
|
74
|
+
|
75
|
+
exp = @routes.inject({}){ |h, r| h.merge(r.id => r) }
|
76
|
+
assert_equal exp, subject.routes
|
62
77
|
end
|
63
78
|
|
64
|
-
should "
|
65
|
-
ENV['QS_PROCESS_LABEL']
|
66
|
-
daemon_data = Qs::DaemonData.new(@config_hash)
|
67
|
-
assert_equal ENV['QS_PROCESS_LABEL'], daemon_data.process_label
|
79
|
+
should "know its process label" do
|
80
|
+
assert_equal ENV['QS_PROCESS_LABEL'], subject.process_label
|
68
81
|
|
69
82
|
ENV['QS_PROCESS_LABEL'] = ""
|
70
83
|
daemon_data = Qs::DaemonData.new(@config_hash)
|
@@ -75,32 +88,16 @@ class Qs::DaemonData
|
|
75
88
|
assert_equal @config_hash[:name], daemon_data.process_label
|
76
89
|
end
|
77
90
|
|
78
|
-
should "use debug env var if set" do
|
91
|
+
should "use the debug env var if set" do
|
79
92
|
ENV['QS_DEBUG'] = Factory.string
|
80
93
|
daemon_data = Qs::DaemonData.new(@config_hash)
|
81
94
|
assert_true daemon_data.debug
|
82
|
-
assert_equal
|
83
|
-
|
84
|
-
ENV['QS_DEBUG'] = ""
|
85
|
-
daemon_data = Qs::DaemonData.new(@config_hash)
|
86
|
-
assert_false daemon_data.debug
|
87
|
-
assert_nil daemon_data.dwp_logger
|
88
|
-
|
89
|
-
ENV.delete('QS_DEBUG')
|
90
|
-
daemon_data = Qs::DaemonData.new(@config_hash)
|
91
|
-
assert_false daemon_data.debug
|
92
|
-
assert_nil daemon_data.dwp_logger
|
95
|
+
assert_equal daemon_data.logger, daemon_data.dwp_logger
|
93
96
|
end
|
94
97
|
|
95
|
-
should "
|
96
|
-
|
97
|
-
assert_equal
|
98
|
-
end
|
99
|
-
|
100
|
-
should "allow looking up a route using `route_for`" do
|
101
|
-
exp_route = @routes.choice
|
102
|
-
route = subject.route_for(exp_route.id)
|
103
|
-
assert_equal exp_route, route
|
98
|
+
should "look up a route using `route_for`" do
|
99
|
+
exp_route = @routes.sample
|
100
|
+
assert_equal exp_route, subject.route_for(exp_route.id)
|
104
101
|
end
|
105
102
|
|
106
103
|
should "raise a not found error using `route_for` with an invalid name" do
|
@@ -109,18 +106,26 @@ class Qs::DaemonData
|
|
109
106
|
end
|
110
107
|
end
|
111
108
|
|
112
|
-
should "default its
|
109
|
+
should "default its attrs when they aren't provided" do
|
113
110
|
daemon_data = Qs::DaemonData.new
|
114
111
|
assert_nil daemon_data.name
|
115
112
|
assert_nil daemon_data.pid_file
|
113
|
+
assert_nil daemon_data.shutdown_timeout
|
114
|
+
|
116
115
|
assert_nil daemon_data.worker_class
|
117
116
|
assert_equal({}, daemon_data.worker_params)
|
118
117
|
assert_nil daemon_data.num_workers
|
119
|
-
|
120
|
-
assert_false daemon_data.verbose_logging
|
121
|
-
assert_nil daemon_data.shutdown_timeout
|
118
|
+
|
122
119
|
assert_equal [], daemon_data.error_procs
|
120
|
+
|
121
|
+
assert_nil daemon_data.logger
|
123
122
|
assert_equal [], daemon_data.queue_redis_keys
|
123
|
+
|
124
|
+
assert_false daemon_data.verbose_logging
|
125
|
+
|
126
|
+
assert_false daemon_data.debug
|
127
|
+
assert_nil daemon_data.dwp_logger
|
128
|
+
|
124
129
|
assert_equal({}, daemon_data.routes)
|
125
130
|
end
|
126
131
|
|
data/test/unit/daemon_tests.rb
CHANGED
@@ -3,9 +3,9 @@ require 'qs/daemon'
|
|
3
3
|
|
4
4
|
require 'dat-worker-pool/worker_pool_spy'
|
5
5
|
require 'much-plugin'
|
6
|
-
require 'ns-options/assert_macros'
|
7
6
|
require 'thread'
|
8
7
|
require 'qs/client'
|
8
|
+
require 'qs/logger'
|
9
9
|
require 'qs/queue'
|
10
10
|
require 'qs/queue_item'
|
11
11
|
require 'test/support/client_spy'
|
@@ -19,110 +19,80 @@ module Qs::Daemon
|
|
19
19
|
end
|
20
20
|
subject{ @daemon_class }
|
21
21
|
|
22
|
-
should have_imeths :
|
23
|
-
should have_imeths :name, :pid_file
|
24
|
-
should have_imeths :worker_class, :worker_params
|
25
|
-
should have_imeths :
|
26
|
-
should have_imeths :
|
27
|
-
should have_imeths :
|
28
|
-
should have_imeths :init, :error, :queue, :queues
|
22
|
+
should have_imeths :config
|
23
|
+
should have_imeths :name, :pid_file, :shutdown_timeout
|
24
|
+
should have_imeths :worker_class, :worker_params, :num_workers, :workers
|
25
|
+
should have_imeths :init, :init_procs, :error, :error_procs
|
26
|
+
should have_imeths :logger, :queue, :queues
|
27
|
+
should have_imeths :verbose_logging
|
29
28
|
|
30
29
|
should "use much-plugin" do
|
31
30
|
assert_includes MuchPlugin, Qs::Daemon
|
32
31
|
end
|
33
32
|
|
34
|
-
should "
|
35
|
-
config = subject.
|
36
|
-
assert_instance_of Configuration, config
|
37
|
-
assert_same config, subject.configuration
|
38
|
-
end
|
33
|
+
should "allow setting its config values" do
|
34
|
+
config = subject.config
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
assert_equal new_name, subject.configuration.name
|
44
|
-
assert_equal new_name, subject.name
|
45
|
-
end
|
36
|
+
exp = Factory.string
|
37
|
+
subject.name exp
|
38
|
+
assert_equal exp, config.name
|
46
39
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
expected = Pathname.new(new_pid_file)
|
51
|
-
assert_equal expected, subject.configuration.pid_file
|
52
|
-
assert_equal expected, subject.pid_file
|
53
|
-
end
|
40
|
+
exp = Factory.file_path
|
41
|
+
subject.pid_file exp
|
42
|
+
assert_equal exp, config.pid_file
|
54
43
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
assert_equal new_worker_class, subject.configuration.worker_class
|
59
|
-
assert_equal new_worker_class, subject.worker_class
|
60
|
-
end
|
44
|
+
exp = Factory.integer
|
45
|
+
subject.shutdown_timeout exp
|
46
|
+
assert_equal exp, config.shutdown_timeout
|
61
47
|
|
62
|
-
|
63
|
-
|
64
|
-
subject.
|
65
|
-
assert_equal new_worker_params, subject.configuration.worker_params
|
66
|
-
assert_equal new_worker_params, subject.worker_params
|
67
|
-
end
|
48
|
+
exp = Class.new
|
49
|
+
subject.worker_class exp
|
50
|
+
assert_equal exp, subject.config.worker_class
|
68
51
|
|
69
|
-
|
70
|
-
|
71
|
-
subject.
|
72
|
-
assert_equal new_num_workers, subject.configuration.num_workers
|
73
|
-
assert_equal new_num_workers, subject.num_workers
|
74
|
-
end
|
52
|
+
exp = { Factory.string => Factory.string }
|
53
|
+
subject.worker_params exp
|
54
|
+
assert_equal exp, subject.config.worker_params
|
75
55
|
|
76
|
-
|
77
|
-
|
78
|
-
subject.
|
79
|
-
assert_equal
|
80
|
-
assert_equal new_workers, subject.workers
|
81
|
-
end
|
56
|
+
exp = Factory.integer
|
57
|
+
subject.num_workers(exp)
|
58
|
+
assert_equal exp, subject.config.num_workers
|
59
|
+
assert_equal exp, subject.workers
|
82
60
|
|
83
|
-
|
84
|
-
|
85
|
-
subject.
|
86
|
-
assert_equal
|
87
|
-
assert_equal
|
88
|
-
end
|
61
|
+
exp = proc{ Factory.string }
|
62
|
+
assert_equal 0, config.init_procs.size
|
63
|
+
subject.init(&exp)
|
64
|
+
assert_equal 1, config.init_procs.size
|
65
|
+
assert_equal exp, config.init_procs.first
|
89
66
|
|
90
|
-
|
91
|
-
|
92
|
-
subject.
|
93
|
-
assert_equal
|
94
|
-
assert_equal
|
95
|
-
end
|
67
|
+
exp = proc{ Factory.string }
|
68
|
+
assert_equal 0, config.error_procs.size
|
69
|
+
subject.error(&exp)
|
70
|
+
assert_equal 1, config.error_procs.size
|
71
|
+
assert_equal exp, config.error_procs.first
|
96
72
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
assert_equal new_shutdown_timeout, subject.configuration.shutdown_timeout
|
101
|
-
assert_equal new_shutdown_timeout, subject.shutdown_timeout
|
102
|
-
end
|
73
|
+
exp = Logger.new(STDOUT)
|
74
|
+
subject.logger exp
|
75
|
+
assert_equal exp, config.logger
|
103
76
|
|
104
|
-
|
105
|
-
|
106
|
-
subject.
|
107
|
-
assert_includes new_init_proc, subject.configuration.init_procs
|
108
|
-
end
|
77
|
+
exp = Factory.string
|
78
|
+
subject.queue(exp)
|
79
|
+
assert_equal [exp], subject.config.queues
|
109
80
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
assert_includes new_error_proc, subject.configuration.error_procs
|
81
|
+
exp = Factory.boolean
|
82
|
+
subject.verbose_logging exp
|
83
|
+
assert_equal exp, config.verbose_logging
|
114
84
|
end
|
115
85
|
|
116
|
-
should "
|
117
|
-
|
118
|
-
subject.
|
119
|
-
assert_includes new_queue, subject.configuration.queues
|
86
|
+
should "demeter its config values that aren't directly set" do
|
87
|
+
assert_equal subject.config.init_procs, subject.init_procs
|
88
|
+
assert_equal subject.config.error_procs, subject.error_procs
|
120
89
|
end
|
121
90
|
|
122
|
-
should "
|
123
|
-
|
124
|
-
|
125
|
-
|
91
|
+
should "know its queues" do
|
92
|
+
assert_equal [], subject.queues
|
93
|
+
exp = Factory.string
|
94
|
+
subject.queue(exp)
|
95
|
+
assert_equal [exp], subject.queues
|
126
96
|
end
|
127
97
|
|
128
98
|
end
|
@@ -134,10 +104,10 @@ module Qs::Daemon
|
|
134
104
|
|
135
105
|
@daemon_class.name Factory.string
|
136
106
|
@daemon_class.pid_file Factory.file_path
|
107
|
+
@daemon_class.shutdown_timeout Factory.integer
|
137
108
|
@daemon_class.worker_params(Factory.string => Factory.string)
|
138
|
-
@daemon_class.
|
109
|
+
@daemon_class.num_workers Factory.integer
|
139
110
|
@daemon_class.verbose_logging Factory.boolean
|
140
|
-
@daemon_class.shutdown_timeout Factory.integer
|
141
111
|
@daemon_class.error{ Factory.string }
|
142
112
|
|
143
113
|
@queue = Qs::Queue.new do
|
@@ -175,71 +145,65 @@ module Qs::Daemon
|
|
175
145
|
end
|
176
146
|
subject{ @daemon }
|
177
147
|
|
178
|
-
should have_readers :daemon_data, :
|
179
|
-
should have_readers :signals_redis_key, :queue_redis_keys
|
148
|
+
should have_readers :daemon_data, :signals_redis_key
|
180
149
|
should have_imeths :name, :process_label, :pid_file
|
150
|
+
should have_imeths :logger, :queue_redis_keys
|
181
151
|
should have_imeths :running?
|
182
152
|
should have_imeths :start, :stop, :halt
|
183
153
|
|
184
|
-
should "
|
185
|
-
assert_true @daemon_class.
|
154
|
+
should "have validated its config" do
|
155
|
+
assert_true @daemon_class.config.valid?
|
186
156
|
end
|
187
157
|
|
188
|
-
should "
|
158
|
+
should "have initialized Qs" do
|
189
159
|
assert_true @qs_init_called
|
190
160
|
end
|
191
161
|
|
192
162
|
should "know its daemon data" do
|
193
|
-
|
194
|
-
data
|
163
|
+
config = @daemon_class.config
|
164
|
+
data = subject.daemon_data
|
195
165
|
|
196
166
|
assert_instance_of Qs::DaemonData, data
|
197
|
-
assert_equal configuration.name, data.name
|
198
|
-
assert_equal configuration.pid_file, data.pid_file
|
199
|
-
assert_equal configuration.worker_class, data.worker_class
|
200
|
-
assert_equal configuration.worker_params, data.worker_params
|
201
|
-
assert_equal configuration.num_workers, data.num_workers
|
202
167
|
|
203
|
-
assert_equal
|
204
|
-
assert_equal
|
205
|
-
assert_equal
|
168
|
+
assert_equal config.name, data.name
|
169
|
+
assert_equal config.pid_file, data.pid_file
|
170
|
+
assert_equal config.shutdown_timeout, data.shutdown_timeout
|
171
|
+
assert_equal config.worker_class, data.worker_class
|
172
|
+
assert_equal config.worker_params, data.worker_params
|
173
|
+
assert_equal config.num_workers, data.num_workers
|
174
|
+
assert_equal config.error_procs, data.error_procs
|
206
175
|
|
207
|
-
|
208
|
-
assert_equal configuration.routes, data.routes.values
|
176
|
+
assert_instance_of config.logger.class, data.logger
|
209
177
|
|
210
|
-
|
211
|
-
|
178
|
+
assert_equal config.queues.size, data.queue_redis_keys.size
|
179
|
+
assert_equal config.verbose_logging, data.verbose_logging
|
212
180
|
|
213
|
-
|
214
|
-
data = subject.daemon_data
|
215
|
-
expected = "signals:#{data.name}-#{Socket.gethostname}-#{::Process.pid}"
|
216
|
-
assert_equal expected, subject.signals_redis_key
|
217
|
-
assert_equal data.queue_redis_keys, subject.queue_redis_keys
|
181
|
+
assert_equal config.routes, data.routes.values
|
218
182
|
end
|
219
183
|
|
220
|
-
should "know its
|
184
|
+
should "know its signals redis keys" do
|
221
185
|
data = subject.daemon_data
|
222
|
-
|
223
|
-
assert_equal
|
224
|
-
assert_equal data.pid_file, subject.pid_file
|
186
|
+
exp = "signals:#{data.name}-#{Socket.gethostname}-#{::Process.pid}"
|
187
|
+
assert_equal exp, subject.signals_redis_key
|
225
188
|
end
|
226
189
|
|
227
190
|
should "build a client" do
|
228
191
|
assert_not_nil @client_spy
|
229
|
-
exp = Qs.
|
192
|
+
exp = Qs.redis_connect_hash.merge({
|
230
193
|
:timeout => 1,
|
231
194
|
:size => subject.daemon_data.num_workers + 1
|
232
195
|
})
|
233
|
-
assert_equal exp, @client_spy.
|
196
|
+
assert_equal exp, @client_spy.redis_connect_hash
|
234
197
|
end
|
235
198
|
|
236
|
-
should "build a worker pool" do
|
199
|
+
should "build a dat-worker-pool worker pool" do
|
237
200
|
data = subject.daemon_data
|
238
201
|
|
239
202
|
assert_not_nil @wp_spy
|
240
203
|
assert_equal data.worker_class, @wp_spy.worker_class
|
241
204
|
assert_equal data.dwp_logger, @wp_spy.logger
|
242
205
|
assert_equal data.num_workers, @wp_spy.num_workers
|
206
|
+
|
243
207
|
exp = data.worker_params.merge({
|
244
208
|
:qs_daemon_data => data,
|
245
209
|
:qs_client => @client_spy,
|
@@ -250,6 +214,16 @@ module Qs::Daemon
|
|
250
214
|
assert_false @wp_spy.start_called
|
251
215
|
end
|
252
216
|
|
217
|
+
should "demeter its daemon data" do
|
218
|
+
data = subject.daemon_data
|
219
|
+
|
220
|
+
assert_equal data.name, subject.name
|
221
|
+
assert_equal data.process_label, subject.process_label
|
222
|
+
assert_equal data.pid_file, subject.pid_file
|
223
|
+
assert_equal data.logger, subject.logger
|
224
|
+
assert_equal data.queue_redis_keys, subject.queue_redis_keys
|
225
|
+
end
|
226
|
+
|
253
227
|
should "not be running by default" do
|
254
228
|
assert_false subject.running?
|
255
229
|
end
|
@@ -260,7 +234,7 @@ module Qs::Daemon
|
|
260
234
|
desc "and started"
|
261
235
|
setup do
|
262
236
|
@thread = @daemon.start
|
263
|
-
@thread.join
|
237
|
+
@thread.join(JOIN_SECONDS)
|
264
238
|
end
|
265
239
|
|
266
240
|
should "ping redis" do
|
@@ -296,14 +270,14 @@ module Qs::Daemon
|
|
296
270
|
|
297
271
|
@daemon = @daemon_class.new
|
298
272
|
@thread = @daemon.start
|
273
|
+
@thread.join(JOIN_SECONDS)
|
299
274
|
end
|
300
275
|
subject{ @daemon }
|
301
276
|
|
302
277
|
should "sleep its thread and not add work to its worker pool" do
|
303
|
-
@thread.join(0.1)
|
304
278
|
assert_equal 'sleep', @thread.status
|
305
279
|
@client_spy.append(@queue.redis_key, Factory.string)
|
306
|
-
@thread.join(
|
280
|
+
@thread.join(JOIN_SECONDS)
|
307
281
|
assert_empty @wp_spy.work_items
|
308
282
|
end
|
309
283
|
|
@@ -314,17 +288,21 @@ module Qs::Daemon
|
|
314
288
|
setup do
|
315
289
|
@daemon = @daemon_class.new
|
316
290
|
@thread = @daemon.start
|
291
|
+
@thread.join(JOIN_SECONDS)
|
317
292
|
|
318
293
|
@encoded_payload = Factory.string
|
319
294
|
@client_spy.append(@queue.redis_key, @encoded_payload)
|
295
|
+
@thread.join(JOIN_SECONDS)
|
320
296
|
end
|
321
297
|
subject{ @daemon }
|
322
298
|
|
323
299
|
should "call dequeue on its client and add work to the worker pool" do
|
324
300
|
call = @client_spy.calls.last
|
325
301
|
assert_equal :block_dequeue, call.command
|
302
|
+
|
326
303
|
exp = [subject.signals_redis_key, subject.queue_redis_keys, 0].flatten
|
327
304
|
assert_equal exp, call.args
|
305
|
+
|
328
306
|
exp = Qs::QueueItem.new(@queue.redis_key, @encoded_payload)
|
329
307
|
assert_equal exp, @wp_spy.work_items.first
|
330
308
|
end
|
@@ -334,25 +312,35 @@ module Qs::Daemon
|
|
334
312
|
class RunningWithErrorWhileDequeuingTests < InitSetupTests
|
335
313
|
desc "running with an error while dequeueing"
|
336
314
|
setup do
|
337
|
-
@
|
338
|
-
@
|
315
|
+
@mutex = Mutex.new
|
316
|
+
@cond_var = ConditionVariable.new
|
317
|
+
@daemon = @daemon_class.new
|
339
318
|
|
340
319
|
@block_dequeue_calls = 0
|
341
320
|
Assert.stub(@client_spy, :block_dequeue) do
|
342
321
|
@block_dequeue_calls += 1
|
322
|
+
@mutex.synchronize{ @cond_var.wait(@mutex) }
|
343
323
|
raise RuntimeError
|
344
324
|
end
|
345
|
-
|
346
|
-
|
347
|
-
@
|
348
|
-
|
325
|
+
|
326
|
+
@thread = @daemon.start
|
327
|
+
@thread.join(JOIN_SECONDS)
|
328
|
+
end
|
329
|
+
teardown do
|
330
|
+
Assert.unstub(@client_spy, :block_dequeue)
|
331
|
+
@mutex.synchronize{ @cond_var.broadcast }
|
349
332
|
end
|
350
333
|
subject{ @daemon }
|
351
334
|
|
352
335
|
should "not cause the thread to exit" do
|
353
336
|
assert_true @thread.alive?
|
354
337
|
assert_equal 1, @block_dequeue_calls
|
355
|
-
|
338
|
+
|
339
|
+
# the daemon is sleeping on the original block_dequeue, cause it to
|
340
|
+
# dequeue (and error)
|
341
|
+
@mutex.synchronize{ @cond_var.broadcast }
|
342
|
+
@thread.join(Qs::Daemon::FETCH_ERR_SLEEP_TIME + JOIN_SECONDS)
|
343
|
+
|
356
344
|
assert_true @thread.alive?
|
357
345
|
assert_equal 2, @block_dequeue_calls
|
358
346
|
end
|
@@ -370,6 +358,7 @@ module Qs::Daemon
|
|
370
358
|
Assert.stub(@daemon.queue_redis_keys, :shuffle){ @shuffled_keys }
|
371
359
|
|
372
360
|
@thread = @daemon.start
|
361
|
+
@thread.join(JOIN_SECONDS)
|
373
362
|
end
|
374
363
|
subject{ @daemon }
|
375
364
|
|
@@ -419,6 +408,7 @@ module Qs::Daemon
|
|
419
408
|
@wp_worker_available = false
|
420
409
|
@daemon = @daemon_class.new
|
421
410
|
@thread = @daemon.start
|
411
|
+
@thread.join(JOIN_SECONDS)
|
422
412
|
@daemon.stop(true)
|
423
413
|
end
|
424
414
|
subject{ @daemon }
|
@@ -466,6 +456,7 @@ module Qs::Daemon
|
|
466
456
|
@wp_worker_available = false
|
467
457
|
@daemon = @daemon_class.new
|
468
458
|
@thread = @daemon.start
|
459
|
+
@thread.join(JOIN_SECONDS)
|
469
460
|
@daemon.halt(true)
|
470
461
|
end
|
471
462
|
subject{ @daemon }
|
@@ -486,7 +477,7 @@ module Qs::Daemon
|
|
486
477
|
# call that happened before the stub
|
487
478
|
@queue_item = Qs::QueueItem.new(@queue.redis_key, Factory.string)
|
488
479
|
@client_spy.append(@queue_item.queue_redis_key, @queue_item.encoded_payload)
|
489
|
-
@thread.join
|
480
|
+
@thread.join(JOIN_SECONDS)
|
490
481
|
end
|
491
482
|
|
492
483
|
should "shutdown the worker pool" do
|
@@ -511,10 +502,8 @@ module Qs::Daemon
|
|
511
502
|
|
512
503
|
end
|
513
504
|
|
514
|
-
class
|
515
|
-
|
516
|
-
|
517
|
-
desc "Configuration"
|
505
|
+
class ConfigTests < UnitTests
|
506
|
+
desc "Config"
|
518
507
|
setup do
|
519
508
|
@queue = Qs::Queue.new do
|
520
509
|
name Factory.string
|
@@ -522,85 +511,106 @@ module Qs::Daemon
|
|
522
511
|
job 'test', 'TestHandler'
|
523
512
|
end
|
524
513
|
|
525
|
-
@
|
526
|
-
|
527
|
-
c.queues << @queue
|
528
|
-
end
|
514
|
+
@config_class = Config
|
515
|
+
@config = Config.new
|
529
516
|
end
|
530
|
-
subject{ @
|
531
|
-
|
532
|
-
should have_options :name, :pid_file
|
533
|
-
should have_options :num_workers
|
534
|
-
should have_options :verbose_logging, :logger
|
535
|
-
should have_options :shutdown_timeout
|
536
|
-
should have_accessors :init_procs, :error_procs
|
537
|
-
should have_accessors :worker_class, :worker_params
|
538
|
-
should have_accessors :queues
|
539
|
-
should have_imeths :routes
|
540
|
-
should have_imeths :to_hash
|
541
|
-
should have_imeths :valid?, :validate!
|
542
|
-
|
543
|
-
should "be an ns-options proxy" do
|
544
|
-
assert_includes NsOptions::Proxy, subject.class
|
545
|
-
end
|
546
|
-
|
547
|
-
should "default its options and attrs" do
|
548
|
-
config = Configuration.new
|
549
|
-
assert_nil config.name
|
550
|
-
assert_nil config.pid_file
|
551
|
-
assert_equal 4, config.num_workers
|
552
|
-
assert_true config.verbose_logging
|
553
|
-
assert_instance_of Qs::NullLogger, config.logger
|
554
|
-
assert_nil subject.shutdown_timeout
|
517
|
+
subject{ @config }
|
555
518
|
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
519
|
+
should have_accessors :name, :pid_file, :shutdown_timeout
|
520
|
+
should have_accessors :worker_class, :worker_params, :num_workers
|
521
|
+
should have_accessors :init_procs, :error_procs, :logger, :queues
|
522
|
+
should have_accessors :verbose_logging
|
523
|
+
should have_imeths :routes, :valid?, :validate!
|
524
|
+
|
525
|
+
should "know its default attr values" do
|
526
|
+
assert_equal 4, @config_class::DEFAULT_NUM_WORKERS
|
562
527
|
end
|
563
528
|
|
564
|
-
should "
|
565
|
-
|
529
|
+
should "default its attrs" do
|
530
|
+
assert_nil subject.name
|
531
|
+
assert_nil subject.pid_file
|
532
|
+
assert_nil subject.shutdown_timeout
|
533
|
+
|
534
|
+
assert_equal DefaultWorker, subject.worker_class
|
535
|
+
|
536
|
+
assert_nil subject.worker_params
|
537
|
+
|
538
|
+
exp = @config_class::DEFAULT_NUM_WORKERS
|
539
|
+
assert_equal exp, subject.num_workers
|
540
|
+
|
541
|
+
assert_equal [], subject.init_procs
|
542
|
+
assert_equal [], subject.error_procs
|
543
|
+
|
544
|
+
assert_instance_of Qs::NullLogger, subject.logger
|
545
|
+
|
546
|
+
assert_equal [], subject.queues
|
547
|
+
assert_equal true, subject.verbose_logging
|
566
548
|
end
|
567
549
|
|
568
550
|
should "know its routes" do
|
569
|
-
|
551
|
+
exp = subject.queues.map(&:routes).flatten
|
552
|
+
assert_equal exp, subject.routes
|
570
553
|
end
|
571
554
|
|
572
|
-
should "
|
573
|
-
|
574
|
-
|
575
|
-
assert_equal subject.error_procs, config_hash[:error_procs]
|
576
|
-
assert_equal subject.worker_class, config_hash[:worker_class]
|
577
|
-
assert_equal subject.worker_params, config_hash[:worker_params]
|
578
|
-
assert_equal subject.routes, config_hash[:routes]
|
555
|
+
should "not be valid until validate! has been run" do
|
556
|
+
assert_false subject.valid?
|
579
557
|
|
580
|
-
|
581
|
-
|
582
|
-
end
|
558
|
+
subject.name = Factory.string
|
559
|
+
subject.queues << @queue
|
583
560
|
|
584
|
-
should "call its init procs when validated" do
|
585
|
-
called = false
|
586
|
-
subject.init_procs << proc{ called = true }
|
587
561
|
subject.validate!
|
588
|
-
assert_true
|
562
|
+
assert_true subject.valid?
|
589
563
|
end
|
590
564
|
|
591
|
-
should "
|
565
|
+
should "complain if validating and its name is nil or it has no queues" do
|
592
566
|
subject.name = nil
|
567
|
+
subject.queues << @queue
|
593
568
|
assert_raises(InvalidError){ subject.validate! }
|
594
|
-
subject.name = Factory.string
|
595
569
|
|
596
|
-
subject.
|
570
|
+
subject.name = Factory.string
|
571
|
+
subject.queues.clear
|
597
572
|
assert_raises(InvalidError){ subject.validate! }
|
573
|
+
end
|
574
|
+
|
575
|
+
should "complain if validating and its worker class isn't a Worker" do
|
576
|
+
subject.name = Factory.string
|
598
577
|
subject.queues << @queue
|
599
578
|
|
600
|
-
|
579
|
+
subject.worker_class = Module.new
|
580
|
+
assert_raises(InvalidError){ subject.validate! }
|
581
|
+
|
582
|
+
subject.worker_class = Class.new
|
583
|
+
assert_raises(InvalidError){ subject.validate! }
|
584
|
+
end
|
585
|
+
|
586
|
+
end
|
587
|
+
|
588
|
+
class ValidationTests < ConfigTests
|
589
|
+
desc "when successfully validated"
|
590
|
+
setup do
|
591
|
+
@config = Config.new.tap do |c|
|
592
|
+
c.name = Factory.string
|
593
|
+
c.queues << @queue
|
594
|
+
end
|
595
|
+
|
596
|
+
@initialized = false
|
597
|
+
@config.init_procs << proc{ @initialized = true }
|
598
|
+
|
599
|
+
@other_initialized = false
|
600
|
+
@config.init_procs << proc{ @other_initialized = true }
|
601
|
+
end
|
602
|
+
|
603
|
+
should "call its init procs" do
|
604
|
+
assert_equal false, @initialized
|
605
|
+
assert_equal false, @other_initialized
|
606
|
+
|
607
|
+
subject.validate!
|
608
|
+
|
609
|
+
assert_equal true, @initialized
|
610
|
+
assert_equal true, @other_initialized
|
601
611
|
end
|
602
612
|
|
603
|
-
should "validate its routes
|
613
|
+
should "validate its routes" do
|
604
614
|
subject.routes.each{ |route| assert_nil route.handler_class }
|
605
615
|
subject.validate!
|
606
616
|
subject.routes.each{ |route| assert_not_nil route.handler_class }
|
@@ -614,12 +624,6 @@ module Qs::Daemon
|
|
614
624
|
assert_raises(InvalidError){ subject.validate! }
|
615
625
|
end
|
616
626
|
|
617
|
-
should "be valid after being validated" do
|
618
|
-
assert_false subject.valid?
|
619
|
-
subject.validate!
|
620
|
-
assert_true subject.valid?
|
621
|
-
end
|
622
|
-
|
623
627
|
should "only be able to be validated once" do
|
624
628
|
called = 0
|
625
629
|
subject.init_procs << proc{ called += 1 }
|
@@ -631,6 +635,27 @@ module Qs::Daemon
|
|
631
635
|
|
632
636
|
end
|
633
637
|
|
638
|
+
class WorkerAvailableTests < UnitTests
|
639
|
+
desc "WorkerAvailable"
|
640
|
+
setup do
|
641
|
+
@worker_available = WorkerAvailable.new
|
642
|
+
end
|
643
|
+
subject{ @worker_available }
|
644
|
+
|
645
|
+
should have_imeths :wait, :signal
|
646
|
+
|
647
|
+
should "allow waiting and signalling" do
|
648
|
+
thread = Thread.new{ subject.wait }
|
649
|
+
thread.join(JOIN_SECONDS)
|
650
|
+
assert_equal 'sleep', thread.status
|
651
|
+
|
652
|
+
subject.signal
|
653
|
+
thread.join(JOIN_SECONDS)
|
654
|
+
assert_equal false, thread.status # dead, done running
|
655
|
+
end
|
656
|
+
|
657
|
+
end
|
658
|
+
|
634
659
|
class StateTests < UnitTests
|
635
660
|
desc "State"
|
636
661
|
setup do
|
@@ -664,24 +689,6 @@ module Qs::Daemon
|
|
664
689
|
|
665
690
|
end
|
666
691
|
|
667
|
-
class WorkerAvailableTests < UnitTests
|
668
|
-
desc "WorkerAvailable"
|
669
|
-
setup do
|
670
|
-
@worker_available = WorkerAvailable.new
|
671
|
-
end
|
672
|
-
subject{ @worker_available }
|
673
|
-
|
674
|
-
should have_imeths :wait, :signal
|
675
|
-
|
676
|
-
should "allow waiting and signalling" do
|
677
|
-
thread = Thread.new{ subject.wait }
|
678
|
-
assert_equal 'sleep', thread.status
|
679
|
-
subject.signal
|
680
|
-
assert_equal false, thread.status # dead, done running
|
681
|
-
end
|
682
|
-
|
683
|
-
end
|
684
|
-
|
685
692
|
TestHandler = Class.new
|
686
693
|
|
687
694
|
end
|