소스 검색

Improves DB integrity check cron job

Refactors the database integrity check cron job to compare data between production and backup databases.

This change enhances the previous version that checked for empty tables by comparing record counts between the production and test backup environments, logging discrepancies exceeding 5%.
This approach provides a more comprehensive assessment of data integrity and identifies potential issues in the backup process.
Olivier Massot 3 달 전
부모
커밋
10a38b1e09
1개의 변경된 파일118개의 추가작업 그리고 53개의 파일을 삭제
  1. 118 53
      src/Service/Cron/Job/DbCheck.php

+ 118 - 53
src/Service/Cron/Job/DbCheck.php

@@ -22,24 +22,14 @@ use Doctrine\ORM\EntityManagerInterface;
  */
 class DbCheck extends BaseCronJob
 {
-    public const IGNORE_EMPTY_TABLES = [
+    public const IGNORE_TABLES = [
         'messenger_messages',
         'enqueue',
         'zzz_.*',
-        'CycleByEducation', // Table a priori non utilisée
-        'educationalproject_file',
-        'ElasticaSynchro',
-        'Odyssee',
-        'PeriodNotation', // Table a priori non utilisée
-        'Presence',
-        'tag_accessWish',
-        'tag_control',
-        'tag_educationNotation',
-        'tag_educationStudent',
-        'tag_repair',
     ];
 
     public function __construct(
+        private readonly EntityManagerInterface $entityManager,
         private readonly EntityManagerInterface $testBackupEntityManager,
     ) {
         parent::__construct();
@@ -62,50 +52,11 @@ class DbCheck extends BaseCronJob
             $connection = $this->getDbConnection();
         } catch (\Exception $e) {
             $this->logger->critical($e->getMessage());
-
             return;
         }
 
-        $this->logger->info('2. Vérification de l\'intégrité des données');
-        try {
-            $schemaManager = $connection->createSchemaManager();
-            $tables = $schemaManager->listTableNames();
-            $this->logger->debug(sprintf('Nombre total de tables: %d', count($tables)));
-
-            $emptyTables = [];
-
-            foreach ($tables as $table) {
-                try {
-                    if (preg_match('/^'.implode('|', self::IGNORE_EMPTY_TABLES).'$/', $table)) {
-                        $this->logger->debug(sprintf('Table %s: -- ignored --', $table));
-                        continue;
-                    }
-
-                    $count = (int) $connection->executeQuery("SELECT COUNT(*) FROM {$table}")->fetchOne();
-
-                    if (!$count > 0) {
-                        $emptyTables[] = $table;
-                    }
-
-                    $this->logger->debug(sprintf('Table %s: %d enregistrements', $table, $count));
-                } catch (\Exception $tableException) {
-                    $this->logger->critical(sprintf('Impossible de vérifier la table %s: %s', $table, $tableException->getMessage()));
-                }
-            }
-
-            if (count($emptyTables) > 0) {
-                $this->logger->critical('%d tables vides détectées sur %d tables au total');
-                $this->logger->error('Tables vides:');
-                foreach ($emptyTables as $table) {
-                    $this->logger->error('- '.$table);
-                }
-            } else {
-                $this->logger->info('Toutes les tables sont présentes et contiennent des données');
-            }
-        } catch (\Exception $e) {
-            $this->logger->critical('Erreur lors de la vérification de l\'intégrité des données: '.$e->getMessage());
-            $this->logger->debug('Stack trace: '.$e->getTraceAsString());
-        }
+        $this->logger->info('2. Comparaison des données entre production et backup');
+        $this->compareProductionWithBackup();
     }
 
     /**
@@ -144,4 +95,118 @@ class DbCheck extends BaseCronJob
 
         return $connection;
     }
+
+    /**
+     * Compare les données entre la base de production et le backup de test.
+     * Enregistre une erreur si un écart de plus de 5% est détecté.
+     */
+    private function compareProductionWithBackup(): void
+    {
+        try {
+            // Connexion à la base de production
+            $productionConnection = $this->entityManager->getConnection();
+            $productionConnection->connect();
+
+            // Connexion à la base de backup
+            $backupConnection = $this->testBackupEntityManager->getConnection();
+            $backupConnection->connect();
+
+            if (!$productionConnection->isConnected() || !$backupConnection->isConnected()) {
+                $this->logger->critical('Impossible d\'établir les connexions pour la comparaison');
+                return;
+            }
+
+            $this->logger->info('Connexions établies pour la comparaison prod/backup');
+
+            // Lister les tables de la connexion standard (production)
+            $productionSchemaManager = $productionConnection->createSchemaManager();
+            $productionTables = $productionSchemaManager->listTableNames();
+
+            $this->logger->debug(sprintf('Nombre de tables en production: %d', count($productionTables)));
+
+            $discrepancies = [];
+
+            foreach ($productionTables as $table) {
+                try {
+                    // Ignorer certaines tables
+                    if (preg_match('/^'.implode('|', self::IGNORE_TABLES).'$/', $table)) {
+                        continue;
+                    }
+
+                    // Compter les enregistrements en production
+                    $prodCount = (int) $productionConnection->executeQuery("SELECT COUNT(*) FROM {$table}")->fetchOne();
+
+                    // Compter les enregistrements en backup
+                    try {
+                        $backupCount = (int) $backupConnection->executeQuery("SELECT COUNT(*) FROM {$table}")->fetchOne();
+                    } catch (\Exception $e) {
+                        // Table n'existe pas en backup
+                        $this->logger->error(sprintf('Table %s non trouvée en backup: %s', $table, $e->getMessage()));
+                        continue;
+                    }
+
+                    // Calculer l'écart en pourcentage
+                    if ($prodCount > 0) {
+                        $percentage = abs($prodCount - $backupCount) / $prodCount * 100;
+
+                        if ($percentage > 5.0) {
+                            $discrepancies[] = [
+                                'table' => $table,
+                                'prod_count' => $prodCount,
+                                'backup_count' => $backupCount,
+                                'percentage' => $percentage
+                            ];
+                        }
+
+                        $this->logger->debug(sprintf(
+                            'Table %s: Prod=%d, Backup=%d, Écart=%.2f%%',
+                            $table,
+                            $prodCount,
+                            $backupCount,
+                            $percentage
+                        ));
+                    } else if ($backupCount > 0) {
+                        // Production vide mais backup non vide
+                        $discrepancies[] = [
+                            'table' => $table,
+                            'prod_count' => $prodCount,
+                            'backup_count' => $backupCount,
+                            'percentage' => 100.0
+                        ];
+                    }
+
+                } catch (\Exception $tableException) {
+                    $this->logger->error(sprintf(
+                        'Erreur lors de la comparaison de la table %s: %s',
+                        $table,
+                        $tableException->getMessage()
+                    ));
+                }
+            }
+
+            // Enregistrer les erreurs pour les écarts détectés
+            if (count($discrepancies) > 0) {
+                $this->logger->error(sprintf(
+                    '%d tables présentent un écart supérieur à 5%% entre production et backup',
+                    count($discrepancies)
+                ));
+
+                foreach ($discrepancies as $discrepancy) {
+                    $this->logger->error(sprintf(
+                        'Table %s: Production=%d, Backup=%d, Écart=%.2f%%',
+                        $discrepancy['table'],
+                        $discrepancy['prod_count'],
+                        $discrepancy['backup_count'],
+                        $discrepancy['percentage']
+                    ));
+                }
+            } else {
+                $this->logger->info('Aucun écart significatif détecté entre production et backup');
+            }
+
+        } catch (\Exception $e) {
+            $this->logger->critical('Erreur lors de la comparaison prod/backup: '.$e->getMessage());
+            $this->logger->debug('Stack trace: '.$e->getTraceAsString());
+        }
+    }
 }