diff --git a/CHANGELOG-3.1.md b/CHANGELOG-3.1.md
index 5dc440f..57fb645 100644
--- a/CHANGELOG-3.1.md
+++ b/CHANGELOG-3.1.md
@@ -33,3 +33,5 @@ https://github.com/FriendsOfSymfony/FOSElasticaBundle/compare/v3.0.4...v3.1.0
that property while transforming. Combined with the above POST_TRANSFORM event
developers can now create calculated dynamic properties on Elastica documents
for indexing. #794
+ * Fixed a case where ProgressCommand would always ignore errors regardless of
+ --ignore-errors being passed or not.
diff --git a/Command/PopulateCommand.php b/Command/PopulateCommand.php
index 5817c4c..e4ed4c9 100644
--- a/Command/PopulateCommand.php
+++ b/Command/PopulateCommand.php
@@ -23,6 +23,11 @@ class PopulateCommand extends ContainerAwareCommand
*/
private $indexManager;
+ /**
+ * @var ProgressClosureBuilder
+ */
+ private $progressClosureBuilder;
+
/**
* @var ProviderRegistry
*/
@@ -47,31 +52,39 @@ class PopulateCommand extends ContainerAwareCommand
->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'Sleep time between persisting iterations (microseconds)', 0)
->addOption('batch-size', null, InputOption::VALUE_REQUIRED, 'Index packet size (overrides provider config option)')
->addOption('ignore-errors', null, InputOption::VALUE_NONE, 'Do not stop on errors')
+ ->addOption('no-overwrite-format', null, InputOption::VALUE_NONE, 'Prevent this command from overwriting ProgressBar\'s formats')
->setDescription('Populates search indexes from providers')
;
}
/**
- * @see Symfony\Component\Console\Command\Command::initialize()
+ * {@inheritDoc}
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->indexManager = $this->getContainer()->get('fos_elastica.index_manager');
$this->providerRegistry = $this->getContainer()->get('fos_elastica.provider_registry');
$this->resetter = $this->getContainer()->get('fos_elastica.resetter');
+ $this->progressClosureBuilder = new ProgressClosureBuilder();
+
+ if (!$input->getOption('no-overwrite-format')) {
+ ProgressBar::setFormatDefinition('normal', " %current%/%max% [%bar%] %percent:3s%%\n%message%");
+ ProgressBar::setFormatDefinition('verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%\n%message%");
+ ProgressBar::setFormatDefinition('very_verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%\n%message%");
+ ProgressBar::setFormatDefinition('debug', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%\n%message%");
+ }
}
/**
- * @see Symfony\Component\Console\Command\Command::execute()
+ * {@inheritDoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $index = $input->getOption('index');
- $type = $input->getOption('type');
- $reset = !$input->getOption('no-reset');
- $options = $input->getOptions();
-
- $options['ignore-errors'] = $input->hasOption('ignore-errors');
+ $index = $input->getOption('index');
+ $type = $input->getOption('type');
+ $reset = !$input->getOption('no-reset');
+ $options = $input->getOptions();
+ $options['ignore-errors'] = $input->getOption('ignore-errors');
if ($input->isInteractive() && $reset && $input->getOption('offset')) {
/** @var DialogHelper $dialog */
@@ -109,73 +122,11 @@ class PopulateCommand extends ContainerAwareCommand
*/
private function doPopulateType(ProviderInterface $provider, OutputInterface $output, $input, $type, $options)
{
- $loggerClosure = $this->getLoggerClosure($output, $input, $type);
+ $loggerClosure = $this->progressClosureBuilder->build($output, 'Populating', $input, $type);
$provider->populate($loggerClosure, $options);
}
- /**
- * Builds a loggerClosure to be called from inside the Provider to update the command
- * line.
- *
- * @param OutputInterface $output
- * @param string $index
- * @param string $type
- * @return callable
- */
- private function getLoggerClosure(OutputInterface $output, $index, $type)
- {
- if (!class_exists('Symfony\Component\Console\Helper\ProgressBar')) {
- $lastStep = null;
- $current = 0;
-
- return function ($increment, $totalObjects) use ($output, $index, $type, &$lastStep, &$current) {
- if ($current + $increment > $totalObjects) {
- $increment = $totalObjects - $current;
- }
-
- $currentTime = microtime(true);
- $timeDifference = $currentTime - $lastStep;
- $objectsPerSecond = $lastStep ? ($increment / $timeDifference) : $increment;
- $lastStep = $currentTime;
- $current += $increment;
- $percent = 100 * $current / $totalObjects;
-
- $output->writeln(sprintf(
- 'Populating %s/%s %0.1f%% (%d/%d), %d objects/s (RAM: current=%uMo peak=%uMo)',
- $index,
- $type,
- $percent,
- $current,
- $totalObjects,
- $objectsPerSecond,
- round(memory_get_usage() / (1024 * 1024)),
- round(memory_get_peak_usage() / (1024 * 1024))
- ));
- };
- }
-
- ProgressBar::setFormatDefinition('normal', " %current%/%max% [%bar%] %percent:3s%%\n%message%");
- ProgressBar::setFormatDefinition('verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%\n%message%");
- ProgressBar::setFormatDefinition('very_verbose', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%\n%message%");
- ProgressBar::setFormatDefinition('debug', " %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%\n%message%");
- $progress = null;
-
- return function ($increment, $totalObjects) use (&$progress, $output, $index, $type) {
- if (null === $progress) {
- $progress = new ProgressBar($output, $totalObjects);
- $progress->start();
- }
-
- $progress->setMessage(sprintf('Populating %s/%s', $index, $type));
- $progress->advance($increment);
-
- if ($progress->getProgressPercent() >= 1.0) {
- $progress->finish();
- }
- };
- }
-
/**
* Recreates an index, populates its types, and refreshes the index.
*
diff --git a/Command/ProgressClosureBuilder.php b/Command/ProgressClosureBuilder.php
new file mode 100644
index 0000000..53bcb18
--- /dev/null
+++ b/Command/ProgressClosureBuilder.php
@@ -0,0 +1,101 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FOS\ElasticaBundle\Command;
+
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ProgressClosureBuilder
+{
+ /**
+ * Builds a loggerClosure to be called from inside the Provider to update the command
+ * line.
+ *
+ * @param OutputInterface $output
+ * @param string $action
+ * @param string $index
+ * @param string $type
+ * @return callable
+ */
+ public function build(OutputInterface $output, $action, $index, $type)
+ {
+ if (!class_exists('Symfony\Component\Console\Helper\ProgressBar') ||
+ !is_callable(array('Symfony\Component\Console\Helper\ProgressBar', 'getProgress'))) {
+ return $this->buildLegacy($output, $action, $index, $type);
+ }
+
+ $progress = null;
+
+ return function ($increment, $totalObjects, $message = null) use (&$progress, $output, $action, $index, $type) {
+ if (null === $progress) {
+ $progress = new ProgressBar($output, $totalObjects);
+ $progress->start();
+ }
+
+ if (null !== $message) {
+ $progress->clear();
+ $output->writeln(sprintf('%s %s', $action, $message));
+ $progress->display();
+ }
+
+ $progress->setMessage(sprintf('%s %s/%s', $action, $index, $type));
+ $progress->advance($increment);
+ };
+ }
+
+ /**
+ * Builds a legacy closure that outputs lines for each step. Used in cases
+ * where the ProgressBar component doesnt exist or does not have the correct
+ * methods to support what we need.
+ *
+ * @param OutputInterface $output
+ * @param string $action
+ * @param string $index
+ * @param string $type
+ * @return callable
+ */
+ private function buildLegacy(OutputInterface $output, $action, $index, $type)
+ {
+ $lastStep = null;
+ $current = 0;
+
+ return function ($increment, $totalObjects, $message = null) use ($output, $action, $index, $type, &$lastStep, &$current) {
+ if ($current + $increment > $totalObjects) {
+ $increment = $totalObjects - $current;
+ }
+
+ if (null !== $message) {
+ $output->writeln(sprintf('%s %s', $action, $message));
+ }
+
+ $currentTime = microtime(true);
+ $timeDifference = $currentTime - $lastStep;
+ $objectsPerSecond = $lastStep ? ($increment / $timeDifference) : $increment;
+ $lastStep = $currentTime;
+ $current += $increment;
+ $percent = 100 * $current / $totalObjects;
+
+ $output->writeln(sprintf(
+ '%s %s/%s %0.1f%% (%d/%d), %d objects/s (RAM: current=%uMo peak=%uMo)',
+ $action,
+ $index,
+ $type,
+ $percent,
+ $current,
+ $totalObjects,
+ $objectsPerSecond,
+ round(memory_get_usage() / (1024 * 1024)),
+ round(memory_get_peak_usage() / (1024 * 1024))
+ ));
+ };
+ }
+}
diff --git a/Doctrine/AbstractProvider.php b/Doctrine/AbstractProvider.php
index 80d0716..2d5d264 100644
--- a/Doctrine/AbstractProvider.php
+++ b/Doctrine/AbstractProvider.php
@@ -67,7 +67,7 @@ abstract class AbstractProvider extends BaseAbstractProvider
$this->objectPersister->insertMany($objects);
} catch(BulkResponseException $e) {
if ($loggerClosure) {
- $loggerClosure(sprintf('%s',$e->getMessage()));
+ $loggerClosure($batchSize, $nbObjects, sprintf('%s', $e->getMessage()));
}
}
}
diff --git a/Provider/ProviderInterface.php b/Provider/ProviderInterface.php
index e8d7ea4..188f2a1 100644
--- a/Provider/ProviderInterface.php
+++ b/Provider/ProviderInterface.php
@@ -12,6 +12,11 @@ interface ProviderInterface
/**
* Persists all domain objects to ElasticSearch for this provider.
*
+ * The closure can expect 2 or 3 arguments:
+ * * The step size
+ * * The total number of objects
+ * * A message to output in error conditions (not normally provided)
+ *
* @param \Closure $loggerClosure
* @param array $options
* @return