Skip to content

Commit 23e72f6

Browse files
committed
added command for daemons on tailable cursors
1 parent afa2b16 commit 23e72f6

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Doctrine MongoDBBundle
5+
*
6+
* The code was originally distributed inside the Symfony framework.
7+
*
8+
* (c) Fabien Potencier <fabien@symfony.com>
9+
* (c) Doctrine Project
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Doctrine\Bundle\MongoDBBundle\Command;
16+
17+
use Doctrine\Bundle\MongoDBBundle\Cursor\TailableCursorProcessorInterface;
18+
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
19+
use Symfony\Component\Console\Input\InputArgument;
20+
use Symfony\Component\Console\Input\InputOption;
21+
use Symfony\Component\Console\Input\InputInterface;
22+
use Symfony\Component\Console\Output\OutputInterface;
23+
24+
/**
25+
* Command helping to configure a daemon listening to a tailable cursor. Works only with capped collections.
26+
*
27+
* @author Jonathan H. Wage <jonwage@gmail.com>
28+
* @author Bilal Amarni <bilal.amarni@gmail.com>
29+
*/
30+
class TailCursorDoctrineODMCommand extends ContainerAwareCommand
31+
{
32+
protected function configure()
33+
{
34+
$this
35+
->setName('doctrine:mongodb:tail-cursor')
36+
->setDescription('Tails a mongodb cursor and processes the documents that come through')
37+
->addArgument('document', InputArgument::REQUIRED, 'The document we are going to tail the cursor for.')
38+
->addArgument('finder', InputArgument::REQUIRED, 'The repository finder method which returns the cursor to tail.')
39+
->addArgument('processor', InputArgument::REQUIRED, 'The service id to use to process the documents.')
40+
->addOption('sleep-time', null, InputOption::VALUE_REQUIRED, 'The number of seconds to wait between two checks.', 10)
41+
;
42+
}
43+
44+
protected function execute(InputInterface $input, OutputInterface $output)
45+
{
46+
$dm = $this->getContainer()->get('doctrine.odm.mongodb.document_manager');
47+
$repository = $dm->getRepository($input->getArgument('document'));
48+
$repositoryReflection = new \ReflectionClass(get_class($repository));
49+
$documentReflection = $repository->getDocumentManager()->getMetadataFactory()->getMetadataFor($input->getArgument('document'))->getReflectionClass();
50+
$processor = $this->getContainer()->get($input->getArgument('processor'));
51+
$sleepTime = $input->getOption('sleep-time');
52+
53+
if (!$processor instanceof TailableCursorProcessorInterface) {
54+
throw new \InvalidArgumentException('A tailable cursor processor must implement the ProcessorInterface.');
55+
}
56+
57+
$processorReflection = new \ReflectionClass(get_class($processor));
58+
$method = $input->getArgument('finder');
59+
60+
$output->writeln(sprintf('Getting cursor for <info>%s</info> from <info>%s#%s</info>', $input->getArgument('document'), $repositoryReflection->getShortName(), $method));
61+
62+
$cursor = $repository->$method();
63+
64+
while (true) {
65+
while (!$cursor->hasNext()) {
66+
$output->writeln('<comment>Nothing found, waiting to try again</comment>');
67+
// read all results so far, wait for more
68+
sleep($sleepTime);
69+
}
70+
$cursor->next();
71+
$document = $cursor->current();
72+
$id = $document->getId();
73+
74+
$output->writeln(sprintf('Processing <info>%s</info> with id of <info>%s</info>', $documentReflection->getShortName(), (string) $id));
75+
$output->writeln(sprintf(' <info>%s</info><comment>#</comment><info>process</info>(<info>%s</info> <comment>$document</comment>)', $processorReflection->getShortName(), $documentReflection->getShortName()));
76+
77+
try {
78+
$processor->process($document);
79+
} catch (\Exception $e) {
80+
$output->writeln(sprintf('Error occurred while processing document: <error>%s</error>', $e->getMessage()));
81+
continue;
82+
}
83+
84+
$dm->flush();
85+
$dm->clear();
86+
}
87+
}
88+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Doctrine MongoDBBundle
5+
*
6+
* The code was originally distributed inside the Symfony framework.
7+
*
8+
* (c) Fabien Potencier <fabien@symfony.com>
9+
* (c) Doctrine Project
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
namespace Doctrine\Bundle\MongoDBBundle\Cursor;
16+
17+
/**
18+
* Contract for tailable cursor processors.
19+
*
20+
* @author Jonathan H. Wage <jonwage@gmail.com>
21+
*/
22+
interface TailableCursorProcessorInterface
23+
{
24+
function process($document);
25+
}

0 commit comments

Comments
 (0)