Forráskód Böngészése

add the CleanDb cron job

Olivier Massot 3 éve
szülő
commit
cfacbcd36a

+ 6 - 0
src/Commands/CronCommand.php

@@ -21,6 +21,12 @@ use Symfony\Contracts\Service\Attribute\Required;
 /**
  * CLI Command to run the cron-jobs
  *
+ * Ex:
+ *
+ *     bin/console ot:cron list
+ *     bin/console ot:cron run clean-db --preview
+ *     bin/console ot:cron run clean-db
+ *
  * @see ~/src/Service/Cron/Readme.md
  */
 #[AsCommand(

+ 160 - 0
src/Service/Cron/Job/CleanDb.php

@@ -0,0 +1,160 @@
+<?php
+
+namespace App\Service\Cron\Job;
+
+use App\Service\Cron\BaseCronJob;
+use App\Service\Cron\CronjobInterface;
+use App\Service\Utils\DatesUtils;
+use DateTime;
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\DBALException;
+use Exception;
+use JetBrains\PhpStorm\Pure;
+
+/**
+ * Cronjob that delete records older than N days in DB tables like Audit_ or Message
+ *
+ * >>> ot:cron clean-db
+ */
+// TODO: voir si ajouter :
+// * Information (282.000 lignes)? (avec NotificationUser, 169.000 lignes)
+// * MigrationLog (972.000 lignes)?
+// * ReportMessage? (4.500.000 lignes)
+
+// TODO: table potentiellement à supprimer dans la foulée : AccessTmp, Person_ori, Person_save, MigrationLog
+
+class CleanDb extends BaseCronJob implements CronjobInterface
+{
+    /**
+     * Delay before deleting the record of the temporary file from the DB
+     */
+    private const PURGE_RECORDS_OLDER_THAN = 365;
+
+    /**
+     * @param Connection $connection
+     */
+    #[Pure]
+    public function __construct(
+        private Connection $connection
+    ) {
+        parent::__construct();
+    }
+
+    /**
+     * Preview the result of the execution, without actually deleting anything
+     * @throws Exception
+     */
+    public function preview(): void
+    {
+        $this->purgeDb(false);
+    }
+
+    /**
+     * Proceed to the deletion of the files and the purge of the DB
+     * @throws Exception
+     */
+    public function execute(): void
+    {
+        $this->purgeDb();
+    }
+
+    /**
+     * Purge the DB from temporary file records older than N days
+     *
+     * @param bool $commit
+     * @throws Exception
+     * @throws \Doctrine\DBAL\Driver\Exception
+     */
+    protected function purgeDb(bool $commit = true): void
+    {
+        $maxDate = DatesUtils::new();
+        $maxDate->sub(new \DateInterval('P' . self::PURGE_RECORDS_OLDER_THAN . 'D'));
+
+        $this->ui->print('Purge DB from temporary records modified before ' . $maxDate->format('c'));
+        $this->connection->beginTransaction();
+
+        $purged = 0;
+
+        $purged += $this->purgeAuditTables($maxDate);
+//        $purged += $this->purgeMessages($maxDate);
+        $purged += $this->purgeLoginLog($maxDate);
+
+        if ($commit) {
+            $this->connection->commit();
+            $this->ui->print('DB purged - ' . $purged . ' records permanently deleted');
+            return;
+        }
+
+        $this->connection->rollback();
+        $this->ui->print('DB purged - ' . $purged . ' records would be permanently deleted');
+    }
+
+    /**
+     * Purge Access tables and returns the number of deleted records
+     *
+     * @param DateTime $maxDate
+     * @return int
+     * @throws DBALException
+     * @throws \Doctrine\DBAL\Driver\Exception
+     * @throws \Doctrine\DBAL\Exception
+     */
+    protected function purgeAuditTables(DateTime $maxDate): int
+    {
+        $this->ui->print('Purge Audit tables');
+
+        $tableNames = $this->connection->getSchemaManager()->listTableNames();
+
+        $total = 0;
+
+        foreach (array_values($tableNames) as $tableName) {
+            if (preg_match("/Audit_\w+/", $tableName)) {
+                /** @noinspection SqlWithoutWhere */
+                $sql = "DELETE a, r 
+                     FROM opentalent.{$tableName} a
+                     INNER JOIN opentalent.revisions r ON r.id = a.rev
+                     WHERE r.timestamp < :maxDate;";
+
+                $stmt = $this->connection->prepare($sql);
+                $purged = $stmt->executeStatement(['maxDate' => $maxDate->format('Y-m-d')]);
+
+                $this->ui->print('* ' . $tableName . ' : ' . $purged . ' lines to delete');
+
+                $total += $purged;
+            }
+        }
+
+        return $total;
+    }
+
+    /**
+     * Purge Message table and returns the number of deleted records
+     * TODO: à confirmer
+     *
+     * @param DateTime $maxDate
+     * @return int
+     * @throws \Doctrine\DBAL\Exception
+     */
+    protected function purgeMessages(DateTime $maxDate): int {
+        $q = $this->connection->createQueryBuilder();
+        $q->delete('Message')->where($q->expr()->lt('dateSent', $maxDate->format('Y-m-d')));
+
+        // TODO: tester si les tables message_documents et message_files sont bien nettoyées en cascade ou s'il faut
+        //       le faire manuellement
+        return $q->execute();
+    }
+
+    /**
+     * Purge LoginLog table and returns the number of deleted records
+     *
+     * @param DateTime $maxDate
+     * @return int
+     * @throws \Doctrine\DBAL\Exception
+     */
+    protected function purgeLoginLog(DateTime $maxDate): int {
+        $q = $this->connection->createQueryBuilder();
+        $q->delete('LoginLog')->where($q->expr()->lt('date', $maxDate->format('Y-m-d')));
+
+        return $q->execute();
+    }
+
+}

+ 2 - 0
src/Service/Cron/Job/CleanTempFiles.php

@@ -16,6 +16,8 @@ use JetBrains\PhpStorm\Pure;
 
 /**
  * Cronjob that delete temporary files older than N days
+ *
+ * >>> ot:cron clean-temp-files
  */
 class CleanTempFiles extends BaseCronJob implements CronjobInterface
 {

+ 2 - 0
src/Service/Cron/Job/DolibarrSync.php

@@ -9,6 +9,8 @@ use JetBrains\PhpStorm\Pure;
 
 /**
  * Push the latest data from the Opentalent DB to dolibarr
+ *
+ * >>> ot:cron dolibarr-sync
  */
 class DolibarrSync extends BaseCronJob implements CronjobInterface
 {