Cron を実行する
Cron は、メンテナンスタスクに便利です。ワーカーと異なり、短い期間でスケジュール実行されます。
コメントをクリーンアップする
スパムとして判定されたコメント、管理者によって拒否されたコメントは、データベース内に残っているので、管理者は少しの間調べることがあるかもしれません。しかし、ある程度時間が経てば、これらのコメントは消されるべきです。コメントが作成されてから1週間くらい残しておくのがちょうど良いでしょう。
コメントリポジトリに、拒否されたコメントを取得したり、数を数えたり、削除したりするためのユーティリティメソッドを追加しましょう:
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
@@ -5,7 +5,9 @@ namespace App\Repository;
use App\Entity\Comment;
use App\Entity\Conference;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Persistence\ManagerRegistry;
+use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
@@ -18,6 +20,8 @@ use Doctrine\ORM\Tools\Pagination\Paginator;
*/
class CommentRepository extends ServiceEntityRepository
{
+ private const DAYS_BEFORE_REJECTED_REMOVAL = 7;
+
public const COMMENTS_PER_PAGE = 2;
public function __construct(ManagerRegistry $registry)
@@ -25,6 +29,27 @@ 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')
+ ->setParameter('state_rejected', 'rejected')
+ ->setParameter('state_spam', 'spam')
+ ->setParameter('date', new \DateTimeImmutable(-self::DAYS_BEFORE_REJECTED_REMOVAL.' days'))
+ ;
+ }
+
public function getCommentPaginator(Conference $conference, int $offset): Paginator
{
$query = $this->createQueryBuilder('c')
Tip
より複雑なクエリーが必要な際は、生成されたSQLステートメントを確認すると便利です(これらはログや、Webリクエストのプロファイラで見つけることができます)。
クラス定数、コンテナのパラメーター、環境変数を使用する
7日としましたが、10日にするかもしれないですし、20日にするかもしれません。この数値は時間と共に変更される可能性があります。ここでは、クラスの定数として格納すると決めましたが、コンテナのパラメータとして格納するかもしれませんし、環境変数として定義するかもしれません。
どのアブストラクションを使用するか決める経験則は以下の通りです:
- 値が注意が必要なもの(パスワードや APIトークン)だった際は、 Symfony の シークレットストレージ かヴォールトを使用してください;
- 値が動的に変わり、デプロイすることなく 変更したいときは、 環境変数 を使用してください;
- 値が環境によって異なっていれば、 コンテナパラメーター を使用してください;
- その他のケースでは、 クラス定数 のようにコードに値を格納してください。
CLI コマンドを作成する
古くなったコメントを削除するのは、Cron ジョブの良いタスクです。そして、定期的に実行されるべきで、少し遅延しても大きな影響はありません。
src/Command/CommentCleanupCommand.php
ファイルを作成して、app:comment:cleanup
と命名した CLI コマンドを作成します:
Symfony にビルトインされている全てのアプリケーションのコマンドは、 symfony console
からアクセス可能です。使用可能なコマンドの数は、とても多くなるので、ネームスペースを付けてください。規約として、アプリケーションコマンドは、 app
ネームスペース以下に格納してください。そして、コロン(:
) で区切りを付けて、サブネームスペースを付けてください。サブネームスペースは1つでも複数個でも良いです。
コマンドは input (コマンドから渡ってきた引数やオプション)を取得し、 コンソールに書き出すのに output を使うことができます。
このコマンドを実行してデータベースをクリーンアップしてください:
1
$ symfony console app:comment:cleanup
Platform.sh で Cron をセットアップする
Platform.sh の便利な点の一つは、ほとんどの設定は .platform.app.yaml
に格納されていることです。メンテナンスを楽にするために、Webコンテナ、ワーカー、Cron ジョブが一緒に記述されています:
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
@@ -61,6 +61,14 @@ crons:
spec: '50 23 * * *'
cmd: if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then croncape php-security-checker; fi
+ comment_cleanup:
+ # Cleanup every night at 11.50 pm (UTC).
+ spec: '50 23 * * *'
+ cmd: |
+ if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
+ croncape symfony console app:comment:cleanup
+ fi
+
workers:
messenger:
commands:
crons
セクションは、全ての Cron ジョブを定義しています。各 Cron は、 spec
スケジュールに応じて実行されます。
croncap
ユーティリティは、コマンドの実行をモニターして、コマンドが 0
でないコードで終わったときに、環境変数 MAILTO
に定義されているメールアドレスにメールを送ります。
MAILTO
環境変数を設定する
1
$ symfony cloud:variable:create --sensitive=1 --level=project -y --name=env:MAILTO --value=ops@example.com
Cron は、全ての Platform.sh のブランチにセットアップされています。本番以外の環境で Cron を走らせたくない場合は、環境変数の $PLATFORM_ENVIRONMENT_TYPE
をチェックしてください:
1 2 3
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
croncape symfony app:invoices:send
fi