Author: bicou
Date: 2010-05-16 23:16:50 +0200 (Sun, 16 May 2010)
New Revision: 29486

Added:
   plugins/sfGearmanPlugin/tags/0.9.0/
   plugins/sfGearmanPlugin/tags/0.9.0/LICENSE
   plugins/sfGearmanPlugin/tags/0.9.0/README
   plugins/sfGearmanPlugin/tags/0.9.0/config/
   plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml
   plugins/sfGearmanPlugin/tags/0.9.0/lib/
   plugins/sfGearmanPlugin/tags/0.9.0/package.xml.tmpl
   plugins/sfGearmanPlugin/tags/0.9.0/test/
Removed:
   plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml
   
plugins/sfGearmanPlugin/tags/0.9.0/test/fixtures/project/cache/project_autoload.cache
Log:
[sfGearmanPlugin] tag version 0.9.0

Copied: plugins/sfGearmanPlugin/tags/0.9.0/LICENSE (from rev 29482, 
plugins/sfGearmanPlugin/trunk/LICENSE)
===================================================================
--- plugins/sfGearmanPlugin/tags/0.9.0/LICENSE                          (rev 0)
+++ plugins/sfGearmanPlugin/tags/0.9.0/LICENSE  2010-05-16 21:16:50 UTC (rev 
29486)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin VIELLARD, [email protected]
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Copied: plugins/sfGearmanPlugin/tags/0.9.0/README (from rev 29485, 
plugins/sfGearmanPlugin/trunk/README)
===================================================================
--- plugins/sfGearmanPlugin/tags/0.9.0/README                           (rev 0)
+++ plugins/sfGearmanPlugin/tags/0.9.0/README   2010-05-16 21:16:50 UTC (rev 
29486)
@@ -0,0 +1,407 @@
+sfGearmanPlugin
+===============
+
+The sfGearman plugin provides a symfony wrapper to gearman pecl module.
+
+Features:
+
+* configuration of servers and workers in a yaml config file
+* run workers in a symfony task
+* auto (un)serialization of job workloads/results
+* a simple message queue manager
+* a Doctrine Template to trigger tasks on record/table events
+* a worker for gearman jobs based on MySQL TRIGGER (gearman UDF)
+
+
+Installation
+------------
+
+First you need to install the gearman pecl module, version 0.6.0 minimum.
+
+Then you can install this plugin the usual way (RTFM), or if you want to work 
with the trunk:
+
+    $ cd plugins
+    $ svn co http://svn.symfony-project.com/plugins/sfGearmanPlugin/trunk/ 
sfGearmanPlugin
+
+Then activate the plugin in the `config/ProjectConfiguration.class.php` file.
+
+
+Configuration
+-------------
+
+By default, there is a connection named "default" which targets a local 
gearman server.
+
+Edit or create `config/gearman.yml` to suit your gearman server installation :
+
+    [yml]
+    all:
+      server:
+        default:
+          host: 192.168.0.1
+          port: 4730
+
+You can also use host:port based notation :
+
+    [yml]
+    all:
+      server:
+        default: 127.0.0.1:4730
+
+If you have more than one gearman job server, you can list them and mix 
notations this way :
+
+    [yml]
+    all:
+      server:
+        default:
+          - 192.168.0.1:4730
+          - { host: 192.168.0.2, port: 4730 }
+
+
+Create a worker
+---------------
+
+Edit `config/gearman.yml` to define worker functions and callbacks, grouped by 
a key name :
+
+    [yml]
+    all:
+      worker:
+        example1:
+          reverse: [Worker1, reverse]
+
+We defined a worker named "example1" registering gearman function "reverse" 
with `Worker1::reverse()` callback.
+
+You can register multiple function for one worker :
+
+    [yml]
+    all:
+      worker:
+        example1:
+          reverse: [Worker1, reverse]
+          hash: [Worker1, hash]
+
+
+Next implement you callback:
+
+    [php]
+    /**
+     * Gearman worker example1
+     */
+    class Worker1
+    {
+      /**
+       * reverse work handler
+       *
+       * @param GearmanJob $job Gearman job
+       * @return string         Result sent to client
+       */
+      public static function reverse($job)
+      {
+        return strrev($job->workload());
+      }
+    }
+
+
+To understand `GearmanJob` and `$job->workload()`, read [gearman php module 
documentation](http://php.net/gearman).
+
+To start your worker, use the symfony task `gearman:worker` with 
`--config=example1` :
+
+    $ symfony gearman:worker --config=example1
+
+
+This command starts a gearman worker, and exit after processing 100 jobs or 
waiting 20 secs for a job.
+You can tweak this with `--count=100` and `--timeout=20` options (use 0 for 
count and a negative value for timeout to never end worker).
+
+If you want your worker to restart automatically, use 
[supervisord](http://supervisord.org/) or 
[daemon-tools](http://cr.yp.to/daemontools.html), or any process control tool.
+
+To see what happens, use `--verbose` option :
+
+    $ symfony gearman:worker --config=example1 --verbose
+
+
+See all options with :
+
+    $ symfony help gearman:worker
+
+
+If you want to trace jobs and workloads as well, you need to notify symfony 
that a job is processed :
+
+    [php]
+    /**
+     * Gearman worker example1
+     */
+    class Worker1
+    {
+      /**
+       * reverse work handler
+       *
+       * @param GearmanJob      $job    Gearman job
+       * @param sfGearmanWorker $worker sfGearmanWorker
+       * @return string                 Result sent to client
+       */
+      public static function reverse($job, $worker)
+      {
+        // sfGearman worker is passed as the 2nd parameter of the method
+        // notifyEventJob() displays a trace in symfony task output
+        // if --verbose is set, workload is logged too
+        $worker->notifyEventJob($job);
+
+        return strrev($job->workload());
+      }
+    }
+
+
+Gearman protocol only handles strings in workloads, if you need to return an 
array or object as a worker result, use `sfGearman::serialize` :
+
+    [php]
+    /**
+     * Gearman worker example1
+     */
+    class Worker1
+    {
+      /**
+       * reverse work handler
+       *
+       * @param GearmanJob      $job    Gearman job
+       * @param sfGearmanWorker $worker sfGearmanWorker
+       * @return string                 Result sent to client
+       */
+      public static function hash($job, $worker)
+      {
+        $worker->notifyEventJob($job);
+
+        $workload = $job->workload();
+
+        $result = array(md5($workload), sha1($workload));
+
+        return sfGearman::serialize($result);
+      }
+    }
+
+The sfGearmanClient will automatically unserialize the result if needed.
+
+
+Use a client
+------------
+
+To create a gearman client, use `sfGearmanClient::getInstance` :
+
+    [php]
+    // client connecting to default server
+    $client = sfGearmanClient::getInstance();
+
+    // client connecting to a different server defined in gearman.yml
+    $client = sfGearmanClient::getInstance('local');
+
+
+You have 2 shorthands methods to send a job to gearman server : 
`task('function' [, 'workload'])` and `background('function' [, 'workload'])`, 
example:
+
+    [php]
+    // this blocks until a worker do the job and return result
+    $result = sfGearmanClient::getInstance()->task('reverse', 'Hello!');
+    // $result == '!olleH'
+
+    // this sends an asynchronous job to gearman server, the return value is a 
gearman handle
+    $handle = sfGearmanClient::getInstance()->background('async');
+    // $handle == 'H:host:id'
+
+
+If you need priorities for your jobs, pass as 3rd parameter the level you want 
:
+
+    [php]
+    // this job has high priority
+    $result = sfGearmanClient::getInstance()->task('reverse', 'Hello!', 
sfGearman::HIGH);
+
+    // this job has low priority
+    $result = sfGearmanClient::getInstance()->task('reverse', 'Hello!', 
sfGearman::LOW);
+
+
+Message queue manager
+---------------------
+
+The plugin provides a `sfGearmanQueue` class to put and get messages in 
queues, usage :
+
+    [php]
+    // put a message in a queue named "q1"
+    sfGearmanQueue::put('q1', 'a message');
+
+    // later or elsewhere, get a message from queue
+    $message = sfGearmanQueue::get('q1');
+
+    // put a message with high priority (will be fetched first)
+    sfGearmanQueue::put('q1', 'urgent', sfGearman::HIGH);
+
+    // ::get() blocks forever until a message arrives, if you want to timeout, 
use 2nd parameter (in ms)
+    try
+    {
+      $message = sfGearmanQueue::get('q1', 10000);
+    }
+    catch(sfGearmanTimeoutException $e)
+    {
+      // waited 10 secs but no message in queue
+    }
+
+
+Internally, this sends messages as serialized workloads of "queue.%name%" jobs.
+
+
+Doctrine integration
+--------------------
+
+The sfGearmanPlugin provides a Doctrine Template which listens to 
insert/update/delete events and sends background jobs to gearman server.
+
+Add the Gearmanable template to `doctrine/schema.yml`, for example we want to 
listen to the update events of articles:
+
+    [yml]
+    Article:
+      actAs:
+        Gearmanable: {events: [update]}
+      columns:
+        title:  string(200)
+
+Update your models, then configure `gearman.yml` to create a doctrine worker :
+
+    [yml]
+    all:
+      doctrine:
+        example2:
+          Article: ~
+
+Unlike the classic worker configuration, the doctrine one is made of the model 
name as key and the list of events as value, ~ is an alias to all events 
defined in `schema.yml`.
+
+Then implement worker callback, they need to be located in the model class and 
named "trigger%Event%" (to avoid overlapping), so :
+
+    [php]
+    class Article extends BaseArticle
+    {
+      public function triggerUpdate($modified)
+      {
+        if (in_array('title', $modified))
+        {
+          // update a search index, refresh symfony cache, ...
+        }
+      }
+    }
+
+Note that the only parameter for doctrine gearman work handler is an array of 
modified properties.
+
+Then launches a doctrine worker with symfony `gearman:worker-doctrine` task :
+
+    $ symfony gearman:worker-doctrine --config=example2
+
+You could omit the `--config=` option, this loads all doctrine models and 
register all events defined in `schema.yml`, but this merge all jobs in same 
workers.
+
+
+Then save as usual your records :
+
+    [php]
+    $article = Doctrine_Core::getTable('Article')->find($id);
+    $article->title = 'new title';
+    $article->save();
+
+This is what happens :
+
+1. The `->save()` sends a background job to gearman server containing 
serialized record
+2. The gearman server sends the job to the worker
+3. The worker unserializes the record and call the trigger
+
+Note:
+
+The object transits through gearman server, and the trigger is called in 
another php process.
+
+So when the record arrives to symfony worker task, it may not exists anymore 
in the database, or may be out-of-date.
+
+If you want a fresh copy, use doctrine `refresh()` in the handler :
+
+    [php]
+    class Article extends BaseArticle
+    {
+      public function triggerUpdate($modified)
+      {
+        try { $this->refresh(); }
+        catch (Doctrine_Record_Exception $e) { return; }
+
+        // here the record is reloaded from db
+      }
+    }
+
+Don't use the previous snippet in `triggerDelete()` because what you have in 
the worker task is only a ghost of your record.
+
+
+To access the gearman job object, use the method `->getGearmanJob()` :
+
+    [php]
+    class Article extends BaseArticle
+    {
+      public function triggerUpdate($modified)
+      {
+        $job = $this->getGearmanJob();
+        $job->sendFail();
+      }
+    }
+
+
+Custom doctrine jobs
+--------------------
+
+You can have custom jobs for Doctrine records, register them in `gearman.yml`:
+
+    [yml]
+    all:
+      doctrine:
+        example2:
+          Article: [publish, ~]
+
+Implement them in your model class:
+
+    [php]
+    class Article extends BaseArticle
+    {
+      public function publish($tweet, $ping)
+      {
+        try { $this->refresh(); }
+        catch (Doctrine_Record_Exception $e) { return; }
+
+        // heavy code to publish your article
+      }
+    }
+
+Reload your worker task to work this new function.
+
+Then launch tasks with `->task('function' [, ...])` for synchronous jobs, or 
`->taskBackground('function' [, ...])` for asynchronous ones.
+
+    [php]
+    $article = Doctrine_Core::getTable('Article')->find($id);
+    $article->taskBackground('publish', false, true);
+    // this returns immediately and let the symfony task do the heavy code for 
->publish(false, true)
+
+
+Doctrine table jobs
+-------------------
+
+You can have function for Doctrine table, example :
+
+    [yml]
+    all:
+      doctrine:
+        example2:
+          Article: [buildFeed, publish, ~]
+
+
+Define the job handler in the table class :
+
+    [php]
+    class TestArticleTable extends Doctrine_Table
+    {
+      public function buildFeed()
+      {
+        // build the feeds
+      }
+    }
+
+
+Call `task()` or `taskBackground()` on the table :
+
+    [php]
+    Doctrine_Core::getTable('Article')->taskBackground('buildFeed');
+
+

Deleted: plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml
===================================================================
--- plugins/sfGearmanPlugin/trunk/config/gearman.yml    2010-05-16 17:11:45 UTC 
(rev 29482)
+++ plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml       2010-05-16 
21:16:50 UTC (rev 29486)
@@ -1,3 +0,0 @@
-all:
-  server:
-    default: ~

Copied: plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml (from rev 29485, 
plugins/sfGearmanPlugin/trunk/config/gearman.yml)
===================================================================
--- plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml                       
        (rev 0)
+++ plugins/sfGearmanPlugin/tags/0.9.0/config/gearman.yml       2010-05-16 
21:16:50 UTC (rev 29486)
@@ -0,0 +1,5 @@
+# default server configuration
+all:
+  server:
+    default: ~ # = GEARMAN_DEFAULT_TCP_HOST:GEARMAN_DEFAULT_TCP_PORT
+

Copied: plugins/sfGearmanPlugin/tags/0.9.0/package.xml.tmpl (from rev 29482, 
plugins/sfGearmanPlugin/trunk/package.xml.tmpl)
===================================================================
--- plugins/sfGearmanPlugin/tags/0.9.0/package.xml.tmpl                         
(rev 0)
+++ plugins/sfGearmanPlugin/tags/0.9.0/package.xml.tmpl 2010-05-16 21:16:50 UTC 
(rev 29486)
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="##ENCODING##"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0"; 
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; packagerversion="1.4.1" 
version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 
http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 
http://pear.php.net/dtd/package-2.0.xsd";>
+  <name>sfGearmanPlugin</name>
+  <channel>plugins.symfony-project.org</channel>
+  <summary>Gearman plugin for symfony</summary>
+  <description>sfGearmanPlugin provides gearman support to symfony 
(pecl/gearman)</description>
+  <lead>
+    <name>Benjamin VIELLARD</name>
+    <user>bicou</user>
+    <email>[email protected]</email>
+    <active>yes</active>
+  </lead>
+  <date>##CURRENT_DATE##</date>
+  <version>
+    <release>##PLUGIN_VERSION##</release>
+    <api>##API_VERSION##</api>
+  </version>
+  <stability>
+    <release>##STABILITY##</release>
+    <api>##STABILITY##</api>
+  </stability>
+  <license uri="http://www.symfony-project.org/license";>MIT license</license>
+  <notes>-</notes>
+  <contents>
+    ##CONTENTS##
+  </contents>
+  <dependencies>
+    <required>
+      <php>
+        <min>5.2.4</min>
+      </php>
+      <pearinstaller>
+        <min>1.4.1</min>
+      </pearinstaller>
+      <package>
+        <name>symfony</name>
+        <channel>pear.symfony-project.com</channel>
+        <min>1.2.0</min>
+        <max>2.0.0</max>
+        <exclude>2.0.0</exclude>
+      </package>
+    </required>
+  </dependencies>
+  <phprelease></phprelease>
+  <changelog>
+    <release>
+      <version>
+        <release>0.9.0</release>
+        <api>0.9.0</api>
+      </version>
+      <stability>
+       <release>beta</release>
+       <api>stable</api>
+      </stability>
+      <license uri="http://www.symfony-project.org/license";>MIT 
license</license>
+      <date>2010-05-11</date>
+      <notes>
+        * First public release
+      </notes>
+    </release>
+  </changelog>
+</package>

Deleted: 
plugins/sfGearmanPlugin/tags/0.9.0/test/fixtures/project/cache/project_autoload.cache
===================================================================
--- 
plugins/sfGearmanPlugin/trunk/test/fixtures/project/cache/project_autoload.cache
    2010-05-16 17:11:45 UTC (rev 29482)
+++ 
plugins/sfGearmanPlugin/tags/0.9.0/test/fixtures/project/cache/project_autoload.cache
       2010-05-16 21:16:50 UTC (rev 29486)
@@ -1 +0,0 @@
-a:3:{i:0;a:16:{s:9:"sfgearman";s:57:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearman.class.php";s:36:"doctrine_record_listener_gearmanable";s:84:"/home/bicou/sfGearmanPlugin/trunk/lib/Doctrine/Record/Listener/Gearmanable.class.php";s:29:"doctrine_template_gearmanable";s:77:"/home/bicou/sfGearmanPlugin/trunk/lib/Doctrine/Template/Gearmanable.class.php";s:14:"sfgearmanqueue";s:62:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearmanQueue.class.php";s:24:"gearmanworkertriggertask";s:77:"/home/bicou/sfGearmanPlugin/trunk/lib/task/gearmanWorkertriggerTask.class.php";s:23:"sfgearmanworkerbasetask";s:76:"/home/bicou/sfGearmanPlugin/trunk/lib/task/sfGearmanWorkerBaseTask.class.php";s:24:"gearmancreatetriggertask";s:77:"/home/bicou/sfGearmanPlugin/trunk/lib/task/gearmanCreateTriggerTask.class.php";s:25:"gearmanworkerdoctrinetask";s:78:"/home/bicou/sfGearmanPlugin/trunk/lib/task/gearmanWorkerdoctrineTask.class.php";s:17:"gearmanworkertask";s:70:"/home/bicou/sfGearmanPlugin/trunk/lib/task/gearmanWorkerTask.class.php";s:15:"sfgearmanclient";s:63:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearmanClient.class.php";s:15:"sfgearmanworker";s:63:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearmanWorker.class.php";s:22:"sfgearmanconfighandler";s:77:"/home/bicou/sfGearmanPlugin/trunk/lib/config/sfGearmanConfigHandler.class.php";s:18:"sfgearmanexception";s:76:"/home/bicou/sfGearmanPlugin/trunk/lib/exception/sfGearmanException.class.php";s:25:"sfgearmantimeoutexception";s:83:"/home/bicou/sfGearmanPlugin/trunk/lib/exception/sfGearmanTimeoutException.class.php";s:19:"sfgearmanconnection";s:67:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearmanConnection.class.php";s:23:"sfgearmanworkerdoctrine";s:71:"/home/bicou/sfGearmanPlugin/trunk/lib/sfGearmanWorkerDoctrine.class.php";}i:1;a:1:{i:2;s:37:"/home/bicou/sfGearmanPlugin/trunk/lib";}i:2;a:0:{}}
\ No newline at end of file

-- 
You received this message because you are subscribed to the Google Groups 
"symfony SVN" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/symfony-svn?hl=en.

Reply via email to