/**
  * @param DeferredQueueCompleteEvent $event
  */
 public static function handleEvent($event)
 {
     //else we have unfinished task
     if ($event->queue->exit_code != 0) {
         return;
     }
     /** @var DeferredGroup $group */
     if (null === ($group = DeferredGroup::loadModel($event->queue->deferred_group_id))) {
         return;
     }
     switch ($group->name) {
         case ExtensionsManager::COMPOSER_INSTALL_DEFERRED_GROUP:
         case ExtensionsManager::COMPOSER_UNINSTALL_DEFERRED_GROUP:
             ExtensionFileWriter::updateConfig();
             break;
         default:
             return;
     }
 }
 /**
  * @param $group_id
  * @param DeferredQueue[]  $queue
  * @return DeferredQueue[]
  */
 private function processGroup($group_id, $queue)
 {
     $parallel_run_allowed = true;
     $group = DeferredGroup::findById($group_id);
     if (is_object($group) === true) {
         $parallel_run_allowed = boolval($group->allow_parallel_run);
         // check if group set to run only latest command
         if ($group->run_last_command_only) {
             $latestQueue = null;
             foreach ($queue as $item) {
                 if ($latestQueue === null) {
                     $latestQueue = $item;
                 }
                 if ($item->initiated_date >= $latestQueue->initiated_date) {
                     $latestQueue = $item;
                 }
             }
             foreach ($queue as $item) {
                 if ($item->id !== $latestQueue->id) {
                     $item->complete();
                 }
             }
             $queue = [$latestQueue];
         }
     }
     if ($this->forceNoParallel === true) {
         $parallel_run_allowed = false;
     }
     if ($parallel_run_allowed === true && $group_id > 0) {
         $this->getMutex()->release('DeferredQueueGroup:' . $group_id);
     }
     $this->trigger(self::EVENT_DEFERRED_QUEUE_GROUP_STARTED, new DeferredGroupEvent($group_id));
     foreach ($queue as &$item) {
         $process = $this->runQueueItem($item);
         $this->trigger(self::EVENT_DEFERRED_QUEUE_ITEM_STARTED, new DeferredQueueEvent($item->deferred_group_id, $item->id));
         $this->stdout("Executing process -> " . $process->getCommandLine() . "\n", Console::FG_YELLOW);
         if (isset(Yii::$app->params['deferred.env'])) {
             $process->setEnv(Yii::$app->params['deferred.env']);
         }
         $process->setTimeout(1800);
         $process->setIdleTimeout(1800);
         $item->setProcess($process);
         if ($parallel_run_allowed === true) {
             try {
                 $process->start();
             } catch (\Exception $e) {
                 $item->status = DeferredQueue::STATUS_FAILED;
                 $item->exit_code = $item->getProcess()->getExitCode();
             }
         } else {
             try {
                 $process->run();
             } catch (\Exception $e) {
                 $item->status = DeferredQueue::STATUS_FAILED;
                 $item->exit_code = $item->getProcess()->getExitCode();
             }
             $this->immediateNotification($group, $item);
         }
     }
     if ($parallel_run_allowed === true) {
         foreach ($queue as &$item) {
             try {
                 $item->getProcess()->wait();
             } catch (\Exception $e) {
                 $item->status = DeferredQueue::STATUS_FAILED;
                 $item->exit_code = $item->getProcess()->getExitCode();
             }
             $this->immediateNotification($group, $item);
         }
         $this->stdout("All processes complete\n", Console::FG_YELLOW);
     } elseif ($group_id > 0) {
         $this->getMutex()->release('DeferredQueueGroup:' . $group_id);
     }
     $this->grouppedNotification($group, $queue);
     return $queue;
 }
 public function testHandleBadQueue()
 {
     TestConfigCleaner::removeExtFile();
     $this->assertFalse(TestConfigCleaner::checkExtFile());
     Yii::setAlias('@vendor', realpath(__DIR__ . '/../../testapp/vendor'));
     $group = new DeferredGroup();
     $group->loadDefaultValues();
     $group->name = ExtensionsManager::ACTIVATE_DEFERRED_TASK;
     $group->group_notifications = 0;
     $group->save();
     $queue = new DeferredQueue([]);
     $queue->deferred_group_id = $group->id;
     $process = new Process('pwd > /dev/null');
     $process->run();
     $queue->setProcess($process);
     $queue->exit_code = 1;
     $event = new DeferredQueueCompleteEvent($queue);
     DeferredQueueCompleteHandler::handleEvent($event);
     $this->assertFalse(TestConfigCleaner::checkExtFile());
 }
 /**
  * Returns corresponding DeferredGroup model instance
  * @return DeferredGroup|null
  */
 public function getGroup()
 {
     return isset($this->deferred_group_id) ? DeferredGroup::findById($this->deferred_group_id) : null;
 }
 /**
  * Builds ReportingTask and places it into certain group. Also if group is not exists yet, it will be created
  * with necessary parameters, such as group_notifications=0.
  *
  * @param array $command
  * @param string $groupName
  * @return ReportingTask
  */
 public static function buildTask($command, $groupName)
 {
     $groupConfig = ['email_notification' => 0, 'allow_parallel_run' => 0, 'group_notifications' => 0, 'run_last_command_only' => 0];
     if (null === ($group = DeferredGroup::findOne(['name' => $groupName]))) {
         $group = new DeferredGroup();
         $group->loadDefaultValues();
         $group->setAttributes($groupConfig);
         $group->name = $groupName;
         $group->save();
     }
     if ((int) $group->group_notifications !== 0) {
         // otherwise DeferredController 'deferred-queue-complete' event will not trigger
         // and we'll unable to write config
         $group->setAttributes($groupConfig);
         $group->save(array_keys($groupConfig));
     }
     $task = new ReportingTask();
     $task->model()->deferred_group_id = $group->id;
     $task->cliCommand(DeferredHelper::getPhpBinary(), $command);
     return $task;
 }