libriciel/cakephp-beanstalk

Permet d'utiliser beanstalk pour lancer des background processes.

4.1.1 2023-10-05 14:21 UTC

README

License build status coverage report

Plugin Cakephp 4.

Interface entre le service beanstalkd, votre application et vos workers.

Prérequis

Un serveur Beanstalkd est indispensable.

sudo apt-get install beanstalkd

Si vous voulez conserver les jobs après le redémarrage du service, il vous faut modifier la conf.

sudo nano /etc/default/beanstalkd

Décommettez la dernière ligne : BEANSTALKD_EXTRA="-b /var/lib/beanstalkd"

Autre méthode : lancez beanstalkd avec l'option -d

Installation

composer config repositories.libriciel/cakephp-beanstalk git https://gitlab.libriciel.fr/CakePHP/cakephp-beanstalk.git
composer require libriciel/cakephp-beanstalk ^2.0

Ajoutez le plugin dans votre Application.php

$this->addPlugin('Beanstalk');

Base de données

Vous pouvez au choix, utiliser le SQL (postgres) fourni dans config/schema/beanstalk.sql, ou bien utiliser le plugin migration :

bin/cake migrations migrate --plugin Beanstalk

Utilisation

Maintenant que vous disposez de votre serveur Beanstalkd, il va vous falloir un ou plusieurs workers selon le besoin.

Exemple sur vendor/libriciel/cakephp-beanstalk/exemple/DefaultWorker.php Copiez ce fichier vers src/Shell/Worker Ajoutez à votre configuration :

Configure::write([
    'Beanstalk' => [
        /**
         * Connection au serveur Beanstalkd
         */
        'host' => '127.0.0.1',
        'port' => 11300,
        'timeout' => null,
        'persistant' => false,

        /**
         * Chemin des classes de workers
         */
        'workerPaths' => [
            APP . 'Shell' . DS . 'Worker'
        ],

        /**
         * Configurations liées aux tests des workers
         *
         * - timeout: durée maximum en secondes entre l'émission du test et la
         *            consultation du résultat
         */
        'tests' => [
            'timeout' => 10,
        ],
        
        /**
         * Configuration optionnelle
         */
         'table_jobs' => 'Beanstalk.BeanstalkJobs',
         'table_workers' => 'Beanstalk.BeanstalkWorkers',
         'classname', \Beanstalk\Utility\Beanstalk::class,
         'PheanstalkClassname' => \Pheanstalk\Pheanstalk::class
    ]
]);

Lancer un worker

Options:

  • --dir Dossier de la classe du worker
  • --one-job N'effectue qu'un seul job - utile pour un worker sous docker
  • --suffix Permet de spécifier le dossier worker (default: Worker)
  • --table-workers Permet de spécifier la table utilisée pour stocker les informations sur le worker lancé (default: Beanstalk.BeanstalkWorkers)
  • --tube Nom du tube (par défaut: nom du worker)
  • --unique Lance le worker seulement s'il est seul sur son tube

Arguments:

  • worker Nom du worker (optional)

Lancez votre shell :

bin/cake worker default_worker

On peut lancer plusieurs workers en même temps. Attention car un worker peut occuper un thread à 100% jusqu’à la fin de la file de job. Si le nombre de workers dépasse celui du nombre de cœur la charge sera équitablement répartie. Si les workers sont sur le même serveur que la page web, l’expérience utilisateur peut s'en retrouver affectée.

L'utilitaire Beanstalk

Permet de communiquer avec le service Beanstalkd tout en manipulant la base de données de l'application afin de conserver certaines informations.

La methode __construct()

Prends en paramètre le tube sur lequel va travailler le worker. Il est bon d'avoir un tube par worker. Les autres paramètres sont pour la connexion au serveur beanstalkd.

emit()

Ajoute un Job dans le tube, avec le data passé en paramètres.

getNext()

Utile pour boucler dessus, il se charge de réserver le prochain job et l'affecter à Worker->job Si aucun job n'est à faire, il attend tranquillement qu'un nouveau job arrive sans prendre de la charge serveur.

getData()

Attention, peut renvoyer faux si la signature des données n'est pas validée. Cette particularité a pour but d'éviter les conflits si une autre application utilise le même tube.

Sinon, la donnée renvoyée peut être de tous types grâce à une conversion json.

done()

Supprime le job car celui-ci est terminé

exemple:

$Beanstalk = new \Beanstalk\Utility\Beanstalk('mon-tube');

$Beanstalk->emit('foo'); // Envoi un message dans le tube

while ($Beanstalk->getNext()) {
    $data = $Beanstalk->getData();
    $Beanstalk->done();
    if ($data === 'foo') {
        break;
    }
}

Faire un worker

Créez une classe Worker (suffixe Worker par défaut) qui implémente WorkerInterface. Vous pouvez étendre la classe AbstractWorker qui possède déjà la mécanique de base d'un worker (il vous faudra juste définir la méthode principale: work()).

exemple:

<?php
namespace App\Shell\Worker;
use Beanstalk\Command\AbstractWorker;
use Beanstalk\Command\WorkerInterface;

class ExempleWorker extends AbstractWorker implements WorkerInterface
{
    public function work($data)
    {
        echo $data;
    }
}