Skip to content
This repository has been archived by the owner on Jan 5, 2022. It is now read-only.
shaneharter edited this page Aug 3, 2011 · 20 revisions

PHP Daemon Implementation Q&A

NOTE: This applies to v1.0.1

An updated version of this guide for the v1.1.0 version is forthcoming.

What Do I Do First?

The Example daemon in /App uses a config.php file that defines an autoloader and other settings. The only external class dependency that Core_Daemon has is on Core_Memcache. If you include that daemon will be satisfied. The other important file in the /App directory is error_handlers.php. You can use whatever error handling strategy you'd like, as long as you include an error handler, an uncaught exception handler, and a shutdown function. The point here is that errors do happen and this daemon needs to be as solid as possible and when it crashes it needs to do so loudly.

From there, if you look at the Example daemon you'll get a quick idea of all you need to do to write a daemon. Specifically:

In the Constructor:

  1. Set a Loop Interval
  2. Set a Log File name, or create a log_file() method in your class.
  3. Set a Config File name (and ensure that config file exists)
  4. Add at least one entry to the memcache_servers array.
  5. Call the parent constructor

In the Setup method:

  1. The base class defines an abstract setup() method so you have to create it. But it can be empty.
  2. If your daemon uses a DB connection, etc, this is where it goes.

**In the Execute method: **

  1. The base class defines an abstract execute() method so you have to create it.
  2. This is where you begin your application. The actual work of your daemon begins here. In most of our production daemons, we use many classes and libraries, and the execute() method is just a few lines to bootstrap and run them.
  3. NOTE: If you've developed a daemon before, you know that you begin with a while(true) loop. This is why your application stays running. Only when you break that loop for some reason -- an error, a Kill signal -- does it stop. REMEMBER, an important design feature of this library is that it provides the while() loop. The execute() method is called INSIDE the while loop. If you create your own while(true) loop inside the execute() method you will lose nearly every feature this daemon library offers.
  4. So remember, you set the loop interval (in seconds). This is the frequency your daemon will run at. Anything you put in the execute() method will be called at that frequency. It also means that your execute() method needs to run within that allotted time. If it takes longer the daemon will log and report it as an error. If you have long-running tasks, you can use the ->fork() method to parallelize them.

How Can I Control the Run Loop?

You have several options to control/break the run loop from your application code.

  1. Graceful Shutdown. When a kill [pid] signal is sent to your daemon, it will do a graceful shutdown: It will finish the current iteration of the while() loop, run its destructors, and exit cleanly. There is an exception to it: If you've used the fork() method to create child processes, they may continue to run after the daemon has exited. You can Mimic this signal by calling $this->shutdown(true).

  2. Exception. You can throw an exception from within execute() that will be caught outside the run loop and will trigger a fatal error.

  3. You can manipulate the loop_frequency. In one production system we wrote the daemon checks an external resource for a new file. This is time intensive. When it detects a new file, it knows that users often work in batches. So it begin checking every few seconds. After a couple minutes that drops down to 5 seconds. Once it's been a couple hours since any activity, it drops 30 seconds. Then eventually down to every 60. You can control the interval however you'd like.

Clone this wiki locally