Commit 3727e9e3 authored by Anthony Gautreau's avatar Anthony Gautreau
Browse files

Import Pegase : limite mémoire PHP propre à l'import (PEGASE_MEMOIRE, 512M par défaut)

parent 383750eb
Loading
Loading
Loading
Loading
+3 −0
Changes for .env.dist: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ PEGASE_LANGUES=
# Dates des semestres, début et fin en mois-jour
PEGASE_SEMESTRE_1=09-01:01-31
PEGASE_SEMESTRE_2=01-15:06-30
# Limite mémoire PHP de l'import, qui croît avec le nombre de cours et de périodes : à augmenter si la mémoire
# affichée dans le bilan de l'import s'en approche (-1 pour aucune limite)
PEGASE_MEMOIRE=512M

# Informations de connexion à l'API via Basic Auth, à communiquer à Smile
API_USER=
+3 −0
Changes for README.md: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -132,6 +132,9 @@ PEGASE_LANGUES=
# Dates des semestres, début et fin en mois-jour
PEGASE_SEMESTRE_1=09-01:01-31
PEGASE_SEMESTRE_2=01-15:06-30
# Limite mémoire PHP de l'import, qui croît avec le nombre de cours et de périodes : à augmenter si la mémoire
# affichée dans le bilan de l'import s'en approche (-1 pour aucune limite)
PEGASE_MEMOIRE=512M

# Informations de connexion à l'API via Basic Auth, à communiquer à Smile
API_USER=
+1 −0
Changes for api/config/services.yaml: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ parameters:
    env(PEGASE_LANGUES): ''
    env(PEGASE_SEMESTRE_1): '09-01:01-31'
    env(PEGASE_SEMESTRE_2): '01-15:06-30'
    env(PEGASE_MEMOIRE): '512M'

services:
    # default configuration for services in *this* file
+19 −0
Changes for api/src/Command/ImportPegaseCommand.php: 19 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ use App\Entity\CourseInstance;
use App\Entity\Ounit;
use App\Entity\PegaseImportLog;
use App\Entity\Programme;
use App\Pegase\PegaseException;
use App\Pegase\PegaseImporter;
use App\Pegase\ResultatImport;
use Doctrine\Common\Collections\ArrayCollection;
@@ -44,6 +45,8 @@ final class ImportPegaseCommand extends Command
     * @param bool                   $pegaseActive valeur de PEGASE_ENABLED
     * @param int                    $lot          entités enregistrées entre deux vidages du gestionnaire, pour
     *                                             borner la mémoire
     * @param string                 $memoire      PEGASE_MEMOIRE, limite mémoire PHP de l'import (512M, -1 sans
     *                                             limite)
     * @param LoggerInterface        $logger       progression de l'enregistrement
     */
    public function __construct(
@@ -54,6 +57,8 @@ final class ImportPegaseCommand extends Command
        #[Autowire(env: 'bool:PEGASE_ENABLED')]
        private readonly bool $pegaseActive,
        private readonly int $lot = 500,
        #[Autowire(env: 'PEGASE_MEMOIRE')]
        private readonly string $memoire = '512M',
        private readonly LoggerInterface $logger = new NullLogger(),
    ) {
        parent::__construct();
@@ -73,6 +78,7 @@ final class ImportPegaseCommand extends Command
        $io->title('Import des données depuis Pegase');
        $io->writeln($journal->date->format('Y-m-d H:i:s'));
        try {
            $this->appliquerLimiteMemoire();
            $resultat = $this->importer->importer($journal->date);
            $journal->nbOunits = \count($resultat->ounits);
            $journal->nbProgrammes = \count($resultat->programmes);
@@ -106,6 +112,19 @@ final class ImportPegaseCommand extends Command
        return Command::SUCCESS;
    }

    /**
     * @throws PegaseException si PEGASE_MEMOIRE n'est pas une limite valide ou est inférieure à la mémoire utilisée
     */
    private function appliquerLimiteMemoire(): void
    {
        // Avertissement de ini_set remplacé par l'exception
        if (preg_match('/^(-1|\d+[KMG]?)$/i', $this->memoire) && false !== @ini_set('memory_limit', $this->memoire)) {
            return;
        }
        $message = \sprintf('PEGASE_MEMOIRE : « %s » n\'est pas une limite mémoire utilisable (512M)', $this->memoire);
        throw new PegaseException($message);
    }

    private function enregistrer(ResultatImport $resultat, PegaseImportLog $journal): void
    {
        $this->manager->wrapInTransaction(function (EntityManagerInterface $manager) use ($resultat, $journal): void {
+32 −2
Changes for api/tests/Command/ImportPegaseCommandTest.php: 32 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -160,8 +160,30 @@ class ImportPegaseCommandTest extends KernelTestCase
        $this->assertSame(['FAILURE'], $this->statuts());
    }

    private function executer(string $annees = self::ANNEES, bool $pegaseActive = true, int $lot = 500): CommandTester
    /**
     * Vérifie le refus d'une limite mémoire invalide ou trop basse, sans appel à Pegase, avec une ligne de journal.
     */
    public function testLimiteMemoireInutilisable(): void
    {
        $limite = ini_get('memory_limit');

        foreach (['beaucoup', '1M'] as $memoire) {
            $tester = $this->executer(memoire: $memoire);

            $this->assertSame(Command::FAILURE, $tester->getStatusCode());
            $this->assertStringContainsString('PEGASE_MEMOIRE : « '.$memoire.' »', $tester->getDisplay());
        }
        $this->assertSame($limite, ini_get('memory_limit'));
        $this->assertSame([], $this->serveur->requetes);
        $this->assertSame(['FAILURE', 'FAILURE'], $this->statuts());
    }

    private function executer(
        string $annees = self::ANNEES,
        bool $pegaseActive = true,
        int $lot = 500,
        string $memoire = '512M',
    ): CommandTester {
        $client = $this->serveur->client();
        $importer = new PegaseImporter(
            $client,
@@ -169,7 +191,15 @@ class ImportPegaseCommandTest extends KernelTestCase
            new Configuration($annees, 'ECA:en,UEA:en,ECN:gmq', '09-01:01-31', '01-15:06-30'),
        );
        $container = static::getContainer();
        $commande = new ImportPegaseCommand($importer, $container->get(EntityManagerInterface::class), $container->get('doctrine'), new MockClock('2026-10-08 12:00:00'), $pegaseActive, $lot);
        $commande = new ImportPegaseCommand(
            $importer,
            $container->get(EntityManagerInterface::class),
            $container->get('doctrine'),
            new MockClock('2026-10-08 12:00:00'),
            $pegaseActive,
            $lot,
            $memoire,
        );

        $tester = new CommandTester($commande);
        $tester->execute([]);