Eseguire Cron
I cron sono utili per svolgere attività di manutenzione. A differenza dei worker, hanno un orario di esecuzione predefinito, e vengono eseguiti per un breve periodo di tempo.
Pulire i commenti
I commenti contrassegnati come spam o rifiutati dall'amministratore sono conservati nel database, in quanto l'amministratore potrebbe volerli ispezionare per un po' di tempo. Ma probabilmente dovrebbero essere rimossi in un secondo momento. Probabilmente è sufficiente conservarli per una settimana.
Creare alcuni metodi nel repository dei commenti: per trovare i commenti rifiutati, per contarli e per cancellarli:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
--- a/src/Repository/CommentRepository.php
+++ b/src/Repository/CommentRepository.php
@@ -6,6 +6,7 @@ use App\Entity\Comment;
use App\Entity\Conference;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
+use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
@@ -16,6 +17,8 @@ use Doctrine\ORM\Tools\Pagination\Paginator;
*/
class CommentRepository extends ServiceEntityRepository
{
+ private const DAYS_BEFORE_REJECTED_REMOVAL = 7;
+
public const PAGINATOR_PER_PAGE = 2;
public function __construct(ManagerRegistry $registry)
@@ -23,6 +26,29 @@ class CommentRepository extends ServiceEntityRepository
parent::__construct($registry, Comment::class);
}
+ public function countOldRejected(): int
+ {
+ return $this->getOldRejectedQueryBuilder()->select('COUNT(c.id)')->getQuery()->getSingleScalarResult();
+ }
+
+ public function deleteOldRejected(): int
+ {
+ return $this->getOldRejectedQueryBuilder()->delete()->getQuery()->execute();
+ }
+
+ private function getOldRejectedQueryBuilder(): QueryBuilder
+ {
+ return $this->createQueryBuilder('c')
+ ->andWhere('c.state = :state_rejected or c.state = :state_spam')
+ ->andWhere('c.createdAt < :date')
+ ->setParameters([
+ 'state_rejected' => 'rejected',
+ 'state_spam' => 'spam',
+ 'date' => new \DateTimeImmutable(-self::DAYS_BEFORE_REJECTED_REMOVAL.' days'),
+ ])
+ ;
+ }
+
public function getCommentPaginator(Conference $conference, int $offset): Paginator
{
$query = $this->createQueryBuilder('c')
Tip
Per le query più complesse, a volte è utile dare un'occhiata alle istruzioni SQL generate (si possono trovare nei log e nel profiler per le richieste web).
Utilizzo delle costanti di classe, dei parametri del container e delle variabili d'ambiente
Sette giorni? Avremmo potuto scegliere un altro numero, forse dieci o venti. Questo numero potrebbe evolvere nel tempo. Abbiamo deciso di memorizzarlo come costante di classe, ma avremmo potuto memorizzarlo come parametro nel container o ancora come variabile d'ambiente.
Ecco alcune regole empiriche per decidere quale astrazione usare:
- Se il valore deve essere mantenuto segreto (password, token API, ...), usare il portachiavi di Symfony o un sistema esterno di portachiavi;
- Se il valore è dinamico e lo si può cambiare senza dover rifare un deploy, usare una variabile d'ambiente;
- Se il valore può essere diverso da un ambiente all'altro, usare un parametro del container;
- Per tutto il resto, memorizzare il valore nel codice, come costante di classe.
Creazione di un comando CLI
La rimozione dei vecchi commenti è il compito perfetto per un cron. Andrebbe fatta su base regolare e un piccolo ritardo non ha un impatto significativo.
Creare un comando CLI denominato app:comment:cleanup
, creando un file src/Command/CommentCleanupCommand.php
:
Tutti i comandi dell'applicazione sono registrati insieme a quelli integrati in Symfony e sono tutti accessibili tramite symfony console
. Poiché il numero di comandi disponibili potrebbe essere elevato, dovremmo raggrupparli per nome. Per convenzione, i comandi dell'applicazione vengono raggruppati sotto il namespace app
. Si possono aggiungere ulteriori namespace, separati con i due punti (:
).
Un comando riceve un input (parametri e opzioni passati al comando) ed è possibile utilizzare il suo output per scrivere nella console.
Pulire il database eseguendo il comando:
1
$ symfony console app:comment:cleanup
Impostare un cron su Platform.sh
Una delle cose belle di Platform.sh è che la maggior parte della configurazione è memorizzata in un unico file: .platform.app.yaml
. Il container web, i worker e i cron sono descritti insieme, per facilitare la manutenzione:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
--- a/.platform.app.yaml
+++ b/.platform.app.yaml
@@ -60,6 +60,14 @@ crons:
spec: '50 23 * * *'
cmd: if [ "$PLATFORM_BRANCH" = "main" ]; then croncape php-security-checker; fi
+ comment_cleanup:
+ # Cleanup every night at 11.50 pm (UTC).
+ spec: '50 23 * * *'
+ cmd: |
+ if [ "$PLATFORM_BRANCH" = "master" ]; then
+ croncape symfony console app:comment:cleanup
+ fi
+
workers:
messenger:
commands:
La sezione crons
definisce tutti i processi di cron. Ogni cron funziona secondo quanto indicato in spec
.
Il programma croncape
controlla l'esecuzione del comando e, se questo restituisce un codice di uscita diverso da 0
, invia un'email agli indirizzi definiti nella variabile d'ambiente MAILTO
.
Configurare la variabile d'ambiente MAILTO
:
1
$ symfony cloud:variable:create --sensitive=1 --level=project -y --name=env:MAILTO --value=ops@example.com
Si noti che i cron sono impostati su tutti i branch di Platform.sh. Se si desidera escluderne qualcuno in ambienti non di produzione, controllare la variabile d'ambiente $PLATFORM_BRANCH
:
1 2 3
if [ "$PLATFORM_BRANCH" = "master" ]; then
croncape symfony app:invoices:send
fi