beetle 0.2.3 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,133 @@
1
+ Given /^a redis server "([^\"]*)" exists as master$/ do |redis_name|
2
+ TestDaemons::Redis[redis_name].start
3
+ TestDaemons::Redis[redis_name].master
4
+ end
5
+
6
+ Given /^a redis server "([^\"]*)" exists as slave of "([^\"]*)"$/ do |redis_name, redis_master_name|
7
+ TestDaemons::Redis[redis_name].start
8
+ Given "redis server \"#{redis_name}\" is slave of \"#{redis_master_name}\""
9
+ end
10
+
11
+ Given /^redis server "([^\"]*)" is master$/ do |redis_name|
12
+ TestDaemons::Redis[redis_name].master
13
+ end
14
+
15
+ Given /^redis server "([^\"]*)" is slave of "([^\"]*)"$/ do |redis_name, redis_master_name|
16
+ TestDaemons::Redis[redis_name].slave_of(TestDaemons::Redis[redis_master_name].port)
17
+ master = TestDaemons::Redis[redis_master_name].redis
18
+ slave = TestDaemons::Redis[redis_name].redis
19
+ begin
20
+ sleep 1
21
+ end while !slave.slave_of?(master.host, master.port)
22
+ end
23
+
24
+ Given /^a redis configuration server using redis servers "([^\"]*)" with clients "([^\"]*)" exists$/ do |redis_names, redis_configuration_client_names|
25
+ redis_servers = redis_names.split(",").map { |redis_name| TestDaemons::Redis[redis_name].ip_with_port }.join(",")
26
+ TestDaemons::RedisConfigurationServer.start(redis_servers, redis_configuration_client_names)
27
+ end
28
+
29
+ Given /^a redis configuration client "([^\"]*)" using redis servers "([^\"]*)" exists$/ do |redis_configuration_client_name, redis_names|
30
+ redis_servers = redis_names.split(",").map do |redis_name|
31
+ TestDaemons::Redis[redis_name].ip_with_port
32
+ end
33
+ TestDaemons::RedisConfigurationClient[redis_configuration_client_name].start
34
+ end
35
+
36
+ Given /^redis server "([^\"]*)" is down$/ do |redis_name|
37
+ TestDaemons::Redis[redis_name].stop
38
+ end
39
+
40
+ Given /^the retry timeout for the redis master check is reached$/ do
41
+ basetime = Time.now
42
+ i = 0
43
+ while (i <= 10.0) do
44
+ break if TestDaemons::RedisConfigurationClient.instances.values.all? {|instance| File.mtime(instance.redis_master_file) > basetime rescue false}
45
+ i += 0.1
46
+ sleep(0.1)
47
+ end
48
+ sleep 1 # give it time to switch because the modified mtime might be because of the initial invalidation and not the switch
49
+ end
50
+
51
+ Given /^a beetle handler using the redis-master file from "([^\"]*)" exists$/ do |redis_configuration_client_name|
52
+ master_file = redis_master_file(redis_configuration_client_name)
53
+ `ruby features/support/beetle_handler start -- --redis-master-file=#{master_file}`
54
+ assert File.exist?(master_file), "file #{master_file} does not exist"
55
+ end
56
+
57
+ Given /^redis server "([^\"]*)" is down for less seconds than the retry timeout for the redis master check$/ do |redis_name|
58
+ TestDaemons::Redis[redis_name].restart(1)
59
+ end
60
+
61
+ Given /^the retry timeout for the redis master determination is reached$/ do
62
+ sleep 1
63
+ end
64
+
65
+ Given /^redis server "([^\"]*)" is coming back$/ do |redis_name|
66
+ TestDaemons::Redis[redis_name].start
67
+ end
68
+
69
+ Given /^an old redis master file for "([^\"]*)" with master "([^\"]*)" exists$/ do |redis_configuration_client_name, redis_name|
70
+ master_file = redis_master_file(redis_configuration_client_name)
71
+ File.open(master_file, 'w') do |f|
72
+ f.puts TestDaemons::Redis[redis_name].ip_with_port
73
+ end
74
+ end
75
+
76
+
77
+ Then /^the role of redis server "([^\"]*)" should be "(master|slave)"$/ do |redis_name, role|
78
+ expected_role = false
79
+ 10.times do
80
+ expected_role = true and break if TestDaemons::Redis[redis_name].__send__ "#{role}?"
81
+ sleep 1
82
+ end
83
+ assert expected_role, "#{redis_name} is not a #{role}"
84
+ end
85
+
86
+ Then /^the redis master of "([^\"]*)" should be "([^\"]*)"$/ do |redis_configuration_client_name, redis_name|
87
+ master_file = redis_master_file(redis_configuration_client_name)
88
+ master = false
89
+ server_info = nil
90
+ 10.times do
91
+ server_info = File.read(master_file).chomp if File.exist?(master_file)
92
+ master = true and break if TestDaemons::Redis[redis_name].ip_with_port == server_info
93
+ sleep 1
94
+ end
95
+ assert master, "#{redis_name} is not master of #{redis_configuration_client_name}, master file content: #{server_info.inspect}"
96
+ end
97
+
98
+ Then /^the redis master of "([^\"]*)" should be undefined$/ do |redis_configuration_client_name|
99
+ master_file = redis_master_file(redis_configuration_client_name)
100
+ empty = false
101
+ server_info = nil
102
+ 10.times do
103
+ server_info = File.read(master_file).chomp if File.exist?(master_file)
104
+ empty = server_info == ""
105
+ break if empty
106
+ sleep 1
107
+ end
108
+ assert empty, "master file is not empty: #{server_info}"
109
+ end
110
+
111
+ Then /^the redis master of the beetle handler should be "([^\"]*)"$/ do |redis_name|
112
+ Beetle.config.servers = "localhost:5672" # rabbitmq
113
+ Beetle.config.logger.level = Logger::INFO
114
+ client = Beetle::Client.new
115
+ client.register_queue(:echo)
116
+ client.register_message(:echo)
117
+ assert_equal TestDaemons::Redis[redis_name].ip_with_port, client.rpc(:echo, 'nil').second
118
+ end
119
+
120
+ Then /^a system notification for "([^\"]*)" not being available should be sent$/ do |redis_name|
121
+ text = "Redis master '#{TestDaemons::Redis[redis_name].ip_with_port}' not available"
122
+ assert_match /#{text}/, File.readlines(system_notification_log_path).last
123
+ end
124
+
125
+ Then /^a system notification for switching from "([^\"]*)" to "([^\"]*)" should be sent$/ do |old_redis_master_name, new_redis_master_name|
126
+ text = "Setting redis master to '#{TestDaemons::Redis[new_redis_master_name].ip_with_port}' (was '#{TestDaemons::Redis[old_redis_master_name].ip_with_port}')"
127
+ assert_match /#{Regexp.escape(text)}/, File.read(system_notification_log_path)
128
+ end
129
+
130
+ Then /^a system notification for no slave available to become new master should be sent$/ do
131
+ text = "Redis master could not be switched, no slave available to become new master"
132
+ assert_match /#{text}/, File.readlines(system_notification_log_path).last
133
+ end
@@ -0,0 +1,32 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "daemons"
5
+ require "optparse"
6
+ require File.expand_path("../../lib/beetle", File.dirname(__FILE__))
7
+
8
+ tmp_path = File.expand_path("../../tmp", File.dirname(__FILE__))
9
+
10
+ Daemons.run_proc("beetle_handler", :log_output => true, :dir_mode => :normal, :dir => tmp_path) do
11
+ opts = OptionParser.new
12
+
13
+ opts.on("-f", "--redis-master-file path", String) do |val|
14
+ Beetle.config.redis_server = val
15
+ end
16
+
17
+ opts.parse!(ARGV - ["start", "--"])
18
+
19
+ Beetle.config.servers = "localhost:5672" # rabbitmq
20
+
21
+ # set Beetle log level to info, less noisy than debug
22
+ Beetle.config.logger.level = Logger::INFO
23
+
24
+ client = Beetle::Client.new.configure :auto_delete => true do |config|
25
+ config.queue(:echo)
26
+ config.message(:echo)
27
+ config.handler(:echo) {|message| client.deduplication_store.redis.server rescue "no redis master"}
28
+ end
29
+ client.listen do
30
+ puts "Started beetle handler"
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../../../lib/beetle', __FILE__)
2
+
3
+ # Allow using Test::Unit for step assertions
4
+ # See http://wiki.github.com/aslakhellesoy/cucumber/using-testunit
5
+ require 'test/unit/assertions'
6
+ World(Test::Unit::Assertions)
7
+
8
+ Before do
9
+ `ruby features/support/system_notification_logger start`
10
+ end
11
+
12
+ After do
13
+ cleanup_test_env
14
+ end
15
+
16
+ at_exit do
17
+ cleanup_test_env
18
+ end
19
+
20
+ def cleanup_test_env
21
+ TestDaemons::RedisConfigurationClient.stop_all
22
+ TestDaemons::RedisConfigurationServer.stop
23
+
24
+ `ruby features/support/beetle_handler stop`
25
+ redis_master_files = tmp_path + "/redis-master-*"
26
+ `rm -f #{redis_master_files}`
27
+
28
+ `ruby features/support/system_notification_logger stop`
29
+ `rm -f #{system_notification_log_path}`
30
+
31
+ TestDaemons::Redis.stop_all
32
+ end
33
+
34
+ def redis_master_file(client_name)
35
+ tmp_path + "/redis-master-#{client_name}"
36
+ end
37
+
38
+ def first_redis_configuration_client_pid
39
+ File.read("redis_configuration_client0.pid").chomp.to_i
40
+ end
41
+
42
+ def system_notification_log_path
43
+ tmp_path + "/system_notifications.log"
44
+ end
45
+
46
+ def tmp_path
47
+ File.expand_path("../../../tmp", __FILE__)
48
+ end
@@ -0,0 +1,31 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "daemons"
5
+ require File.expand_path("../../lib/beetle", File.dirname(__FILE__))
6
+
7
+ tmp_path = File.expand_path("../../tmp", File.dirname(__FILE__))
8
+ system_notification_log_file_path = "#{tmp_path}/system_notifications.log"
9
+
10
+ Daemons.run_proc("system_notification_logger", :log_output => true, :dir_mode => :normal, :dir => tmp_path) do
11
+ Beetle.config.servers = "localhost:5672, localhost:5673" # rabbitmq
12
+
13
+ # set Beetle log level to info, less noisy than debug
14
+ Beetle.config.logger.level = Logger::DEBUG
15
+
16
+ client = Beetle::Client.new
17
+ client.configure :exchange => :system, :auto_delete => true do |config|
18
+ config.message :system_notification
19
+ config.queue :system_notification
20
+ config.handler :system_notification do |message|
21
+ payload = ActiveSupport::JSON.decode(message.data)
22
+ text = payload["message"]
23
+ puts "Writing message to #{system_notification_log_file_path}: #{text}"
24
+ File.open(system_notification_log_file_path, "a+") do |f|
25
+ f << text
26
+ end
27
+ end
28
+ end
29
+ puts "Started system notification logger"
30
+ client.listen
31
+ end
@@ -0,0 +1,189 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile <%= pid_file %>
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port <%= port %>
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Set server verbosity to 'debug'
23
+ # it can be one of:
24
+ # debug (a lot of information, useful for development/testing)
25
+ # notice (moderately verbose, what you want in production probably)
26
+ # warning (only very important / critical messages are logged)
27
+ loglevel debug
28
+
29
+ # Specify the log file name. Also 'stdout' can be used to force
30
+ # the demon to log on the standard output. Note that if you use standard
31
+ # output for logging but daemonize, logs will be sent to /dev/null
32
+ logfile <%= log_file %>
33
+
34
+ # Set the number of databases. The default database is DB 0, you can select
35
+ # a different one on a per-connection basis using SELECT <dbid> where
36
+ # dbid is a number between 0 and 'databases'-1
37
+ databases 16
38
+
39
+ ################################ SNAPSHOTTING #################################
40
+ #
41
+ # Save the DB on disk:
42
+ #
43
+ # save <seconds> <changes>
44
+ #
45
+ # Will save the DB if both the given number of seconds and the given
46
+ # number of write operations against the DB occurred.
47
+ #
48
+ # In the example below the behaviour will be to save:
49
+ # after 900 sec (15 min) if at least 1 key changed
50
+ # after 300 sec (5 min) if at least 10 keys changed
51
+ # after 60 sec if at least 10000 keys changed
52
+ save 900 1
53
+ save 300 10
54
+ save 60 10000
55
+
56
+ # Compress string objects using LZF when dump .rdb databases?
57
+ # For default that's set to 'yes' as it's almost always a win.
58
+ # If you want to save some CPU in the saving child set it to 'no' but
59
+ # the dataset will likely be bigger if you have compressible values or keys.
60
+ rdbcompression yes
61
+
62
+ # The filename where to dump the DB
63
+ dbfilename dump.rdb
64
+
65
+ # For default save/load DB in/from the working directory
66
+ # Note that you must specify a directory not a file name.
67
+ dir <%= dir %>
68
+
69
+ ################################# REPLICATION #################################
70
+
71
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
72
+ # another Redis server. Note that the configuration is local to the slave
73
+ # so for example it is possible to configure the slave to save the DB with a
74
+ # different interval, or to listen to another port, and so on.
75
+ #
76
+ # slaveof <masterip> <masterport>
77
+
78
+ # If the master is password protected (using the "requirepass" configuration
79
+ # directive below) it is possible to tell the slave to authenticate before
80
+ # starting the replication synchronization process, otherwise the master will
81
+ # refuse the slave request.
82
+ #
83
+ # masterauth <master-password>
84
+
85
+ ################################## SECURITY ###################################
86
+
87
+ # Require clients to issue AUTH <PASSWORD> before processing any other
88
+ # commands. This might be useful in environments in which you do not trust
89
+ # others with access to the host running redis-server.
90
+ #
91
+ # This should stay commented out for backward compatibility and because most
92
+ # people do not need auth (e.g. they run their own servers).
93
+ #
94
+ # requirepass foobared
95
+
96
+ ################################### LIMITS ####################################
97
+
98
+ # Set the max number of connected clients at the same time. By default there
99
+ # is no limit, and it's up to the number of file descriptors the Redis process
100
+ # is able to open. The special value '0' means no limts.
101
+ # Once the limit is reached Redis will close all the new connections sending
102
+ # an error 'max number of clients reached'.
103
+ #
104
+ # maxclients 128
105
+
106
+ # Don't use more memory than the specified amount of bytes.
107
+ # When the memory limit is reached Redis will try to remove keys with an
108
+ # EXPIRE set. It will try to start freeing keys that are going to expire
109
+ # in little time and preserve keys with a longer time to live.
110
+ # Redis will also try to remove objects from free lists if possible.
111
+ #
112
+ # If all this fails, Redis will start to reply with errors to commands
113
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
114
+ # to reply to most read-only commands like GET.
115
+ #
116
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
117
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
118
+ # database the memory usage will grow over the weeks, it will be obvious if
119
+ # it is going to use too much memory in the long run, and you'll have the time
120
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
121
+ # errors for write operations, and this may even lead to DB inconsistency.
122
+ #
123
+ # maxmemory <bytes>
124
+
125
+ ############################## APPEND ONLY MODE ###############################
126
+
127
+ # By default Redis asynchronously dumps the dataset on disk. If you can live
128
+ # with the idea that the latest records will be lost if something like a crash
129
+ # happens this is the preferred way to run Redis. If instead you care a lot
130
+ # about your data and don't want to that a single record can get lost you should
131
+ # enable the append only mode: when this mode is enabled Redis will append
132
+ # every write operation received in the file appendonly.log. This file will
133
+ # be read on startup in order to rebuild the full dataset in memory.
134
+ #
135
+ # Note that you can have both the async dumps and the append only file if you
136
+ # like (you have to comment the "save" statements above to disable the dumps).
137
+ # Still if append only mode is enabled Redis will load the data from the
138
+ # log file at startup ignoring the dump.rdb file.
139
+ #
140
+ # The name of the append only file is "appendonly.log"
141
+ #
142
+ # IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
143
+ # log file in background when it gets too big.
144
+
145
+ appendonly yes
146
+
147
+ # The fsync() call tells the Operating System to actually write data on disk
148
+ # instead to wait for more data in the output buffer. Some OS will really flush
149
+ # data on disk, some other OS will just try to do it ASAP.
150
+ #
151
+ # Redis supports three different modes:
152
+ #
153
+ # no: don't fsync, just let the OS flush the data when it wants. Faster.
154
+ # always: fsync after every write to the append only log . Slow, Safest.
155
+ # everysec: fsync only if one second passed since the last fsync. Compromise.
156
+ #
157
+ # The default is "always" that's the safer of the options. It's up to you to
158
+ # understand if you can relax this to "everysec" that will fsync every second
159
+ # or to "no" that will let the operating system flush the output buffer when
160
+ # it want, for better performances (but if you can live with the idea of
161
+ # some data loss consider the default persistence mode that's snapshotting).
162
+
163
+ # appendfsync always
164
+ appendfsync everysec
165
+ # appendfsync no
166
+
167
+ ############################### ADVANCED CONFIG ###############################
168
+
169
+ # Glue small output buffers together in order to send small replies in a
170
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
171
+ # in terms of number of queries per second. Use 'yes' if unsure.
172
+ glueoutputbuf yes
173
+
174
+ # Use object sharing. Can save a lot of memory if you have many common
175
+ # string in your dataset, but performs lookups against the shared objects
176
+ # pool so it uses more CPU and can be a bit slower. Usually it's a good
177
+ # idea.
178
+ #
179
+ # When object sharing is enabled (shareobjects yes) you can use
180
+ # shareobjectspoolsize to control the size of the pool used in order to try
181
+ # object sharing. A bigger pool size will lead to better sharing capabilities.
182
+ # In general you want this value to be at least the double of the number of
183
+ # very common strings you have in your dataset.
184
+ #
185
+ # WARNING: object sharing is experimental, don't enable this feature
186
+ # in production before of Redis 1.0-stable. Still please try this feature in
187
+ # your development environment so that we can test it better.
188
+ shareobjects no
189
+ shareobjectspoolsize 1024
@@ -0,0 +1,186 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'erb'
4
+ require 'redis'
5
+ require 'lib/beetle/redis_ext'
6
+ require 'daemon_controller'
7
+
8
+ module TestDaemons
9
+ class Redis
10
+
11
+ @@instances = {}
12
+ @@next_available_port = 6381
13
+
14
+ attr_reader :name, :port
15
+
16
+ def initialize(name)
17
+ @name = name
18
+ @port = @@next_available_port
19
+
20
+ @@next_available_port += 1
21
+ @@instances[name] = self
22
+ end
23
+
24
+ class << self
25
+ def find_or_initialize_by_name(name)
26
+ @@instances[name] ||= new(name)
27
+ end
28
+ alias_method :[], :find_or_initialize_by_name
29
+
30
+ def stop_all
31
+ @@instances.values.each{|i| i.stop}
32
+ end
33
+ end
34
+
35
+ def start
36
+ create_dir
37
+ create_config
38
+ daemon_controller.start
39
+ end
40
+
41
+ def restart(delay=1)
42
+ redis.shutdown rescue Errno::ECONNREFUSED
43
+ sleep delay
44
+ `redis-server #{config_filename}`
45
+ end
46
+
47
+ def stop
48
+ # TODO: Might need to be moved into RedisConfigurationServer
49
+ # 10.times do
50
+ # break if (redis.info["bgsave_in_progress"]) == 0 rescue false
51
+ # sleep 1
52
+ # end
53
+ daemon_controller.stop
54
+ ensure
55
+ cleanup
56
+ end
57
+
58
+ def cleanup
59
+ remove_dir
60
+ remove_config
61
+ remove_pid_file
62
+ end
63
+
64
+ # TODO: The retry logic must be moved into RedisConfigurationServer
65
+ def master
66
+ tries = 0
67
+ begin
68
+ redis.master!
69
+ rescue Errno::ECONNREFUSED, Errno::EAGAIN
70
+ puts "master role setting for #{name} failed: #{$!}"
71
+ sleep 1
72
+ retry if (tries+=1) > 5
73
+ raise "could not setup master #{name} #{$!}"
74
+ end
75
+ end
76
+
77
+ def running?
78
+ cmd = "ps aux | grep 'redis-server #{config_filename}' | grep -v grep"
79
+ res = `#{cmd}`
80
+ x = res.chomp.split("\n")
81
+ x.size == 1
82
+ end
83
+
84
+ def available?
85
+ redis.available?
86
+ end
87
+
88
+ def master?
89
+ redis.master?
90
+ end
91
+
92
+ def slave?
93
+ redis.slave?
94
+ end
95
+
96
+ # TODO: Move to redis_ext
97
+ def slave_of(master_port)
98
+ tries = 0
99
+ begin
100
+ redis.slave_of!("127.0.0.1", master_port)
101
+ rescue Errno::ECONNREFUSED, Errno::EAGAIN
102
+ puts "slave role setting for #{name} failed: #{$!}"
103
+ sleep 1
104
+ retry if (tries+=1) > 5
105
+ raise "could not setup slave #{name}: #{$!}"
106
+ end
107
+ end
108
+
109
+ def ip_with_port
110
+ "127.0.0.1:#{port}"
111
+ end
112
+
113
+ def redis
114
+ @redis ||= ::Redis.new(:host => "127.0.0.1", :port => port)
115
+ end
116
+
117
+ private
118
+
119
+ def create_dir
120
+ FileUtils.mkdir(dir) unless File.exists?(dir)
121
+ end
122
+
123
+ def remove_dir
124
+ FileUtils.rm_r(dir) if File.exists?(dir)
125
+ end
126
+
127
+ def create_config
128
+ File.open(config_filename, "w") do |file|
129
+ file.puts config_content
130
+ end
131
+ end
132
+
133
+ def remove_config
134
+ FileUtils.rm(config_filename) if File.exists?(config_filename)
135
+ end
136
+
137
+ def remove_pid_file
138
+ FileUtils.rm(pid_file) if File.exists?(pid_file)
139
+ end
140
+
141
+ def tmp_path
142
+ File.expand_path(File.dirname(__FILE__) + "/../../../tmp")
143
+ end
144
+
145
+ def config_filename
146
+ tmp_path + "/redis-test-server-#{name}.conf"
147
+ end
148
+
149
+ def config_content
150
+ template = ERB.new(File.read(config_template_filename))
151
+ template.result(binding)
152
+ end
153
+
154
+ def config_template_filename
155
+ File.dirname(__FILE__) + "/redis.conf.erb"
156
+ end
157
+
158
+ def pid_file
159
+ tmp_path + "/redis-test-server-#{name}.pid"
160
+ end
161
+
162
+ def pid
163
+ File.read(pid_file).chomp.to_i
164
+ end
165
+
166
+ def log_file
167
+ tmp_path + "/redis-test-server-#{name}.log"
168
+ end
169
+
170
+ def dir
171
+ tmp_path + "/redis-test-server-#{name}/"
172
+ end
173
+
174
+ def daemon_controller
175
+ @daemon_controller ||= DaemonController.new(
176
+ :identifier => "Redis test server",
177
+ :start_command => "redis-server #{config_filename}",
178
+ :ping_command => lambda { running? && available? },
179
+ :pid_file => pid_file,
180
+ :log_file => log_file,
181
+ :start_timeout => 5
182
+ )
183
+ end
184
+
185
+ end
186
+ end