PHP on the Backend (part 2)

To run the class I posted yesterday, I typically use a class called DaemonRunner. This class sets up for proper signal handling, and ‘executes’ the class extended from Daemon.

declare(ticks=1);

class DaemonRunner {
    public static function exec($className) {
        $argv = $_SERVER['argv'];
        $daemon = new $className($argv);
        $daemon->init();
        while (!$daemon->isDone()) {
            $daemon->run();
        }
        $daemon->shutdown();
    }
}

The first statement is a PHPism. This allows PHP to check for signals every 1 tick. A tick is simply a low-level PHP interpreter step. The way I’ve setup my daemon and signal handling by default, the PHP will finish its current iteration and then quit when receiving a signal. This ensures that the database, and whatever background stuff aren’t left in inconsistent states. As with anything, you’re free to modify, extend, or otherwise alter this behavior.

PHP on the Backend

PHP (or any language for that matter) can just as easily be used as a daemon as on the web. This can be especially useful when solving problems that can’t “complete” in less than 500 ms which one shoots for on the web. As you write an application to handle things such as those mentioned below, be sensitive to the processing, disk space, and time needed to process these requests in planning how to handle these. As an example jobs of a small size might be handled inline by the code that handles the form submission, but for larger jobs it queues them for background processing.

great for background/async processing of:

  • photos
  • movies
  • reports
  • imports of data

advantages:

  • use the same codebase as your app
  • use the same expertise on your team of programmers

challenges:

  • signals
  • one thread
  • memory (this will have to be a whole separate article)
  • starting and stopping

A typical Daemon class I use:

abstract class Daemon {
    protected $done = false;

    public function __construct($argv) {
    }
    public function init() {
        pnctl_signal(SIGTERM, array($this, "onSignal"));
        pnctl_signal(SIGINT, array($this, "onSignal"));

    }
    abstract public function run();
    public function shutdown() {}
    public function isDone() {
        return $this->done;
    }
    public onSignal($signal){
        switch ($signal) {
             case SIGTERM:
             case SIGINT:
                $this->done = true;
                 break;
             default:
                 // handle all other signals
        }
    }
}

As you can see, we’ve started to tackle some of the challenges here. The idea is to handle signals, specifically I usually care about SIGTERM (default when using ‘kill’ on *nix) and SIGINT (from pressing Ctrl-C). Both will cause the program to exit gracefully.

I’ll be posting the class I use to run Daemon’s tomorrow.

TriPUG and MySQL Talk on Memcache and PHP

Memcache is an extension written by Danga for simple Key/Value pair caching for use with your favorite programming language. In this talk I demonstrate how to install, integrate, and leverage Memcache in PHP (using MySQL for a database). I build a sample application, demonstrate less than desirable performance and finally, return performance with a 100x improvement.

The whole talk and its supporting files can also be downloaded.