From d5e5c715d8208272de1953a8a9279076ed2e63ad Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 28 Feb 2014 03:38:41 +0100 Subject: [PATCH 1/2] Make tests silent --- .../Phrasea/Command/Task/SchedulerPauseTest.php | 4 ++++ .../Phrasea/Command/Task/SchedulerResumeTest.php | 4 ++++ .../Phrasea/Command/Task/SchedulerRunTest.php | 4 ++++ .../Phrasea/Command/Task/SchedulerStateTest.php | 4 ++++ .../Tests/Phrasea/Command/Task/TaskListTest.php | 4 ++++ .../Tests/Phrasea/Command/Task/TaskStartTest.php | 4 ++++ .../Tests/Phrasea/Command/Task/TaskStateTest.php | 4 ++++ .../Tests/Phrasea/Command/Task/TaskStopTest.php | 4 ++++ tests/classes/PhraseanetTestCase.php | 14 ++++++++++++++ 9 files changed, 46 insertions(+) diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerPauseTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerPauseTest.php index ebab942faf..7cef0f79e7 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerPauseTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerPauseTest.php @@ -17,6 +17,10 @@ class SchedulerPauseTest extends \PhraseanetTestCase $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $command = new SchedulerPauseTasks(); $command->setContainer(self::$DI['cli']); $command->execute($input, $output); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerResumeTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerResumeTest.php index 09d0007600..c745102d03 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerResumeTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerResumeTest.php @@ -14,6 +14,10 @@ class SchedulerResumeTest extends \PhraseanetTestCase self::$DI['cli']['task-manager.status']->expects($this->once()) ->method('start'); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerRunTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerRunTest.php index 537f9a0f2d..091e9fbb04 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerRunTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerRunTest.php @@ -17,6 +17,10 @@ class SchedulerRunTest extends \PhraseanetTestCase self::$DI['cli']['task-manager']->expects($this->once()) ->method('start'); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerStateTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerStateTest.php index 9facc5de81..5823501cb4 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerStateTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/SchedulerStateTest.php @@ -11,6 +11,10 @@ class SchedulerStateTest extends \PhraseanetTestCase $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $command = new SchedulerState(); $command->setContainer(self::$DI['cli']); $command->execute($input, $output); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskListTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskListTest.php index eb94a77b37..5317826f3b 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskListTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskListTest.php @@ -14,6 +14,10 @@ class TaskListTest extends \PhraseanetTestCase ->method('getFormatter') ->will($this->returnValue($this->getMock('Symfony\Component\Console\Formatter\OutputFormatterInterface'))); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $command = new TaskList(); $command->setContainer(self::$DI['cli']); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStartTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStartTest.php index 97d452826e..97d574c375 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStartTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStartTest.php @@ -17,6 +17,10 @@ class TaskStartTest extends \PhraseanetTestCase ->with('task_id') ->will($this->returnValue(1)); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $command = new TaskStart(); $command->setContainer(self::$DI['cli']); $command->execute($input, $output); diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStateTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStateTest.php index ef64697c0c..e004187299 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStateTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStateTest.php @@ -12,6 +12,10 @@ class TaskStateTest extends \PhraseanetTestCase $input = $this->getMock('Symfony\Component\Console\Input\InputInterface'); $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface'); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $input->expects($this->any()) ->method('getArgument') ->with('task_id') diff --git a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStopTest.php b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStopTest.php index 748c8a86ed..47dd3f5363 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStopTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Task/TaskStopTest.php @@ -17,6 +17,10 @@ class TaskStopTest extends \PhraseanetTestCase ->with('task_id') ->will($this->returnValue(1)); + self::$DI['cli']['monolog'] = self::$DI['cli']->share(function () { + return $this->createMonologMock(); + }); + $command = new TaskStop(); $command->setContainer(self::$DI['cli']); $command->execute($input, $output); diff --git a/tests/classes/PhraseanetTestCase.php b/tests/classes/PhraseanetTestCase.php index ba7ee9e432..c18ae8029d 100644 --- a/tests/classes/PhraseanetTestCase.php +++ b/tests/classes/PhraseanetTestCase.php @@ -14,6 +14,7 @@ use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\Routing\RequestContext; use Alchemy\Tests\Tools\TranslatorMockTrait; use Alchemy\Phrasea\Authentication\ACLProvider; +use Alchemy\Phrasea\TaskManager\Notifier; use Guzzle\Http\Client as Guzzle; abstract class PhraseanetTestCase extends WebTestCase @@ -294,6 +295,12 @@ abstract class PhraseanetTestCase extends WebTestCase return $generator; })); + $app['task-manager.notifier'] = $app->share($app->extend('task-manager.notifier', function (Notifier $notifier) { + $notifier->setTimeout(0.0001); + + return $notifier; + })); + $app['translator'] = $this->createTranslatorMock(); $app['phraseanet.SE.subscriber'] = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface'); @@ -642,4 +649,11 @@ abstract class PhraseanetTestCase extends WebTestCase { return $this->getMock('Psr\Log\LoggerInterface'); } + + protected function createMonologMock() + { + return $this->getMockBuilder('Monolog\Logger') + ->disableOriginalConstructor() + ->getMock(); + } } From 4d4f7ec5dab28f2989b329b7a6f3c2a098aa3673 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 28 Feb 2014 03:39:28 +0100 Subject: [PATCH 2/2] Improve live notifier response time for tasks list --- lib/Alchemy/Phrasea/Command/Task/TaskList.php | 15 +++--- .../Phrasea/TaskManager/LiveInformation.php | 54 +++++++++++++------ lib/Alchemy/Phrasea/TaskManager/Notifier.php | 24 +++++---- 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/lib/Alchemy/Phrasea/Command/Task/TaskList.php b/lib/Alchemy/Phrasea/Command/Task/TaskList.php index 56d7b47668..db3939cdf4 100644 --- a/lib/Alchemy/Phrasea/Command/Task/TaskList.php +++ b/lib/Alchemy/Phrasea/Command/Task/TaskList.php @@ -28,23 +28,24 @@ class TaskList extends Command { $output->writeln("Querying the task manager..."); $errors = 0; - $probe = $this->container['task-manager.live-information']; + $tasks = $this->container['manipulator.task']->getRepository()->findAll(); + $infos = $this->container['task-manager.live-information']->getTasks($tasks); + $rows = []; - $rows = array_map(function (Task $task) use ($probe, &$errors) { - $info = $probe->getTask($task); - $error = $info['actual'] !== $task->getStatus(); - if ($error) { + foreach ($tasks as $task) { + $info = isset($infos[$task->getId()]) ? $infos[$task->getId()] : ['actual' => null]; + if (true === $error = $info['actual'] !== $task->getStatus()) { $errors ++; } - return [ + $rows[] = [ $task->getId(), $task->getName(), $task->getStatus() !== 'started' ? "".$task->getStatus() . "" : $task->getStatus(), $error ? "".$info['actual']."" : $info['actual'], $info['process-id'], ]; - }, $this->container['manipulator.task']->getRepository()->findAll()); + } $this ->getHelperSet()->get('table') diff --git a/lib/Alchemy/Phrasea/TaskManager/LiveInformation.php b/lib/Alchemy/Phrasea/TaskManager/LiveInformation.php index 9c5d73827f..9712ce363c 100644 --- a/lib/Alchemy/Phrasea/TaskManager/LiveInformation.php +++ b/lib/Alchemy/Phrasea/TaskManager/LiveInformation.php @@ -32,14 +32,7 @@ class LiveInformation */ public function getManager($throwException = false) { - try { - $data = $this->notifier->notify(Notifier::MESSAGE_INFORMATIONS, 2); - } catch (RuntimeException $e) { - if($throwException) { - throw $e; - } - $data = []; - } + $data = $this->query($throwException); return [ 'configuration' => $this->status->getStatus(), @@ -55,14 +48,33 @@ class LiveInformation */ public function getTask(Task $task, $throwException = false) { - try { - $data = $this->notifier->notify(Notifier::MESSAGE_INFORMATIONS, 2); - } catch (RuntimeException $e) { - if($throwException) { - throw $e; - } - $data = []; + $data = $this->query($throwException); + + return $this->formatTask($task, $data); + } + + /** + * Returns live informations about some tasks. + * + * @param Task[] $tasks + * @param boolean $throwException + * + * @return array + */ + public function getTasks($tasks, $throwException = false) + { + $data = $this->query($throwException); + + $ret = []; + foreach ($tasks as $task) { + $ret[$task->getId()] = $this->formatTask($task, $data); } + + return $ret; + } + + private function formatTask(Task $task, $data) + { $taskData = (isset($data['jobs']) && isset($data['jobs'][$task->getId()])) ? $data['jobs'][$task->getId()] : []; return [ @@ -71,4 +83,16 @@ class LiveInformation 'process-id' => isset($taskData['process-id']) ? $taskData['process-id'] : null, ]; } + + private function query($throwException) + { + try { + return $this->notifier->notify(Notifier::MESSAGE_INFORMATIONS); + } catch (RuntimeException $e) { + if($throwException) { + throw $e; + } + return []; + } + } } diff --git a/lib/Alchemy/Phrasea/TaskManager/Notifier.php b/lib/Alchemy/Phrasea/TaskManager/Notifier.php index 25c9ca43a4..124f5c6f7d 100644 --- a/lib/Alchemy/Phrasea/TaskManager/Notifier.php +++ b/lib/Alchemy/Phrasea/TaskManager/Notifier.php @@ -33,40 +33,46 @@ class Notifier /** @var LoggerInterface */ private $logger; + /** @var integer */ + private $timeout = 2; + public function __construct(\ZMQSocket $socket, LoggerInterface $logger) { $this->socket = $socket; $this->logger = $logger; } + public function setTimeout($timeout) + { + if ($timeout <= 0) { + throw new \InvalidArgumentException('Timeout must be a positive value'); + } + $this->timeout = (float) $timeout; + } + /** * Notifies the task manager given a message constant, see MESSAGE_* constants. * * @param string $message - * @param integer $timeout * * @return mixed|null The return value of the task manager. * * @throws RuntimeException in case notification did not occur within the timeout. */ - public function notify($message, $timeout = 1) + public function notify($message) { - if ($timeout <= 0) { - throw new \InvalidArgumentException('Timeout must be a positive value'); - } - try { $command = $this->createCommand($message); $this->socket->send($command); - $limit = microtime(true) + $timeout; + $limit = microtime(true) + $this->timeout; while (microtime(true) < $limit && false === $result = $this->socket->recv(\ZMQ::MODE_NOBLOCK)) { usleep(1000); } if (false === $result) { - $this->logger->error(sprintf('Unable to notify the task manager with message "%s" within timeout of %d seconds', $message, $timeout)); + $this->logger->error(sprintf('Unable to notify the task manager with message "%s" within timeout of %d seconds', $message, $this->timeout)); throw new RuntimeException('Unable to retrieve information.'); } @@ -80,7 +86,7 @@ class Notifier return $data['reply']; } catch (\ZMQSocketException $e) { - $this->logger->error(sprintf('Unable to notify the task manager with message "%s" within timeout of %d seconds', $message, $timeout), array('exception' => $e)); + $this->logger->error(sprintf('Unable to notify the task manager with message "%s" within timeout of %d seconds', $message, $this->timeout), array('exception' => $e)); throw new RuntimeException('Unable to retrieve information.', $e->getCode(), $e); } }