The embedded Erfurt library contains a background worker implementation using Gearman. This means: OntoWiki and its extensions can handle expensive tasks in the background by calling a job for execution which were registered on the server beforehand.

Now here is how it works and how you can use it:

Server

To make use of Gearman as worker background, you need to install the Gearman service on the server.

Installation

This process depends on the operating system.

RHEL/Fedora
yum install gearmand-server ##### Debian/Ubuntu

apt-get install gearman-job-server
Windows

Please use CYGWIN!

Compilation from archive

At first, download the Gearman [daemon archive][???] and install:

tar xzf gearmand-X.Y.tar.gz
cd gearmand-X.Y
./configure
make
make install

After installation via package management the server already should be running but only listening to localhost.
More on Gearman documentation or by typing gearmand --help.

Client and Worker API for PHP

First install needed libraries - for Debian/Ubuntu this would be:

apt-get install php5-dev php5-cli libgearman6

Now download the archive from PECL.

tar xzf gearman-X.Y.tgz
cd gearman-X.Y
phpize
./configure
make
make install

HINT: If you are having trouble with the version if libgearman, try an older archive (read more).

Test

Console

Open a terminal and create a new worker, which will register a function “wc” which will count list items of given data.

gearman -w -f wc -- wc -l

Open another terminal and call the worker:

gearman -f wc < /etc/passwd

… and you should see the number of entries on your passwords file.

PHP example

Server script
<?php
class MyWorker{
	public function reverse( GearmanJob $job ){
		return strrev( $job->workload() );
	}
}
$worker= new GearmanWorker();
$worker->addServer();
$worker->addFunction( "reverse", array( "MyWorker", "reverse" ) );
while( $worker->work() );
Client script
<?php
$client     = new GearmanClient();
$client->addServer();
print($client->do("reverse", "Hello World!"));

Usage in OntoWiki / Erfurt

Classes in Erfurt

Worker_Registry

This class will be started by the server side shell script to start the job server.

It triggers the event onAnnounceWorker and will allow OntoWiki / Erfurt components to state their worker jobs. These will be stored within the registry as a later input for the worker backend.

Worker_Backend

This class is wrapper for the Gearman worker, which runs server side. It knows the worker registry and add the registered jobs to the Gearman server. Afterwards the server side worker script will set the backend and Gearman server to listen mode.

While this is the empty engine for handling job calls, you will now also need jobs classes to register.

Worker_Job_Interface

Every job class will implement the interface. At the moment you will need to implement the run method by your needs. So every job class only has one public method, which will be called automatically.

Worker_Job_Container

This class is used to store registerable worker jobs within the worker registry. You do not need to use this class at all.

Configuration

Configure in either OntoWiki/application/config/default.ini or OntoWiki/libraries/Erfurt/library/Erfurt/config/default.ini:

worker.enable  = true
worker.backend = "Gearman"
worker.servers = "127.0.0.1:4730"

Fakts: - Gearman is the only worker backend at the moment. - Several servers can be enlisted separated by comma. - You must set the port. Default port is 4730.

Integration in OntoWiki

First register the event onAnnounceWorker in the doap.n3 file of a plugin, module or extension. This is an example for a plugin:

owconfig:pluginEvent event:onAnnounceWorker ;

Within the plugin class implement:

public function onAnnounceWorker($event)
{
	$event->registry->registerJob(
		"myJobName",                                    //  job key name
		"extensions/myPlugin/jobs/MyJobName.php",       //  job class file
		"MyPlugin_Job_MyJobName"                        //  job class name
	);
}

The Erfurt worker backend will register your job class once it is started.

Now you need to implement your job class. Here is a simple example:

class MyPlugin_Job_MyJobName extends Erfurt_Worker_Job_Abstract
{
    public function run( $workload ){
        if (empty($workload)) {
            $this->logSuccess('MyPlugin_Job_MyJobName started (without workload)');
        } else {
            $this->logSuccess('MyPlugin_Job_MyJobName started');
            return strrev($workload);  //  reverse string and return
    }
}

Worker execution

On the server

Go into OntoWiki’s base folder and run the worker script:

cd OntoWiki
application/shell.worker.php &

Please keep in mind that this script will not quit since it will listen for new job calls. Therefore the script is told to run in background (by the ampersand).

To stop or restart the worker, please kill the process and start the script again.

Hint: For job accessing filesystem resources, it is important to run the script as a user which has access to the desired resources.

On the client

You can call jobs for execution with this one-liner:

OntoWiki::getInstance()->callJob("MyJobId", "MyPayloadData");

Jobs also can call other jobs. An example job is available (and registered as ‘test’) in Erfurts repository.

Tags: ontowiki