Welcome to Recruiter’s documentation!¶
Features and characteristics:
- Jobs are made persistent on MongoDB
- Jobs with complex and customizable strategies
- Jobs are stored by default in an history collection for after the fact inspection and analytics
- Multiple queues are supported through grouping
- Built to be robust, scalable and fault tolerant
At high level, it provides a few major components:
- A recruiter: a single instance long-running process who assign enqueued jobs to a worker
- A worker: a multiple instace long-running processes that each execute a single job at a time
- A cleaner: a single instance long-running process who takes care of cleaning up the dirty conditions that can happen (i.e. worker dead for a fatal error)
What is Recruiter¶
Features and characteristics:
- Jobs are made persistent on MongoDB
- Jobs with complex and customizable strategies
- Jobs are stored by default in an history collection for after the fact inspection and analytics
- Multiple queues are supported through grouping
- Built to be robust, scalable and fault tolerant
At high level, it provides a few major components:
- A recruiter: a single instance long-running process who assign enqueued jobs to a worker
- A worker: a multiple instace long-running processes that each execute a single job at a time
- A cleaner: a single instance long-running process who takes care of cleaning up the dirty conditions that can happen (i.e. worker dead for a fatal error)
Why¶
DA COMPLETARE¶
Onebip is a payment system (think PayPal with mobile devices in place of credit cards), things like: payment notifications, subscription renewals, remainder messages, … are really important. You cannot skip or lose a job (notification are idempotent but payments are not). You cannot forgot to have completed a job (customer/merchant support must have data to do their job). You need to know if and when you can retry a failed job (external services have rate limits and are based on agreements/contracts). We have developed internally our job/queue solution called Recruiter. After a year in production and many billions of jobs we have decided to put what we have learned into a stand alone project and to make it available to everyone.
Processes¶
Recruiter process¶
$ php vendor/bin/recruiter start:recruiter --target 127.0.0.1:27017
Per una lista completa delle opzioni lanciare il comando:
$ php vendor/bin/recruiter help start:recruiter
Worker process¶
$ php vendor/bin/recruiter start:worker --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
Per una lista completa delle opzioni lanciare il comando:
$ php vendor/bin/recruiter help start:worker
Cleaner process¶
$ php vendor/bin/recruiter start:cleaner --target 127.0.0.1:27017
Per una lista completa delle opzioni lanciare il comando:
$ php vendor/bin/recruiter help start:cleaner
Logging¶
vendor/bin/recruiter
.vendor/bin/recruiter
non fa altro che creare una istanza di Symfony\Component\Console\Application
, registrare i vari Symfony\Component\Console\Command\Command
(Recruiter, Worker e Clenaer Commands) ed eseguire l’applicazione symfony.Psr\Log\LoggerInterface
che logga su standard output. Nel caso in cui si desiderasse una diversa tipologia di Psr\Log\LoggerInterface
bisogna includere questi comandi nella propria Symfony\Component\Console\Application
in modo tale da poterli inizializzare iniettandogli il logger che si vuole.<?php
// bin/my-command
use Recruiter\Geezer\Command\RobustCommandRunner;
use Recruiter\Factory;
use Recruiter\Infrastructure\Command\CleanerCommand;
use Recruiter\Infrastructure\Command\RecruiterCommand;
use Recruiter\Infrastructure\Command\WorkerCommand;
use Symfony\Component\Console\Application;
use Domain\MyLogger;
$logger = new MyLogger();
$application = new Application();
$application->add(RecruiterCommand::toRobustCommand(new Factory(), $logger));
$application->add(WorkerCommand::toRobustCommand(new Factory(), $logger));
$application->add(CleanerCommand::toRobustCommand(new Factory(), $logger));
$application->run();
Setup¶
Install¶
You can install Recruiter through Composer by running the following command in your terminal:
$ composer require recruiterphp/recruiter
Setup¶
<?php
# src/recruiter-autoload.php
require_once __DIR__ . '/../vendor/autoload.php';
// in the bootstrap file you have access to a Recruiter\Recruiter instance through global variable `$recruiter`.
// $recruiter;
$ php vendor/bin/recruiter start:recruiter --target 127.0.0.1:27017 --bootstrap src/recruiter-bootstrap.php
$ php vendor/bin/recruiter start:worker --target 127.0.0.1:27017 --bootstrap src/recruiter-bootstrap.php
$ php vendor/bin/recruiter start:cleaner --target 127.0.0.1:27017
Sample¶
Cos’é un oggetto Workable?¶
Implementare un proprio Workable¶
<?php
use Http\Request;
class HttpRequestCommand
{
/**
* @var Request
*/
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public static function fromRequest(Request $request)
{
return new self ($request);
}
public function execute()
{
$httpClient = Container::instance()->get('Http\Client');
$httpClient->send($this->request);
}
}
Note
Recruiter\Workable
.<?php
use Recruiter\Recruiter;
use Recruiter\Workable;
use Http\Request;
class HttpRequestCommand implements Workable
{
/**
* @var Request
*/
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public static function fromRequest(Request $request)
{
return new self ($request);
}
public function execute()
{
$httpClient = Container::instance()->get('Http\Client');
$httpClient->send($this->request);
}
public function asJobOf(Recruiter $recruiter)
{
return $recruiter->jobOf($this);
}
public function export()
{
return ['request' => $this->request];
}
public static function import($parameters)
{
return new self(Request::box($parameters['request']));
}
}
Warning
Http\Client
non sia serializzabile, per questo motivo non é inclusa nell’export e viene ricavata tramite l’utilizzo di un “ServiceLocator”.<?php
use Recruiter\Recruiter;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$request = Request::post($url, $body);
HttpRequestCommand::fromRequest($request)
->asJobOf($recruiter)
->inBackground()
->execute() // this is the method defined in the Workable class
;
Jobs¶
Cos’é un Job¶
Job
come le unità di lavoro eseguite dal recruiter.Workable
che abbiamo visto in precedenza (e quindi la procedura da esegure) oltre a tutte le altre informazioni necessarie alla corretta esecuzione di questa procedura, come ad esempio:- la data di schedulazione,
- la policy di retry in caso di fallimento,
- lo stato attuale (da eseguire, in esecuzione, eseguito),
- il gruppo a cui appartiene
- altri (i.e. data di creazione, numero di tentativi effettuati, tags, ecc.)
- essere eseguito in process instantaneamente,
- essere schedulato per l’esecuzione in background il prima possibile,
- essere schedulato per l’esecuzione in background ad una determinata data/ora
- essere eseguito in process instantaneamente, ed in caso di fallimento essere schedulato per l’esecuzione in background in accordo con le proprie policy di retry.
- essere ritentato in caso di fallimento una o più volte, in accordo con delle specifiche politiche di retry.
Per poter accodare dei job da eseguire dovremo avere in mano un istanza della classe Recruiter\Recruiter
.
Warning
eseguito
; in quel caso il job verrà, dopo un certo periodo di tempo, assegnato ad un altro worker e quindi eseguito una seconda volta.Hello World¶
<?php
use MyDomain\HttpRequestCommand;
use MyDomain\Request;
use Recruiter\Recruiter;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$request = Request::post($url, $body);
HttpRequestCommand::fromRequest($request)
->asJobOf($recruiter)
->inBackground()
->execute() // this is the method defined in the Workable class
;
job
che chiamerà il metodo execute()
della classe HttpRequestCommand
e verrà eseguito non appena un worker
sarà disponibile.Schedule a Job in the future¶
scheduleAt()
a cui dovremo pasasre un instanza di Timeless\Moment
19 gennaio 2038
potremmo fare in questo modo:<?php
use MyDomain\HttpRequestCommand;
use MyDomain\Request;
use Recruiter\Recruiter;
use Timeless\Moment;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$request = Request::post($url, $body);
HttpRequestCommand::fromRequest($request)
->asJobOf($recruiter)
->scheduleAt(Moment::fromDateTime(new DateTime('2038-01-19T00:00:00.000000Z');))
->inBackground()
->execute()
;
In questo modo il job verrà messo in coda e verrà eseguto non appena ci sarà un worker libero disponibile successivamente alla data ‘2038-01-19T00:00:00.000000Z’
Retry¶
Recruiter\RetryPolicy
al job tramite il metodo retryWithPolicy(RetryPolicy $retryPolicy)
.<?php
use MyDomain\HttpRequestCommand;
use MyDomain\Request;
use Recruiter\Recruiter;
use Recruiter\RetryPolicy\RetryManyTimes;
use Timeless\Moment;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$retryPolicy = new RetryManyTimes(3, 60);
$request = Request::post($url, $body);
HttpRequestCommand::fromRequest($request)
->asJobOf($recruiter)
->scheduleAt(Moment::fromDateTime(new DateTime('2038-01-19T00:00:00.000Z')))
->retryWithPolicy($retryPolicy)
->inBackground()
->execute()
;
Retriable Exceptions¶
retryWithPolicy
permette infatti di specificare, come secondo argomento, un array di eccezioni per le quali é consentito eseguire un nuovo tentativo.<?php
$retryPolicy = new RetryManyTimes(3, 60);
$retriableExceptionTypes = [
\Psr\Http\Client\NetworkExceptionInterface::class
];
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy, $retriableExceptionTypes)
->inBackground()
->execute()
;
In questo caso il job verrà ripetuto solo in caso avvenga un eccezione di tipo Psr\Http\Client\NetworkExceptionInterface
, in tutti gli altri casi il job verrà archiviato.
Optimistic Jobs¶
<?php
$retryPolicy = new RetryManyTimes(3, 60);
$retriableExceptionTypes = [
\Psr\Http\Client\NetworkExceptionInterface::class
];
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy, $retriableExceptionTypes)
->execute()
;
inBackground()
, in questo modo il comando verrà eseguito subito, e, solo in caso di fallimento, verrà inserito nella coda dei job da eseguire in background.Note
<?php
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy, $retriableExceptionTypes)
->inBackground()
->execute()
;
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy, $retriableExceptionTypes)
->scheduleAt(Moment::fromDateTime(new DateTime('2151-02-21T15:03:01.012345Z');))
->execute()
;
Raggrupare i Job¶
inGroup($group)
<?php
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->inGroup('http')
->inBackground()
->execute()
;
Tags¶
<?php
HttpCommand::fromRequest($request);
->asJobOf($recruiter)
->taggedAs(['userId:42', 'color:red'])
->inBackground()
->execute()
;
Retry Policies¶
Implements a custom RetryPolicy¶
Recruiter\RetryPolicy
DoNotDoItAgain¶
This is the default (implicit) RetryPolicy, use it only if you want to make explicit the fact that the job should not be repeated.
<?php
use Recruiter\Recruiter;
use Recruiter\Workable\ShellCommand;
use Recruiter\RetryPolicy\DoNotDoItAgain;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
ShellCommand::fromCommandLine("false");
->asJobOf($recruiter)
->retryWithPolicy(new DoNotDoItAgain())
->inBackground()
->execute()
;
ExponentialBackoff¶
Questa RetryPolicy permette di ritentare l’esecuzione di un job ad intervalli esponenziali. Ad esempio possiamo impostare di avere un massimo di 10 retry con un intervallo iniziale di 30 secondi. Questo significa che dopo il primo fallimento verrà effettuato un retry dopo 30 secondi, in caso anche questo fallisca verrà effettuato un altro retry dopo 60 secondi, nel caso in cui anche questo fallisca verrà effettuato un nuovo retry dopo 120 secondi e cosi via, fino ad un massimo di 10 nuovi tentativi.
L’ ExponentialBackoff policy accetta come parametri il numero massimo di tentativi da effettuare ed i secondi iniziali di intervallo prima di effettuare il primo tentativo.
Examples:
<?php
use Recruiter\Recruiter;
use Recruiter\Workable\ShellCommand;
use Recruiter\RetryPolicy\ExponentialBackoff;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$retryPolicy = ExponentialBackoff::forTimes(10, 30);
//This is the same to the following:
// $retryPolicy = new ExponentialBackoff(10, 30);
ShellCommand::fromCommandLine("false");
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy)
->inBackground()
->execute()
;
..TODO: verificare al parte seguente prima di pubblicarla .. Questa policy comprende anche un factory method che accetta il numero di secondi massimo in cui riprovare ed il numero di secondi iniziali di intervallo prima di effettuare il primo tentativo: .. .. Examples: .. .. .. code-block:: php .. .. <?php .. .. use RecruiterRecruiter; .. use RecruiterWorkableShellCommand; .. use RecruiterRetryPolicyExponentialBackoff; .. .. $mongodbInstance = new MongoDBClient(…); .. $recruiter = new Recruiter($mongodbInstance); .. .. // In this case there will be a maximum of 4 attempts: after the first failure a retry will be made after 30 seconds, another one after 60 seconds, and the last after 120 seconds .. $retryPolicy = ExponentialBackoff::forAnInterval(120, 30); .. .. ShellCommand::fromCommandLine(“false”); .. ->asJobOf($recruiter) .. ->retryWithPolicy($retryPolicy) .. ->scheduleAt(Moment::fromDateTime(new DateTime(‘2027-02-21T15:00:00.0000Z’);)) .. ->inBackground() .. ->execute() .. ;
RetryForevers¶
Questa RetryPolicy permette di ritentare l’esecuzione di un job all’infinito specificando l’intervallo di tempo tra un tentativo e l’altro. Se ad esempio volessimo eseguire un job all’infinito aspettando 30 secondi tra un tentativo e l’altro possiamo scrivere:
<?php
use Recruiter\Recruiter;
use Recruiter\Workable\ShellCommand;
use Recruiter\RetryPolicy\RetryForevers;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$retryPolicy = RetryForevers::afterSeconds(30);
//This is the same to the following:
// $retryPolicy = new RetryForevers(30);
ShellCommand::fromCommandLine("false");
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy)
->inBackground()
->execute()
;
RetryManyTimes¶
Questa RetryPolicy permette di ritentare l’esecuzione di un job un numero finito di volte specificando l’intervallo di tempo tra un tentativo e l’altro. Se ad esempio vogliamo ritentare un job per 3 volte, aspettando 30 secondi tra un tentativoo e l’altro, possiamo scrivere:
<?php
use Recruiter\Recruiter;
use Recruiter\Workable\ShellCommand;
use Recruiter\RetryPolicy\RetryManyTimes;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$retryPolicy = RetryManyTimes::forTimes(3, 30);
//This is the same to the following:
// $retryPolicy = new RetryManyTimes(3, 30);
ShellCommand::fromCommandLine("false");
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy)
->inBackground()
->execute()
;
TimeTable¶
Questa RetryPolicy permette di ritentare l’esecuzione di un job ad intervalli regolari dipendenti da quanto tempo é passato rispetto alla creazione del job.
Ad esempio se volessimo ritentare il job * ogni minuto per i primi 5 minuti di vita del job, * ogni 5 minuti per la prima ora (cioé i successivi 55 minuti) .. * ogni 5 minuti per i successivi 55 minuti * ed ogni ora per le prime 24 ore (cioé le successive 23 ore) .. * ogni ora per le successive 23 ore
Possiamo scrivere il seguente codice:
<?php
use Recruiter\Recruiter;
use Recruiter\Workable\ShellCommand;
use Recruiter\RetryPolicy\TimeTable;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$retryPolicy = new TimeTable([
'5 minutes ago' => '1 minute',
'1 hour ago' => '5 minutes',
'24 hours ago' => '1 hour',
]);
ShellCommand::fromCommandLine("false");
->asJobOf($recruiter)
->retryWithPolicy($retryPolicy)
->inBackground()
->execute()
;
Warning
Questa policy accetta un array chiave-valore dove sia le chiavi che i valori devono essere stringhe parsabili dalla funzione php strtotime
Repeatable Jobs¶
Recruiter\Workable
utilizzando il trait Recruiter\WorkableBehaviour
per evitare di scrivere codice ridondante.<?php
use Recruiter\Recruiter;
use Recruiter\Workable;
use Recruiter\WorkableBehaviour;
class DailyReportCommand implements Workable
{
use WorkableBehaviour;
public function execute()
{
// ...
// here we generate the report and send it to the desired recipient
// ...
}
}
Recruiter\Repeatable
in modo che possa essere schedulato automaticamente secondo un determinato schema.<?php
use Recruiter\Recruiter;
use Recruiter\Repeatable;
use Recruiter\RepeatableBehaviour;
use Recruiter\Workable;
use Recruiter\WorkableBehaviour;
class DailyReportCommand implements Workable, Repeatable
{
use WorkableBehaviour, RepeatableBehaviour;
public function execute()
{
// ...
// here we generate the report and send it to the desired recipient
// ...
}
public function urn(): string
{
return 'report:daily';
}
public function unique(): bool
{
return false;
}
}
urn()
), ed indicato al Recruiter se é possibile o meno che 2 o più istanze di questo job si sovrappongano (tramite il metodo unique()
)Recruiter\SchedulePolicy
Recruiter\SchedulePolicy\Cron
e permette di specificare gli intervalli di esecuzione con la stessa sintassi utilizzata dal demone unix cron.<?php
use Recruiter\Recruiter;
use Recruiter\SchedulePolicy\Cron;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$schedulePolicy = new Cron('0 6 * * *');
$scheduler = (new DailyReportCommand())
->asRepeatableJobOf($this->recruiter)
->repeatWithPolicy($schedulePolicy)
->retryWithPolicy(new DoNotDoItAgain()) // this is the default behaviour
->create()
;
$ php vendor/bin/recruiter scheduler:remove --target 127.0.0.1:27017
Recruiter Hooks¶
hook functions
che verranno richiamate dal Recruiter in determinati momenti/stati.- recruiter_became_master
- recruiter_stept_back
recruiter_became_master¶
<?php
use Recruiter\Recruiter;
function recruiter_became_master(Recruiter $recruiter): void
{
// Schedule a Recruiter\Repeatable job
}
How to handle priority¶
- invio di un messaggio email di double-option (per la verifica dell’indirizzo email prima dell’acquisto).
- invio di una email di conferma acquisto.
- invio di una email di follow-up agli utenti che non hanno completato l’acquisto dopo 7 giorni.
Workable
), ma tutte e tre hanno una diversa priorità:- double-optin-email (or high-priority)
- confirmation-email (or generics)
- follow-up-email (or low-priority)
workers
per prendersi carico solo di una determinata tipologia di gruppo. In questo modo, grazie al numero di workers
presenti su ogni coda (gruppo) avremo velocità di evasione dei jobs
differenti.- 1 worker che lavora sulla coda
follow-up-email
(orlow-priority
) - 2 worker che lavorano sulla coda
confirmation-email
(orgenerics
) - 4 worker che lavorano sulla coda
double-optin-email
(orhigh-priority
)
- un solo job facente parte del gruppo
follow-up-email
alla volta (Quindi nel caso in cui ci siano 2 jobs nel gruppolow-priority
schedulati entrambi per lo stesso orario, il secondo verrà eseguito solo al termine del primo). - due job facenti parti del gruppo
confirmation-email
in parallelo - quattro job facenti parti del gruppo
double-optin-email
in parallelo
$ php vendor/bin/recruiter start:worker --work-on='double-optin-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='double-optin-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='double-optin-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='double-optin-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='confirmation-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='confirmation-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
$ php vendor/bin/recruiter start:worker --work-on='follow-up-email' --target 127.0.0.1:27017 --bootstrap $APP_BASE_PATH/worker-boostrap.php
Analytics¶
analytics
dell’oggetto Recruiter\Recruiter
.- jobs:
- queued: il numero di jobs in coda con una data di schedulazione passata (e quindi da eseguire), questo numero dovrebbe rimanere stabile.
- postponed: il numero di jobs in coda con una data di schedulazione futura (da eseguire solo quando la data di schedulazione sarà passata).
- throughput:
- value: numero di job eseguiti al minuto
- value_per_second: numero di job eseguiti al secondo
- latency:
- average: Il numero medio di secondi che passa dalla data di schedulazione alla data di esecuzione del job. Un valore alto significa che ci sono troppi pochi worker in esecuzione per quella specifica coda.
- execution_time:
- average: il tempo di esecuzione medio di un job.
<?php
use Recruiter\Recruiter;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$analytics = $recruiter->analytics();
var_export($analytics);
// array (
// 'jobs' => array (
// 'queued' => 10,
// 'postponed' => 30,
// 'zombies' => 0,
// ),
// 'throughput' => array (
// 'value' => 3.0,
// 'value_per_second' => 0.05,
// ),
// 'latency' => array (
// 'average' => 0.0,
// ),
// 'execution_time' => array (
// 'average' => 0,
// ),
// )
<?php
$analytics = $recruiter->analytics('custom-group');
Mongo Collections¶
“roster” collection¶
“scheduled” collection¶
“archived” collection¶
- indagare i motivi del fallimento di un job (nel documento viene incluso lo stato del job (completato o meno) e il motivo dell’ultimo fallimento, più altri dati utili)
- rischedulare un job
“schedulers” collection¶
Administration console¶
Recovering a job¶
$ php vendor/bin/recruiter job:recover --target mongodb://localhost:27017/recruiter --scheduleAt "2019-12-01T22:18:00Z" 5d27436e2bacd566a67e85e4
Analytics¶
target
.group
.$ php vendor/bin/recruiter bko:analytics --target mongodb://localhost:27017/recruiter --group html
Esecuzione dei jobs all’interno dei tests:¶
- Maggiore difficoltà di esecuzione dei test: in quanto il nostro ambiente deve prevedere l’esecuzione di long running process ed assicurarsi che siano attivi durante l’intera esecuzione del test.
- Diminuzione della velocità di esecuzione dei test: Nel caso in cui i test dipendano dal risultato dell’esecuzione dei job dovremmo attendere la loro esecuzione da parte dei worker, che per quanto reattivi possano essere non possono essere istantanei; dobbiamo inoltre considerare il fatto che i job potrebbero essere schedulati nel futuro e che quindi i worker non potranno eseguirli finché la data di schedulazione non sia passata.
- Impossibilità di dipendere da job schedulati molto avanti nel futuro: Se nel caso in cui i job siano schedulati a qualche secondo di distanza dal momento corrente porta al solo rallentamento di esecuzione dei test, il caso in cui i job siano schedulati molto avanti nel futuro (es. il giorno seguente o il mese seguente) porta all’impossibilità di esecuzione dei test (non possiamo certo attendere cosi tanto tempo per terminarne l’esecuzione di un test).
Recruiter\Recruiter
, che permette l’esecuzione, nel processo corrente, di tutti i job precedentemente accodati.flushJobsSynchronously()
e può essere chiamato su qualsiasi istanza della classe Recruiter\Recruiter
(quindi non per forza la stessa istanza utilizzata per accodare i job).<?php
namespace Tests;
use Core\DomainService;
$mongodbInstance = new MongoDB\Client(...);
$recruiter = new Recruiter($mongodbInstance);
$domainService = new DomainService($recruiter);
$domainService->methodThatQueuesJobs();
$recruiter->flushJobsSynchronously(); // Here all previously queued jobs are executed
Documentazione da scrivere:¶
- dipendenze
- perché esiste
- che problemi risolve é sufficiente dire che permette l’esecuzione di routine in background?
- struttura
- cos’é recruiter
- cos’é un worker
- cos’é il cleaner
- setup
- installazione
- lanciare recruiter
- lanciare workers
- lanciare cleaners
- esempi
- hello world: task singolo che deve essere completato
- senza retry policy (hello world)
- schedule subito
- schedule nel futuro
- con retry policy semplice
- retryable exceptions
- retry policy complesse (exponential backoff)
- task ottimistico
- approfondimenti
- come si implementa una workable
- come si implementa una retry policy (non é dettagliato, ma uno si può guardare l’implementazione di una delle tante esistenti per capire come fare…)
- tags
- recruiter statistiche
- hooks
- repeatable jobs
- working-on (priority queues)
- collezioni ( a che serve archived, etc.)
- come rimettere un job in coda
- esecuzione nei test
- iniettare il logger
- geezer