In the use of the process feel very good, it is recommended to look at the principle of the queue.
shmilyzxt/yii2-queue
Simple explanation:
I use the YII2 Premium version, we start from the configuration to see the code, here I use the MySQL queue, the first configuration file, I put the queue
configuration item in the root directory under common\config\main-local.php
the components
array, change the database configuration. Replication composer
after installation
vendor\shmilyzxt\yii2-queue\jobs\jobs.sql
vendor\shmilyzxt\yii2-queue\failed\failed.sql
2 SQL files into the database to set up the queue data table and the data table when the task fails to execute.
Push task start syntax: \Yii::$app->queue->pushOn(new SendMial(),['email'=>'49783121@qq.com','title'=>'test','content'=>'email test'],'email');
let's vendor\shmilyzxt\queue\queues\DatabaseQueue.php
go to see the code, which is pushOn()
written in the DatabaseQueue
class's parent class vendor\shmilyzxt\queue\base\Queue.php
:
into the queue public function Pushon ($job, $data = ", $queue = null) { //canpush checks if the queue has reached the maximum task amount if ($this->canpush ()) { //beforepush event $this->trigger (Self::event_before_push) before entering the queue; into the queue $ret = $this->push ($job, $data, $queue); Afterpush Event $this->trigger (Self::event_after_push) after entering the queue; return $ret; } else { throw new \exception ("Max jobs number exceed! The max jobs number is {$this->maxjob} "); } }
Note: It's a good idea to look at the Yii2 event class.
About into the queue: $this->push($job, $data, $queue);
, here in the matching queue
class file view, related functions jump, processing the data record into the database. Function direction: getQueue()-->createPayload()-->pushToDatabase()
), the result of the pushOn()
final return data inserted into the database, the success $ret
is 1.
3. Background Run command processing queue, example: php ./yii worker/listen default 10 128 3 0
where default
is the name of the queue, the above pushes a email
queue should be changed email
.
After starting the command, let's look at the code: first execute: The WorkerController
controller actionListen
method, we follow the code into the vendor\shmilyzxt\queue\Worker.php -- listen
method, here is actually always in the loop, the task of performing the operation queue:
/** * Enable a queue background listener task * @param queue $queue * @param string $queueName The name of the listener queue (the queue to which to push the task when Pushon, you need to listen to the queue to get the task) * @param int $attempt Queue task failed attempts, 0 is unlimited * @param int $memory maximum memory allowed * @param int $sleep time interval per detection */public STA Tic function Listen (Queue $queue, $queueName = ' Default ', $attempt = ten, $memory =, $sleep = 3, $delay = 0) { while (true) {try{//databasequeue removes an available task (instance) from the database queue and updates the task $job = $queue->pop ($queueName); }catch (\exception $e) {throw $e; Continue if ($job instanceof Job) {//To determine if the number of execution errors is greater than the number of executions passed in if ($attempt > 0 && $job->getattempts () > $attempt) {$job->fail Ed (); }else{try{ throw new \exception ("Test Failed"); $job->execute (); }catch (\exception $e) {//execution failed, judging whether it was deleted, re-queued if ( ! $job->isdeleted ()) {$job->release ($delay); }}}}else{Self::sleep ($ Sleep); } if (self::memoryexceeded ($memory)) {self::stop (); } } }
Note: $queue->pop($queueName);
vendor\shmilyzxt\queue\queues\DatabaseQueue.php
executing SQL using transactions within a method, and creating vendor\shmilyzxt\queue\jobs\DatabaseJob.php
an instance
//Remove a task public function pop ($queue = null) {$queue = $this->ge Tqueue ($queue); if (!is_null ($this->expire)) {//$this->releasejobsthathavebeenreservedtoolong ($queue); } $tran = $this->connector->begintransaction (); Determine if there is an available task that needs to execute if ($job = $this->getnextavailablejob ($queue)) {$this->markjobasreserved ($job- >ID); $tran->commit (); $config = Array_merge ($this->jobevent, [' class ' = ' Shmilyzxt\queue\jobs\databasejob ', ' Queue ' = $queue, ' job ' = $job, ' queueinstance ' + $this,]); Return \yii::createobject ($config); } $tran->commit (); return false; }
As for: $job->execute();
is DatabaseJob
inherited Job
from the parent class execution, along with the code to find out is yii\base\Component trigger
the execution of the event,
/** * Perform task */public function execute () { //beforeexecute an event before performing a task there is no executable code in jobevent $this- >trigger (Self::event_before_execute, New Jobevent ("job" = $this, ' payload ' + $this->getpayload ()])); $this->resolveandfire ();//method of the task actually performed}
/** * True Task execution method (call hander's Handle method) * @param array $payload * @return void */protected function Resolveandfire () {$payload = $this->getpayload (); $payload = Unserialize ($payload); Deserialization of data $type = $payload [' type ']; $class = $payload [' Job ']; if ($type = = ' closure ' && ($closure = (new Serializer ())->unserialize ($class [1])) instanceof \closure) { $this->handler = $this->gethander ($class [0]); $this->handler->closure = $closure; $this->handler->handle ($this, $payload [' data ']; } else if ($type = = ' Classmethod ') {$payload [' job '][0]-> $payload [' Job '][1] ($this, $payload [' data ']); } else if ($type = = ' Staticmethod ') {$payload [' job '][0]:: $payload [' Job '][1] ($this, $payload [' data ']); } else {//execute ' handle ($job, $data) ' method of ' SendMail ' class $this->handler = $this->gethander ($class); $this->handler->handlE ($this, $payload [' data ']); }//Delete if after executing task (! $this->isdeletedorreleased ()) {$this->delete (); } }
Finally to the SendMail
class of execution handle($job,$data)
, here is the object and data pushed to the queue, and then our processing logic.
Public function handle ($job, $data) { if ($job->getattempts () > 3) { $this->failed ($job); } $payload = $job->getpayload (); Echo ' <pre> ';p rint_r ($payload); $payload is the task data, you get the task data will be able to execute e-mail//todo e- Mail }