daemon_controller 1.2.0 → 3.0.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZTczYjIwNTI5YjU3OTZmN2YyNzY0ZmYzOGE0MjA2YjJkNDE3OTZjYQ==
5
- data.tar.gz: !binary |-
6
- MTUyNDIxMmExMmNlMTFjOWQ1ZjVhODdmM2ExOTUwMTQ2YTk0MjM2MQ==
2
+ SHA256:
3
+ metadata.gz: bd4f2d08b82c7340e6b00c8a97e63f66a6677fbc28e9b705ecb6c53d75701e00
4
+ data.tar.gz: 11bc6d68d7837db49c123b5e2b08fc932bf60c1b0c29742e7e891e66d8f4f82a
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NjdlNDgzYWVhNDg4NDQwMGFhMjM2Mjg3Njg2NTkyN2U1ZThiOTM0MjRjNmNl
10
- ODBmMGQxMWIwYTc3ZmRlYTJlZmQwNGNiOGQ1MmZiNDE2MzI1NTFjZGY3NjE3
11
- MWQ1ZjExYzc1ZTI2MDM3YTc2ZjhhZjJmMGFkZDZkMTY2NTQzYmI=
12
- data.tar.gz: !binary |-
13
- ZWI1NmQ1Y2U5NjRlZGUxZDE0ODA3NTMwMDQ2NWM5NjlkMjYxZTgxYTFkYTA2
14
- ZWY2NjUxYjczZTQ5YWJjODM1MWZlODQxY2UyOTc2M2I5NjVmOGUwNTZmMWNl
15
- MGZkZTUwODg0NDFjNmU2MzZlODI2ZTZhZmZiMmYwYjEwMWQ1ZDg=
6
+ metadata.gz: c29f7ea6b92d607774bef4f42dba2e03215f85078079fb3febd404cf87efff8f0536e03ba870234c72925f7404142dba2bf73217d7586175328d6611ba72e3d8
7
+ data.tar.gz: 1b5d67e7165fb4c2ba1c667c774e089a5a5029e57ba47dd1f91cbcd17e2dcdef7136947b0d115d71b7db9c154013043f9da01428d55659898eee198bd1ca3d3a
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2014 Phusion
1
+ Copyright (c) 2008-2025 Asynchronous B.V.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -17,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
17
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  THE SOFTWARE.
20
-
@@ -12,11 +12,11 @@ It provides the following functionality:
12
12
  * Starting daemons. If the daemon fails to start then an exception will be
13
13
  raised. *daemon_controller* can even detect failures that occur after the
14
14
  daemon has already daemonized.
15
-
15
+
16
16
  Starting daemons is done in a race-condition-free manner. If another
17
17
  process using *daemon_controller* is trying to start the same daemon,
18
18
  then *daemon_controller* will guarantee serialization.
19
-
19
+
20
20
  *daemon_controller* also raises an exception if it detects that the daemon
21
21
  is already started.
22
22
  * Connecting to a daemon, starting it if it's not already started. This too
@@ -25,53 +25,11 @@ It provides the following functionality:
25
25
  * Stopping daemons.
26
26
  * Checking whether a daemon is running.
27
27
 
28
- ## Installation with RubyGems
29
-
30
- gem install daemon_controller
31
-
32
- This gem is signed using PGP with the [Phusion Software Signing key](http://www.phusion.nl/about/gpg). That key in turn is signed by [the rubygems-openpgp Certificate Authority](http://www.rubygems-openpgp-ca.org/).
33
-
34
- You can verify the authenticity of the gem by following [The Complete Guide to Verifying Gems with rubygems-openpgp](http://www.rubygems-openpgp-ca.org/blog/the-complete-guide-to-verifying-gems-with-rubygems-openpgp.html).
35
-
36
- ## Installation on Ubuntu
37
-
38
- Use our [PPA](https://launchpad.net/~phusion.nl/+archive/misc):
39
-
40
- sudo add-apt-repository ppa:phusion.nl/misc
41
- sudo apt-get update
42
- sudo apt-get install ruby-daemon-controller
43
-
44
- ## Installation on Debian
45
-
46
- Our Ubuntu Lucid packages are compatible with Debian 6.
28
+ ## Installation
47
29
 
48
- sudo sh -c 'echo deb http://ppa.launchpad.net/phusion.nl/misc/ubuntu lucid main > /etc/apt/sources.list.d/phusion-misc.list'
49
- sudo sh -c 'echo deb-src http://ppa.launchpad.net/phusion.nl/misc/ubuntu lucid main >> /etc/apt/sources.list.d/phusion-misc.list'
50
- sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 2AC745A50A212A8C
51
- sudo apt-get update
52
- sudo apt-get install ruby-daemon-controller
53
-
54
- ## Installation on RHEL, CentOS and Amazon Linux
55
-
56
- Enable our YUM repository:
57
-
58
- # RHEL 6, CentOS 6
59
- curl -L https://oss-binaries.phusionpassenger.com/yumgems/phusion-misc/el.repo | \
60
- sudo tee /etc/yum.repos.d/phusion-misc.repo
61
-
62
- # Amazon Linux
63
- curl -L https://oss-binaries.phusionpassenger.com/yumgems/phusion-misc/amazon.repo | \
64
- sudo tee /etc/yum.repos.d/phusion-misc.repo
65
-
66
- Install our package:
67
-
68
- sudo yum install rubygem-daemon_controller
69
-
70
- ## Resources
71
-
72
- * [Website](https://github.com/FooBarWidget/daemon_controller)
73
- * [RDoc](http://rdoc.info/projects/FooBarWidget/daemon_controller)
74
- * [Git repository](git://github.com/FooBarWidget/daemon_controller.git)
30
+ ```bash
31
+ gem install daemon_controller
32
+ ```
75
33
 
76
34
 
77
35
  What is it for?
@@ -123,13 +81,15 @@ daemon varies. We've observed that waiting a fixed amount of time is by far the
123
81
  most common way. For example, UltraSphinx's daemon starting code looks like
124
82
  this:
125
83
 
126
- system "searchd --config '#{Ultrasphinx::CONF_PATH}'"
127
- sleep(4) # give daemon a chance to write the pid file
128
- if ultrasphinx_daemon_running?
129
- say "started successfully"
130
- else
131
- say "failed to start"
132
- end
84
+ ```ruby
85
+ system "searchd --config '#{Ultrasphinx::CONF_PATH}'"
86
+ sleep(4) # give daemon a chance to write the pid file
87
+ if ultrasphinx_daemon_running?
88
+ say "started successfully"
89
+ else
90
+ say "failed to start"
91
+ end
92
+ ```
133
93
 
134
94
  This is in no way a slam against UltraSphinx. However, if the daemon starts in
135
95
  200 miliseconds, then the user who issued the start command will be waiting for
@@ -168,11 +128,11 @@ From the problem descriptions, it would become apparent that our wishlist is as
168
128
  follows. Why is this wishlist often not implemented? Let's go over them.
169
129
 
170
130
  - **A daemon should be automatically started on demand, instead of requiring the user to manually start it.**
171
-
131
+
172
132
  The most obvious problems are related to concurrency. Suppose that your web
173
133
  application has a search box, and you want to start the search daemon if it
174
134
  isn't already started, then connect to. Two problems will arise:
175
-
135
+
176
136
  * Suppose that Rails process A is still starting the daemon. At the same
177
137
  time, another visitor tries to search something, and Rails process B
178
138
  notices that the daemon is not running. If B tries to start the daemon
@@ -183,24 +143,24 @@ follows. Why is this wishlist often not implemented? Let's go over them.
183
143
  start. For example, if you wait 2 seconds, then try to connect to the
184
144
  daemon, and the daemon isn't done initializing yet, then it will seem as
185
145
  if the daemon failed to start.
186
-
146
+
187
147
  These are the most probable reasons why people don't try to write
188
148
  auto-starting code, and instead require the user to start the daemon
189
149
  manually.
190
-
150
+
191
151
  These problems, as well as several less obvious problems, are closely
192
152
  related to the next few points.
193
-
153
+
194
154
  - **The daemon starter must wait until the daemon is done initializing, no longer and no shorter**
195
-
155
+
196
156
  Because only after the daemon is fully initialized, is it safe to connect
197
157
  to it. And because the user should not have to wait longer than he really
198
158
  has to. During startup, the daemon will have to be continuously checked
199
159
  whether it's done initializing or whether an error occured. Writing this
200
160
  code can be quite a hassle, which is why most people don't do it.
201
-
161
+
202
162
  - **The daemon starter must report any startup errors**
203
-
163
+
204
164
  If the daemon starting command - e.g. `sphinx -c config_file.conf`,
205
165
  `apachectl start` or `mongrel_rails cluster::start` - reports startup
206
166
  errors, then all is fine as long as the user is starting the command from a
@@ -208,16 +168,16 @@ follows. Why is this wishlist often not implemented? Let's go over them.
208
168
  already gone into the background. Such errors are only reported to the log
209
169
  file.
210
170
  *The daemon starter should also check the log file for any startup errors.*
211
-
171
+
212
172
  Furthermore, it should be able to raise startup errors as exceptions. This
213
173
  allows the the application to decide what to do with the error. For less
214
174
  experienced system administrators, the error might be displayed in the
215
175
  browser, allowing the administrators to become aware of the problem without
216
176
  forcing them to manually check the log files. Or the error might be emailed
217
177
  to a system administrator's email address.
218
-
178
+
219
179
  - **The daemon starter must be able to correct stale or corrupted PID files**
220
-
180
+
221
181
  If the PID file is stale, or for some reason has been corrupted, then the
222
182
  daemon starter must be able to cope with that.
223
183
  *It should check whether the PID file contains a valid PID, and whether the PID exists.*
@@ -292,28 +252,28 @@ or [God](http://god.rubyforge.org/). Rather, it is a solution to the following
292
252
  problem:
293
253
 
294
254
  > **Hongli:** hey Ninh, do a 'git pull', I just implemented awesome searching
295
- > features in our application!
296
- > **Ninh:** cool. *pulls from repository*
297
- > **Ninh:** hey Hongli, it doesn't work.
298
- > **Hongli:** what do you mean, it doesn't work?
299
- > **Ninh:** it says "connection refused", or something
255
+ > features in our application!
256
+ > **Ninh:** cool. *pulls from repository*
257
+ > **Ninh:** hey Hongli, it doesn't work.
258
+ > **Hongli:** what do you mean, it doesn't work?
259
+ > **Ninh:** it says "connection refused", or something
300
260
  > **Hongli:** oh I forgot to mention it, you have to run the Sphinx search
301
261
  > daemon before it works. type "rake sphinx:daemon:start" to do
302
- > that
262
+ > that
303
263
  > **Ninh:** great. but now I get a different error. something about
304
- > BackgrounDRb.
264
+ > BackgrounDRb.
305
265
  > **Hongli:** oops, I forgot to mention this too. you need to start the
306
- > BackgrounDRb server with "rake backgroundrb:start_server"
266
+ > BackgrounDRb server with "rake backgroundrb:start_server"
307
267
  > **Ninh:** okay, so every time I want to use this app, I have to type
308
268
  > "rake sphinx:daemon:start", "rake backgroundrb:start_server" and
309
- > "./script/server"?
269
+ > "./script/server"?
310
270
  > **Hongli:** yep
311
271
 
312
272
  Imagine the above conversation becoming just:
313
273
 
314
274
  > **Hongli:** hey Ninh, do a 'git pull', I just implemented awesome searching
315
- > features in our application!
316
- > **Ninh:** cool. *pulls from repository*
275
+ > features in our application!
276
+ > **Ninh:** cool. *pulls from repository*
317
277
  > **Ninh:** awesome, it works!
318
278
 
319
279
  This is not something that can be achieved with Monit/God. Monit/God are for
@@ -327,7 +287,7 @@ without having to start the daemons manually.
327
287
  Tutorial #1: controlling Apache
328
288
  ===============================
329
289
 
330
- Suppose that you're a [Phusion Passenger](http://www.modrails.com/) developer,
290
+ Suppose that you're a [Phusion Passenger](https://www.phusionpasseenger.com/) developer,
331
291
  and you need to write tests for the Apache module. In particular, you want to
332
292
  test whether the different Phusion Passenger configuration directives are
333
293
  working as expected. Obviously, to test the Apache module, the Apache web
@@ -342,29 +302,30 @@ server must be running. For every test, you will want the unit test suite to:
342
302
 
343
303
  That can be done with the following code:
344
304
 
345
- require 'daemon_controller'
346
-
347
- File.open("apache.conf", "w") do |f|
348
- f.write("PidFile apache.pid\n")
349
- f.write("LogFile apache.log\n")
350
- f.write("Listen 1234\n")
351
- f.write(... other relevant configuration options ...)
352
- end
353
-
354
- controller = DaemonController.new(
355
- :identifier => 'Apache web server',
356
- :start_command => 'apachectl -f apache.conf -k start',
357
- :ping_command => [:tcp, 'localhost', 1234],
358
- :pid_file => 'apache.pid',
359
- :log_file => 'apache.log',
360
- :start_timeout => 25
361
- )
362
- controller.start
363
-
364
- .... apache is now started ....
365
- .... some test code here ....
366
-
367
- controller.stop
305
+ ```ruby
306
+ require "daemon_controller"
307
+
308
+ File.open("apache.conf", "w") do |f|
309
+ f.write("PidFile apache.pid\n")
310
+ f.write("LogFile apache.log\n")
311
+ f.write("Listen 1234\n")
312
+ f.write(... other relevant configuration options ...)
313
+ end
314
+
315
+ controller = DaemonController.new(
316
+ identifier: "Apache web server",
317
+ start_command: "apachectl -f apache.conf -k start",
318
+ ping_command: [:tcp, "localhost", 1234],
319
+ pid_file: "apache.pid",
320
+ log_file: "apache.log"
321
+ )
322
+ controller.start
323
+
324
+ # .... apache is now started ....
325
+ # .... some test code here ....
326
+
327
+ controller.stop
328
+ ```
368
329
 
369
330
  The `File.open` line is obvious: it writes the relevant Apache configuration
370
331
  file.
@@ -372,8 +333,8 @@ file.
372
333
  The next line is for creating a new DaemonController object. We pass a
373
334
  human-readable identifier for this daemon ("Apache web server") to the
374
335
  constructor. This is used for generating friendlier error messages.
375
- We also tell it how Apache is supposed to be started (`:start_command`), how to
376
- check whether it can be connected to (`:ping_command`), and where its PID file
336
+ We also tell it how Apache is supposed to be started (`start_command:`), how to
337
+ check whether it can be connected to (`ping_command:`), and where its PID file
377
338
  and log file is. If Apache failed with an error during startup, then it will be
378
339
  reported. If Apache failed with an error after it has gone into the background,
379
340
  then that will be reported too: the given log file is monitored for new error
@@ -381,7 +342,8 @@ messages.
381
342
  Finally, a timeout of 25 seconds is given. If Apache doesn't start within 25
382
343
  seconds, then an exception will be raised.
383
344
 
384
- The ping command is just a `Proc` which returns true or false. If the Proc
345
+ The ping command specifies which socket to connect to in order to check whether
346
+ the daemon is ready. It can also be a `Proc` which returns true or false. If the Proc
385
347
  raises `Errno::ECONNREFUSED`, then that's also interpreted by DaemonController
386
348
  as meaning that the daemon isn't responding yet.
387
349
 
@@ -428,41 +390,43 @@ isn't running.
428
390
 
429
391
  This can be achieved with the following code:
430
392
 
431
- require 'daemon_controller'
432
-
433
- class SearchServer
434
- SEARCH_SERVER_PORT = 1234
435
-
436
- def initialize
437
- @controller = DaemonController.new(
438
- :identifier => 'Sphinx search server',
439
- :start_command => "searchd -c config/sphinx.conf",
440
- :before_start => method(:before_start),
441
- :ping_command => [:tcp, 'localhost', SEARCH_SERVER_PORT],
442
- :pid_file => 'tmp/pids/sphinx.pid',
443
- :log_file => 'log/sphinx.log')
444
- end
445
-
446
- def query(search_terms)
447
- socket = @controller.connect do
448
- TCPSocket.new('localhost', SEARCH_SERVER_PORT)
449
- end
450
- send_query(socket, search_terms)
451
- return retrieve_results(socket)
452
- end
453
-
454
- private
455
- def before_start
456
- generate_configuration_file
457
- if !index_exists?
458
- generate_index
459
- end
460
- end
461
-
462
- ...
393
+ ```ruby
394
+ require "daemon_controller"
395
+
396
+ class SearchServer
397
+ SEARCH_SERVER_PORT = 1234
398
+
399
+ def initialize
400
+ @controller = DaemonController.new(
401
+ identifier: "Sphinx search server",
402
+ start_command: "searchd -c config/sphinx.conf",
403
+ before_start: method(:before_start),
404
+ ping_command: [:tcp, "localhost", SEARCH_SERVER_PORT],
405
+ pid_file: "tmp/pids/sphinx.pid",
406
+ log_file: "log/sphinx.log")
407
+ end
408
+
409
+ def query(search_terms)
410
+ socket = @controller.connect do
411
+ TCPSocket.new("localhost", SEARCH_SERVER_PORT)
412
+ end
413
+ send_query(socket, search_terms)
414
+ retrieve_results(socket)
415
+ end
416
+
417
+ private
418
+ def before_start
419
+ generate_configuration_file
420
+ if !index_exists?
421
+ generate_index
463
422
  end
423
+ end
464
424
 
465
- Notice the `:before_start` option. We pass a block of code which is to be run,
425
+ # ...
426
+ end
427
+ ```
428
+
429
+ Notice the `before_start:` option. We pass a block of code which is to be run,
466
430
  just before the daemon is started. This block, along with starting the daemon,
467
431
  is completely serialized. That is, if you're inside the block, then it's
468
432
  guaranteed that no other process is running this block at the same time as well.
@@ -506,11 +470,11 @@ synchronization. This has a few implications:
506
470
  Multiple threads can safely use daemon_controller concurrently. Multiple
507
471
  processes can safely use daemon_controller concurrently. There will be no
508
472
  race conditions.
509
-
473
+
510
474
  However `flock()` is not implemented on Solaris. daemon_controller, if
511
475
  used in MRI does not currently work on Solaris. You need to use JRuby
512
476
  which does not use `flock()` to implement `File#flock`.
513
-
477
+
514
478
  * On JRuby `File#flock` is implemented through the Java file locking API,
515
479
  which on Unix is implemented with the `fcntl()` system calls. This is a
516
480
  different kind of lock with very strange semantics.
@@ -524,7 +488,7 @@ synchronization. This has a few implications:
524
488
  cannot be used to synchronize threads. If a thread has obtained a file
525
489
  lock, then another thread within the same JVM process will not block upon
526
490
  trying to lock the same file.
527
-
491
+
528
492
  In other words, if you're on JRuby then don't concurrently access
529
493
  daemon_controller from multiple threads without manual locking. Also be
530
494
  careful with mixing MRI processes that use daemon_controller with JRuby
@@ -534,5 +498,7 @@ synchronization. This has a few implications:
534
498
  API documentation
535
499
  =================
536
500
 
537
- Detailed API documentation is available in the form of inline comments in
538
- `lib/daemon_controller.rb`.
501
+ Detailed API documentation is available here:
502
+ - [Configuration options](doc/OPTIONS.md)
503
+ - [Stop flow](doc/STOP_FLOW.md)
504
+ - Inline comments in `lib/daemon_controller.rb`.