Step 24: Running Crons
Running Crons
Comments marked as spam or rejected by the admin are kept in the database as the admin might want to inspect them for a little while. But they should probably be removed after some time. Keeping them around for a week after their creation is probably enough.
Create some utility methods in the comment repository to find rejected comments, count them, and delete them:
patch_file
Tip
For more complex queries, it is sometimes useful to have a look at the generated SQL statements (they can be found in the logs and in the profiler for Web requests).
7 days? We could have chosen another number, maybe 10 or 20. This number might evolve over time. We have decided to store it as a constant on the class, but we might have stored it as a parameter in the container, or we might have even defined it as an environment variable.
- If the value is sensitive (passwords, API tokens, …), use the Symfony secret storage or a Vault;
- If the value is dynamic and you should be able to change it without re-deploying, use an environment variable;
- If the value can be different between environments, use a container parameter;
- For everything else, store the value in code, like in a class constant.
Removing the old comments is the perfect task for a cron job. It should be done on a regular basis, and a little delay does not have any major impact.
Create a CLI command named by creating a src/Command/CommentCleanupCommand.php
file:
src/Command/CommentCleanupCommand.php
namespace App\Command;
use App\Repository\CommentRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class CommentCleanupCommand extends Command
{
private $commentRepository;
public function __construct(CommentRepository $commentRepository)
{
$this->commentRepository = $commentRepository;
parent::__construct();
}
protected function configure()
{
->setDescription('Deletes rejected and spam comments from the database')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Dry run')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
if ($input->getOption('dry-run')) {
$io->note('Dry mode enabled');
$count = $this->commentRepository->countOldRejected();
} else {
$count = $this->commentRepository->deleteOldRejected();
}
$io->success(sprintf('Deleted "%d" old rejected/spam comments.', $count));
return 0;
}
}
All application commands are registered alongside Symfony built-in ones and they are all accessible via symfony console
. As the number of available commands can be large, you should namespace them. By convention, the application commands should be stored under the app
namespace. Add any number of sub-namespaces by separating them by a colon (:
).
A command gets the input (arguments and options passed to the command) and you can use the output to write to the console.
Clean up the database by running the command:
patch_file
--- a/.symfony.cloud.yaml
+++ b/.symfony.cloud.yaml
@@ -52,6 +52,15 @@ hooks:
(>&2 symfony-deploy)
+crons:
+ comment_cleanup:
+ # Cleanup every night at 11.50 pm (UTC).
+ spec: '50 23 * * *'
+ cmd: |
+ if [ "$SYMFONY_BRANCH" = "master" ]; then
+ croncape symfony console app:comment:cleanup
+ fi
+
workers:
messages:
commands:
The crons
section defines all cron jobs. Each cron runs according to a spec
schedule.
The croncape
utility monitors the execution of the command and sends an email to the addresses defined in the MAILTO
environment variable if the command returns any exit code different than 0
.
Configure the MAILTO
environment variable:
You can force a cron to run on your local machine:
$ symfony cron comment_cleanup
Note that crons are set up on all SymfonyCloud branches. If you don’t want to run some on non-production environments, check the environment variable:
This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.