qs 0.5.0 → 0.6.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.
@@ -1,14 +1,14 @@
1
+ require 'much-plugin'
1
2
  require 'qs/message_handler'
2
3
 
3
4
  module Qs
4
5
 
5
6
  module JobHandler
7
+ include MuchPlugin
6
8
 
7
- def self.included(klass)
8
- klass.class_eval do
9
- include Qs::MessageHandler
10
- include InstanceMethods
11
- end
9
+ plugin_included do
10
+ include Qs::MessageHandler
11
+ include InstanceMethods
12
12
  end
13
13
 
14
14
  module InstanceMethods
@@ -28,6 +28,22 @@ module Qs
28
28
 
29
29
  end
30
30
 
31
+ module TestHelpers
32
+
33
+ def self.included(klass)
34
+ require 'qs/test_runner'
35
+ end
36
+
37
+ def test_runner(handler_class, args = nil)
38
+ Qs::JobTestRunner.new(handler_class, args)
39
+ end
40
+
41
+ def test_handler(handler_class, args = nil)
42
+ test_runner(handler_class, args).handler
43
+ end
44
+
45
+ end
46
+
31
47
  end
32
48
 
33
49
  end
@@ -1,12 +1,13 @@
1
+ require 'much-plugin'
2
+
1
3
  module Qs
2
4
 
3
5
  module MessageHandler
6
+ include MuchPlugin
4
7
 
5
- def self.included(klass)
6
- klass.class_eval do
7
- extend ClassMethods
8
- include InstanceMethods
9
- end
8
+ plugin_included do
9
+ extend ClassMethods
10
+ include InstanceMethods
10
11
  end
11
12
 
12
13
  module InstanceMethods
@@ -15,37 +16,40 @@ module Qs
15
16
  @qs_runner = runner
16
17
  end
17
18
 
18
- def init
19
- run_callback 'before_init'
19
+ def qs_init
20
+ self.qs_run_callback 'before_init'
20
21
  self.init!
21
- run_callback 'after_init'
22
+ self.qs_run_callback 'after_init'
22
23
  end
23
24
 
24
25
  def init!
25
26
  end
26
27
 
27
- def run
28
- run_callback 'before_run'
28
+ def qs_run
29
+ self.qs_run_callback 'before_run'
29
30
  self.run!
30
- run_callback 'after_run'
31
+ self.qs_run_callback 'after_run'
31
32
  end
32
33
 
33
34
  def run!
34
- raise NotImplementedError
35
+ end
36
+
37
+ def qs_run_callback(callback)
38
+ (self.class.send("#{callback}_callbacks") || []).each do |callback|
39
+ self.instance_eval(&callback)
40
+ end
41
+ end
42
+
43
+ def ==(other_handler)
44
+ self.class == other_handler.class
35
45
  end
36
46
 
37
47
  private
38
48
 
39
49
  # Helpers
40
50
 
41
- def params; @qs_runner.params; end
42
51
  def logger; @qs_runner.logger; end
43
-
44
- def run_callback(callback)
45
- (self.class.send("#{callback}_callbacks") || []).each do |callback|
46
- self.instance_eval(&callback)
47
- end
48
- end
52
+ def params; @qs_runner.params; end
49
53
 
50
54
  end
51
55
 
@@ -26,7 +26,6 @@ module Qs
26
26
  benchmark = Benchmark.measure{ run!(@daemon_data, @queue_item) }
27
27
  @queue_item.time_taken = RoundedTime.new(benchmark.real)
28
28
  log_complete(@queue_item)
29
- raise_if_debugging!(@queue_item.exception)
30
29
  end
31
30
 
32
31
  private
@@ -67,10 +66,6 @@ module Qs
67
66
  log_exception(queue_item.exception)
68
67
  end
69
68
 
70
- def raise_if_debugging!(exception)
71
- raise exception if exception && ENV['QS_DEBUG']
72
- end
73
-
74
69
  def log_received
75
70
  log_verbose "===== Received message ====="
76
71
  end
@@ -99,9 +94,8 @@ module Qs
99
94
  end
100
95
 
101
96
  def log_exception(exception)
102
- backtrace = exception.backtrace.join("\n")
103
- message = "#{exception.class}: #{exception.message}\n#{backtrace}"
104
- log_verbose(message, :error)
97
+ log_verbose("#{exception.class}: #{exception.message}", :error)
98
+ (exception.backtrace || []).each{ |l| log_verbose(l, :error) }
105
99
  end
106
100
 
107
101
  def log_verbose(message, level = :info)
data/lib/qs/qs_runner.rb CHANGED
@@ -15,10 +15,10 @@ module Qs
15
15
 
16
16
  def run
17
17
  OptionalTimeout.new(self.timeout) do
18
- run_callbacks self.handler_class.before_callbacks
19
- self.handler.init
20
- self.handler.run
21
- run_callbacks self.handler_class.after_callbacks
18
+ self.handler.qs_run_callback 'before'
19
+ self.handler.qs_init
20
+ self.handler.qs_run
21
+ self.handler.qs_run_callback 'after'
22
22
  end
23
23
  rescue TimeoutError => exception
24
24
  error = TimeoutError.new "#{handler_class} timed out (#{timeout}s)"
@@ -28,10 +28,6 @@ module Qs
28
28
 
29
29
  private
30
30
 
31
- def run_callbacks(callbacks)
32
- callbacks.each{ |proc| self.handler.instance_eval(&proc) }
33
- end
34
-
35
31
  module OptionalTimeout
36
32
  def self.new(timeout, &block)
37
33
  if !timeout.nil?
data/lib/qs/runner.rb CHANGED
@@ -5,16 +5,15 @@ module Qs
5
5
  class Runner
6
6
 
7
7
  attr_reader :handler_class, :handler
8
- attr_reader :message, :params, :logger
8
+ attr_reader :logger, :message, :params
9
9
 
10
10
  def initialize(handler_class, args = nil)
11
- @handler_class = handler_class
12
-
13
- a = args || {}
14
- @message = a[:message]
15
- @params = a[:params] || {}
16
- @logger = a[:logger] || Qs::NullLogger.new
11
+ args ||= {}
12
+ @logger = args[:logger] || Qs::NullLogger.new
13
+ @message = args[:message]
14
+ @params = args[:params] || {}
17
15
 
16
+ @handler_class = handler_class
18
17
  @handler = @handler_class.new(self)
19
18
  end
20
19
 
@@ -9,25 +9,25 @@ module Qs
9
9
  class TestRunner < Runner
10
10
 
11
11
  def initialize(handler_class, args = nil)
12
- args = (args || {}).dup
12
+ a = (args || {}).dup
13
13
  super(handler_class, {
14
- :message => args.delete(:message),
15
- :params => normalize_params(args.delete(:params) || {}),
16
- :logger => args.delete(:logger)
14
+ :logger => a.delete(:logger),
15
+ :message => a.delete(:message),
16
+ :params => normalize_params(a.delete(:params) || {})
17
17
  })
18
- args.each{ |key, value| self.handler.send("#{key}=", value) }
18
+ a.each{ |key, value| self.handler.send("#{key}=", value) }
19
19
 
20
- self.handler.init
20
+ self.handler.qs_init
21
21
  end
22
22
 
23
23
  def run
24
- self.handler.run
24
+ self.handler.qs_run
25
25
  end
26
26
 
27
27
  private
28
28
 
29
- # Stringify and encode/decode to ensure params are valid and are
30
- # in the format they would normally be when a handler is built and run.
29
+ # stringify and encode/decode to ensure params are valid and are
30
+ # in the format they would normally be when a live handler is built and run.
31
31
  def normalize_params(params)
32
32
  params = Qs::Payload::StringifyParams.new(params)
33
33
  Qs.decode(Qs.encode(params))
@@ -39,13 +39,13 @@ module Qs
39
39
 
40
40
  def initialize(handler_class, args = nil)
41
41
  if !handler_class.include?(Qs::JobHandler)
42
- raise InvalidJobHandlerError, "#{handler_class.inspect} is not a"\
43
- " Qs::JobHandler"
42
+ raise InvalidJobHandlerError, "#{handler_class.inspect} is not a " \
43
+ "Qs::JobHandler"
44
44
  end
45
45
 
46
- args = (args || {}).dup
47
- args[:message] = args.delete(:job) if args.key?(:job)
48
- super(handler_class, args)
46
+ a = (args || {}).dup
47
+ a[:message] = a.delete(:job) if a.key?(:job)
48
+ super(handler_class, a)
49
49
  end
50
50
 
51
51
  end
@@ -54,13 +54,13 @@ module Qs
54
54
 
55
55
  def initialize(handler_class, args = nil)
56
56
  if !handler_class.include?(Qs::EventHandler)
57
- raise InvalidEventHandlerError, "#{handler_class.inspect} is not a"\
58
- " Qs::EventHandler"
57
+ raise InvalidEventHandlerError, "#{handler_class.inspect} is not a " \
58
+ "Qs::EventHandler"
59
59
  end
60
60
 
61
- args = (args || {}).dup
62
- args[:message] = args.delete(:event) if args.key?(:event)
63
- super(handler_class, args)
61
+ a = (args || {}).dup
62
+ a[:message] = a.delete(:event) if a.key?(:event)
63
+ super(handler_class, a)
64
64
  end
65
65
 
66
66
  end
data/lib/qs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qs
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/qs/worker.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'dat-worker-pool/worker'
2
+ require 'much-plugin'
3
+ require 'qs/client'
4
+ require 'qs/daemon'
5
+ require 'qs/daemon_data'
6
+ require 'qs/payload_handler'
7
+
8
+ module Qs
9
+
10
+ module Worker
11
+ include MuchPlugin
12
+
13
+ plugin_included do
14
+ include DatWorkerPool::Worker
15
+ include InstanceMethods
16
+
17
+ on_available{ params[:qs_worker_available].signal }
18
+
19
+ on_error{ |e, wi| qs_handle_exception(e, wi) }
20
+
21
+ end
22
+
23
+ module InstanceMethods
24
+
25
+ def work!(queue_item)
26
+ Qs::PayloadHandler.new(params[:qs_daemon_data], queue_item).run
27
+ end
28
+
29
+ private
30
+
31
+ # this only catches errors that happen outside of running the payload
32
+ # handler, the only known use-case for this is dwps shutdown errors; if
33
+ # there isn't a queue item (this can happen when an idle worker is being
34
+ # forced to exit) then we don't need to do anything; if we never started
35
+ # processing the queue item, its safe to requeue it, otherwise it happened
36
+ # while it was being processed (by the payload handler) or after it was
37
+ # processed, for these cases, either the payload handler caught the error
38
+ # (while it was being processed) or we don't care because its been
39
+ # processed and the worker is just finishing up
40
+ def qs_handle_exception(exception, queue_item)
41
+ return if queue_item.nil?
42
+ if !queue_item.started
43
+ qs_log "Worker error, requeueing message because it hasn't started", :error
44
+ params[:qs_client].prepend(
45
+ queue_item.queue_redis_key,
46
+ queue_item.encoded_payload
47
+ )
48
+ else
49
+ qs_log "Worker error after message was processed, ignoring", :error
50
+ end
51
+ qs_log "#{exception.class}: #{exception.message}", :error
52
+ qs_log (exception.backtrace || []).join("\n"), :error
53
+ end
54
+
55
+ def qs_log(message, level = :info)
56
+ params[:qs_logger].send(level, "[Qs-#{number}] #{message}")
57
+ end
58
+
59
+ end
60
+
61
+ module TestHelpers
62
+ include MuchPlugin
63
+
64
+ plugin_included do
65
+ include DatWorkerPool::Worker::TestHelpers
66
+ include InstanceMethods
67
+ end
68
+
69
+ module InstanceMethods
70
+
71
+ def test_runner(worker_class, options = nil)
72
+ options ||= {}
73
+ options[:params] = {
74
+ :qs_daemon_data => Qs::DaemonData.new,
75
+ :qs_client => Qs::TestClient.new({}),
76
+ :qs_worker_available => Qs::Daemon::WorkerAvailable.new,
77
+ :qs_logger => Qs::NullLogger.new
78
+ }.merge(options[:params] || {})
79
+ super(worker_class, options)
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
data/qs.gemspec CHANGED
@@ -18,11 +18,13 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ["lib"]
20
20
 
21
- gem.add_dependency("dat-worker-pool", ["~> 0.5"])
21
+ gem.add_dependency("dat-worker-pool", ["~> 0.6"])
22
22
  gem.add_dependency("hella-redis", ["~> 0.3"])
23
+ gem.add_dependency("much-plugin", ["~> 0.1"])
23
24
  gem.add_dependency("ns-options", ["~> 1.1"])
24
25
  gem.add_dependency("SystemTimer", ["~> 1.2"])
25
26
 
26
27
  gem.add_development_dependency("assert", ["~> 2.15"])
27
- gem.add_development_dependency("scmd", ["~> 2.3"])
28
+ gem.add_development_dependency("scmd", ["~> 3.0"])
29
+
28
30
  end
@@ -0,0 +1,43 @@
1
+ require 'qs/client'
2
+
3
+ class ClientSpy < Qs::TestClient
4
+ attr_reader :calls
5
+
6
+ def initialize(redis_config = nil)
7
+ super(redis_config || {})
8
+ @calls = []
9
+ @list = []
10
+ @mutex = Mutex.new
11
+ @cv = ConditionVariable.new
12
+ end
13
+
14
+ def block_dequeue(*args)
15
+ @calls << Call.new(:block_dequeue, args)
16
+ if @list.empty?
17
+ @mutex.synchronize{ @cv.wait(@mutex) }
18
+ end
19
+ @list.shift
20
+ end
21
+
22
+ def append(*args)
23
+ @calls << Call.new(:append, args)
24
+ @list << args
25
+ @cv.signal
26
+ end
27
+
28
+ def prepend(*args)
29
+ @calls << Call.new(:prepend, args)
30
+ @list << args
31
+ @cv.signal
32
+ end
33
+
34
+ def clear(*args)
35
+ @calls << Call.new(:clear, args)
36
+ end
37
+
38
+ def ping
39
+ @calls << Call.new(:ping)
40
+ end
41
+
42
+ Call = Struct.new(:command, :args)
43
+ end
@@ -10,7 +10,8 @@ module Factory
10
10
  klass ||= StandardError
11
11
  message ||= Factory.text
12
12
  exception = nil
13
- begin; raise(klass, message); rescue StandardError => exception; end
13
+ begin; raise(klass, message); rescue klass => exception; end
14
+ exception.set_backtrace(nil) if Factory.boolean
14
15
  exception
15
16
  end
16
17
 
@@ -0,0 +1,17 @@
1
+ require 'qs/message_handler'
2
+ require 'qs/test_runner'
3
+
4
+ # manually define some test helpers since we don't provide helpers for
5
+ # general message handlers as the user facing helpers are the job/event ones
6
+
7
+ module Qs::MessageHandler
8
+
9
+ module TestHelpers
10
+
11
+ def test_runner(handler_class, args = nil)
12
+ Qs::TestRunner.new(handler_class, args)
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -144,27 +144,6 @@ module Qs::Daemon
144
144
 
145
145
  end
146
146
 
147
- class NoWorkersAvailableTests < SystemTests
148
- desc "when no workers are available"
149
- setup do
150
- AppDaemon.workers 0 # no workers available, don't do this
151
- setup_app_and_dispatcher_daemon
152
- end
153
-
154
- should "shutdown when stopped" do
155
- @app_daemon.stop
156
- @app_thread.join 2 # give it time to shutdown, should be faster
157
- assert_false @app_thread.alive?
158
- end
159
-
160
- should "shutdown when halted" do
161
- @app_daemon.halt
162
- @app_thread.join 2 # give it time to shutdown, should be faster
163
- assert_false @app_thread.alive?
164
- end
165
-
166
- end
167
-
168
147
  class ShutdownWithoutTimeoutTests < SystemTests
169
148
  desc "without a shutdown timeout"
170
149
  setup do
@@ -270,6 +249,24 @@ module Qs::Daemon
270
249
 
271
250
  end
272
251
 
252
+ class WithEnvProcessLabelTests < SystemTests
253
+ desc "with a process label env var"
254
+ setup do
255
+ ENV['QS_PROCESS_LABEL'] = Factory.string
256
+
257
+ @daemon = AppDaemon.new
258
+ end
259
+ teardown do
260
+ ENV.delete('QS_PROCESS_LABEL')
261
+ end
262
+ subject{ @daemon }
263
+
264
+ should "set the daemons process label to the env var" do
265
+ assert_equal ENV['QS_PROCESS_LABEL'], subject.process_label
266
+ end
267
+
268
+ end
269
+
273
270
  class DaemonRunner
274
271
  def initialize(app_daemon, dispatcher_daemon = nil)
275
272
  @app_daemon = app_daemon
@@ -9,71 +9,87 @@ class Qs::DaemonData
9
9
  class UnitTests < Assert::Context
10
10
  desc "Qs::DaemonData"
11
11
  setup do
12
- @name = Factory.string
13
- @process_label = Factory.string
14
- @pid_file = Factory.file_path
15
- @min_workers = Factory.integer
16
- @max_workers = Factory.integer
17
- @start_procs = Factory.integer(3).times.map{ proc{} }
18
- @shutdown_procs = Factory.integer(3).times.map{ proc{} }
19
- @sleep_procs = Factory.integer(3).times.map{ proc{} }
20
- @wakeup_procs = Factory.integer(3).times.map{ proc{} }
21
- @logger = Factory.string
22
- @verbose_logging = Factory.boolean
23
- @shutdown_timeout = Factory.integer
24
- @error_procs = [ proc{ Factory.string } ]
25
- @queue_redis_keys = Factory.integer(3).times.map{ Factory.string }
12
+ @current_env_process_label = ENV['QS_PROCESS_LABEL']
13
+ ENV['QS_PROCESS_LABEL'] = Factory.string
14
+
15
+ @current_env_debug = ENV['QS_DEBUG']
16
+ ENV['QS_DEBUG'] = Factory.string
26
17
 
27
18
  @routes = (0..Factory.integer(3)).map do
28
19
  Qs::Route.new(Factory.string, TestHandler.to_s).tap(&:validate!)
29
20
  end
30
21
 
31
- @daemon_data = Qs::DaemonData.new({
32
- :name => @name,
33
- :process_label => @process_label,
34
- :pid_file => @pid_file,
35
- :min_workers => @min_workers,
36
- :max_workers => @max_workers,
37
- :worker_start_procs => @start_procs,
38
- :worker_shutdown_procs => @shutdown_procs,
39
- :worker_sleep_procs => @sleep_procs,
40
- :worker_wakeup_procs => @wakeup_procs,
41
- :logger => @logger,
42
- :verbose_logging => @verbose_logging,
43
- :shutdown_timeout => @shutdown_timeout,
44
- :error_procs => @error_procs,
45
- :queue_redis_keys => @queue_redis_keys,
46
- :routes => @routes
47
- })
22
+ @config_hash = {
23
+ :name => Factory.string,
24
+ :pid_file => Factory.file_path,
25
+ :worker_class => Class.new,
26
+ :worker_params => { Factory.string => Factory.string },
27
+ :num_workers => Factory.integer,
28
+ :logger => Factory.string,
29
+ :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
+ :routes => @routes
34
+ }
35
+ @daemon_data = Qs::DaemonData.new(@config_hash)
36
+ end
37
+ teardown do
38
+ ENV['QS_DEBUG'] = @current_env_debug
39
+ ENV['QS_PROCESS_LABEL'] = @current_env_process_label
48
40
  end
49
41
  subject{ @daemon_data }
50
42
 
51
- should have_readers :name, :process_label
52
- should have_readers :pid_file
53
- should have_readers :min_workers, :max_workers
54
- should have_readers :worker_start_procs, :worker_shutdown_procs
55
- should have_readers :worker_sleep_procs, :worker_wakeup_procs
56
- should have_readers :logger, :verbose_logging
43
+ should have_readers :name, :process_label, :pid_file
44
+ should have_readers :worker_class, :worker_params, :num_workers
45
+ should have_readers :debug, :logger, :dwp_logger, :verbose_logging
57
46
  should have_readers :shutdown_timeout
58
- should have_readers :error_procs
59
- should have_readers :queue_redis_keys, :routes
47
+ should have_readers :error_procs, :queue_redis_keys, :routes
60
48
  should have_imeths :route_for
61
49
 
62
50
  should "know its attributes" do
63
- assert_equal @name, subject.name
64
- assert_equal @process_label, subject.process_label
65
- assert_equal @pid_file, subject.pid_file
66
- assert_equal @min_workers, subject.min_workers
67
- assert_equal @max_workers, subject.max_workers
68
- assert_equal @start_procs, subject.worker_start_procs
69
- assert_equal @shutdown_procs, subject.worker_shutdown_procs
70
- assert_equal @sleep_procs, subject.worker_sleep_procs
71
- assert_equal @wakeup_procs, subject.worker_wakeup_procs
72
- assert_equal @logger, subject.logger
73
- assert_equal @verbose_logging, subject.verbose_logging
74
- assert_equal @shutdown_timeout, subject.shutdown_timeout
75
- assert_equal @error_procs, subject.error_procs
76
- assert_equal @queue_redis_keys, subject.queue_redis_keys
51
+ h = @config_hash
52
+ assert_equal h[:name], subject.name
53
+ assert_equal h[:pid_file], subject.pid_file
54
+ assert_equal h[:worker_class], subject.worker_class
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
59
+ assert_equal h[:shutdown_timeout], subject.shutdown_timeout
60
+ assert_equal h[:error_procs], subject.error_procs
61
+ assert_equal h[:queue_redis_keys], subject.queue_redis_keys
62
+ end
63
+
64
+ should "use process label env var if set" do
65
+ ENV['QS_PROCESS_LABEL'] = Factory.string
66
+ daemon_data = Qs::DaemonData.new(@config_hash)
67
+ assert_equal ENV['QS_PROCESS_LABEL'], daemon_data.process_label
68
+
69
+ ENV['QS_PROCESS_LABEL'] = ""
70
+ daemon_data = Qs::DaemonData.new(@config_hash)
71
+ assert_equal @config_hash[:name], daemon_data.process_label
72
+
73
+ ENV.delete('QS_PROCESS_LABEL')
74
+ daemon_data = Qs::DaemonData.new(@config_hash)
75
+ assert_equal @config_hash[:name], daemon_data.process_label
76
+ end
77
+
78
+ should "use debug env var if set" do
79
+ ENV['QS_DEBUG'] = Factory.string
80
+ daemon_data = Qs::DaemonData.new(@config_hash)
81
+ assert_true daemon_data.debug
82
+ assert_equal @config_hash[:logger], daemon_data.dwp_logger
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
77
93
  end
78
94
 
79
95
  should "build a routes lookup hash" do
@@ -97,8 +113,9 @@ class Qs::DaemonData
97
113
  daemon_data = Qs::DaemonData.new
98
114
  assert_nil daemon_data.name
99
115
  assert_nil daemon_data.pid_file
100
- assert_nil daemon_data.min_workers
101
- assert_nil daemon_data.max_workers
116
+ assert_nil daemon_data.worker_class
117
+ assert_equal({}, daemon_data.worker_params)
118
+ assert_nil daemon_data.num_workers
102
119
  assert_nil daemon_data.logger
103
120
  assert_false daemon_data.verbose_logging
104
121
  assert_nil daemon_data.shutdown_timeout