[PHP] Gearman en PHP namespaces (5.3+) geeft file als output

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Ik probeer mijn script samen met Gearman te laten werken. Ik draai een Gearman-daemon (gearmand) op mijn server. De output zou een pagina moeten zijn met eigenlijk vrijwel niets. Maar de echte uitkomst is nog minder dan dat, want er komt helemaal geen pagina uit, maar een file dat me aan wordt geboden via mijn browser (in dit geval worker.php, zoals mijn bestand heet). Ik snap niet wat ik fout doe, heeft het mogelijk met de namespaces te maken?

Onderstaand mijn volledige script. Wanneer ik een 'addFunction' statement uncomment, dan krijg ik het als bestand aangeboden. Anders werkt het prima. Ook een callback met '$this' ipv static geeft hetzelfde resultaat.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
namespace Rows
{
    class Worker
    {   public static $aMappings = Array(), $oInst = null;  
        public $sId, $oClient, $oWorker, $aNeighbours = Array();
    
    
            // Life starts // Should be singleton I guess..
        private function __construct()
        {   $this->sId = base64_encode(time().rand());
            
            $this->initClient();
            $this->initWorker();

            $this->oClient->doHigh('addNeighbour', $this->sId);
        }
        
        
        public static function &getInstance()
        {   if (self::$oInst == null)
                self::$oInst = new self();
            
            return self::$oInst;            
        }
                
        
        private function initClient()
        {   $this->oClient = new \GearmanClient();
            $this->oClient->setTimeout(2000);
            $this->oClient->addServer();
        }
        
        private function initWorker()
        {   $this->oWorker = new \GearmanWorker();
            $this->oWorker->addServer();
            
            /*var_dump( $this->oClient->do('getNeighbours', null) );
            $this->aNeighbours = $this->oClient->do('getNeighbours', null);*/           
            
            $this->oWorker->addFunction('addNeighbour', '\Rows\Worker::addNeighbour');
            //$this->oWorker->addFunction('removeNeighbour',                Array(__CLASS__, 'removeNeighbour'));
        }
        
        
        public function doWork()
        {   $this->oWorker->work();
            //while ($this->oWorker->work()){ echo '!'.$this->oWorker->returnCode(); };         
        }
        
        
            // Neighbour functions
        public static function addNeighbour($sId)
        {   
            //return self::getInstance()->aNeighbours[$sId->workload()] = true;
        
            //return self::getInstance()->updateNeighbours($sId);
        }
        
        
        public static function setNeighbours($aIds)
        {   return self::getInstance()->aNeighbours = $aIds;
        }
        
        
        public static function getNeighbours()
        {   return self::getInstance()->aNeighbours;
        }
        
        
        public static function updateNeighbours($sId)
        {
            foreach (self::getInstance()->aNeighbours as $sNeigbourId => $bTrue)
            {   echo $sNeighbourId;
                /*if(($sNeigbourId == $sId)
                || ($sNeighbourId == self::getInstance()->sId))
                    continue;

                self::getInstance()->oClient->do('setNeighbours_'.$sNeigbourId, self::getInstance()->aNeighbours);*/
            }
            return true;
        }
        
        public static function removeNeighbour($sId)
        {   self::getInstance()->aNeighbours[$sId->workload()] = null;

            //return self::getInstance()->updateNeighbours($sId->workload());
        }
        
        
            // Dead meat
        public function __destruct()
        {   $this->oClient->doHigh('removeNeighbour', $this->sId);
        }       
    }
}

[..]
init
[..]


Iemand die me helpen kan? Ik draai dus PHP 5.3.1 op Apache 2.2

[ Voor 7% gewijzigd door r0bert op 04-02-2010 19:21 ]


Acties:
  • 0 Henk 'm!

  • Jory
  • Registratie: Mei 2006
  • Laatst online: 08-09 23:10
Dit komt niet door de namespaces. Dit komt omdat je Gearman verkeerd gebruikt.

In principe is je opzet goed, je maakt alleen één fout. Je moet je workers niet starten als deel van de afhandeling van een http request. Het idee is dat je een aantal workers hebt draaien, en in je request afhandeling enkel een client gebruikt.

Op de Gearman website staan een aantal usecases. Één daarvan is een simpel voorbeeld van een PHP worker + client: http://gearman.org/index.php?id=php_-_mail_queue
Wat ze daar waarschijnlijk doen, is een of meerdere workers (bovenste blok code) starten, bijvoorbeeld tijdens het opstarten van de server. Vervolgens wordt in de afhandeling van een webpagina het onderste stuk code uitgevoerd.
Je hebt dus twee verschillende stukken code, die apart worden uitgevoerd. Jij hebt beide in één zitten.

Ik zou zeggen, ga eerst ergens een simpel iets maken waarbij je Gearman gebruikt, zodat je weet hoe het precies werkt. Ga het daarna pas integreren in je systeem.

Acties:
  • 0 Henk 'm!

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Jory167; Bedankt voor je reactie, echter is dit precies wat ik wil. De Worker is tegelijk een Client, dat om de Workers met elkaar synchroom te houden. Standaard biedt de extensie geen mogelijkheden heden voor publish/subscribe. Door bij te houden welke workers beschikbaar zijn, kan de client ze queryen. Daarmee bouw ik een mapping-cache op (zit niet in deze code). Zijn nog meer redenen toe, maar het belangrijkste is dat bovenstaande naar mijn idee gewoon zou moeten kunnen.

In principe kun je het ook onder elkaar zetten
PHP:
1
2
3
4
5
6
7
8
9
10
11
$this->oClient = new \GearmanClient();
$this->oClient->setTimeout(2000);
$this->oClient->addServer(); 

$this->oWorker = new \GearmanWorker();
$this->oWorker->addServer();
$this->oWorker->addFunction('addNeighbour', '\Rows\Worker::addNeighbour'); 
$this->oWorker->addFunction('removeNeighbour', '\Rows\Worker::removeNeighbour');
$this->oClient->doHigh('addNeighbour', $this->sId); // Fails, no worker available
$this->oWorker->work(); // Wait for request, so I start another instance in other browser window
$this->oClient->doHigh('removeNeighbour', $this->sId); // It'll continue. Other instance is up, so this should work and other instance will end to (with error because of no removeNeighbour worker).


Maar dan nog, snap ik niet waarom ik een bestand geserveerd krijg:?

Acties:
  • 0 Henk 'm!

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Lijkt op een bug
code:
1
[error] [..] gearman_client_run_tasks: Assertion `client->tasks != ((void *)0)` failed [..]


Een fix lijkt geplant te zijn voor 0.12.

Voor nu los ik het zo denk ik op:
PHP:
1
2
3
4
5
6
[..]
public function __destruct()
{   $this->oClient->doHigh('removeNeighbour', $this->sId);
    $this->oClient->doBackground('removeNeighbour', $this->sId);
}
[..]

Lelijk, maar het werkt voor testomgeving, in productie verre van wenselijk.

[ Voor 57% gewijzigd door r0bert op 04-02-2010 19:19 . Reden: Workaround ]