|
|
@@ -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());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|