Commit 16f17c55 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

WIP API : Corrections pour que les logs soient enregistrés dans import_log...

WIP API : Corrections pour que les logs soient enregistrés dans import_log même si pb d'import gérable.
parent a11cfab6
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -11450,7 +11450,7 @@
            "source": {
                "type": "git",
                "url": "https://git.unicaen.fr/lib/unicaen/db-import.git",
                "reference": "bff6eb4a61e9f2fc518c0083231b25bc1f189829"
                "reference": "feca088fc7fccb2d9649ff35abcb509586a79da6"
            },
            "require": {
                "beberlei/assert": "^3.3",
@@ -11462,7 +11462,8 @@
                "php": "^8.0",
                "ramsey/uuid": "^3.0",
                "unicaen/app": "^6.0",
                "unicaen/livelog": "^2.0"
                "unicaen/livelog": "^2.0",
                "webmozart/assert": "^1.3"
            },
            "require-dev": {
                "phpunit/phpunit": "^8.0"
@@ -11482,7 +11483,7 @@
                }
            },
            "description": "Module d'import entre bases de données",
            "time": "2023-06-05T11:55:09+00:00"
            "time": "2023-06-09T09:50:43+00:00"
        },
        {
            "name": "unicaen/faq",
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ class SynchroService

    /**
     * Lance la synchro des données par UnicaenImport pour tous les services inscrits.
     *
     * @throws \Doctrine\DBAL\Exception Erreur imprévue en base de données
     */
    public function synchronize()
    {
+10 −0
Original line number Diff line number Diff line
<?php

namespace SygalApiImpl\V1\Exception;

use Exception;

class ErrorDuringImportException extends Exception
{

}
 No newline at end of file
+45 −9
Original line number Diff line number Diff line
@@ -3,9 +3,14 @@
namespace SygalApiImpl\V1\Facade;

use Doctrine\DBAL\Connection;
use Exception;
use RuntimeException;
use stdClass;
use UnicaenDbImport\Domain\Import;
use UnicaenDbImport\Domain\ImportResult;
use UnicaenDbImport\Domain\Synchro;
use UnicaenDbImport\Domain\SynchroResult;
use UnicaenDbImport\Service\Exception\DatabaseServiceException;
use UnicaenDbImport\Service\ImportService;
use UnicaenDbImport\Service\SynchroService;

@@ -38,24 +43,55 @@ abstract class AbstractImportFacade
    /**
     * @throws \Exception
     */
    protected function runImport(Import $import)
    protected function runImport(Import $import): ImportResult
    {
        $result = $this->importService->runImport($import);

        if ($exception = $result->getFailureException()) {
            throw $exception;
        try {
            return $this->importService->runImport($import);
        } catch (DatabaseServiceException $e) {
            throw new Exception("Une erreur est survenue lors de l'import : " . $e->getMessage(), null, $e);
        }
    }

    /**
     * @throws \Exception
     */
    protected function runSynchro(Synchro $import)
    protected function runSynchro(Synchro $synchro): SynchroResult
    {
        try {
            return $this->synchroService->runSynchro($synchro);
        } catch (DatabaseServiceException $e) {
            throw new Exception("Une erreur est survenue lors de la synchro : " . $e->getMessage(), null, $e);
        }
    }

    protected function beginTransaction(): void
    {
        try {
            $this->destinationConnection->setNestTransactionsWithSavepoints(true); // transactions imbriquées
            $this->destinationConnection->beginTransaction();
        } catch (\Doctrine\DBAL\Exception $e) {
            throw new RuntimeException("Echec de l'ouverture d'une transaction en bdd", null, $e);
        }
    }

    protected function commit()
    {
        $result = $this->synchroService->runSynchro($import);
        try {
            $this->destinationConnection->commit();
        } catch (\Doctrine\DBAL\Exception $e) {
            $exception = new RuntimeException("Echec du commit en bdd, rollback.", null, $e);
            $this->rollback($exception);
        }
    }

        if ($exception = $result->getFailureException()) {
            throw $exception;
    protected function rollback(Exception $reason)
    {
        try {
            $this->destinationConnection->rollback();
        } catch (\Doctrine\DBAL\Exception $e) {
            throw new RuntimeException(
                sprintf("Echec du rollback en bdd (raison du rollback : %s)", $reason->getMessage()), null, $e
            );
        }
    }
}
 No newline at end of file
+204 −190
Original line number Diff line number Diff line
@@ -4,11 +4,14 @@ namespace SygalApiImpl\V1\Rest\InscriptionAdministrative\Facade;

use Exception;
use Import\Filter\PrefixEtabColumnValueFilter;
use InvalidArgumentException;
use stdClass;
use SygalApi\V1\Rest\InscriptionAdministrative\Extractor\DoctorantExtractor;
use SygalApi\V1\Rest\InscriptionAdministrative\Extractor\IndividuExtractor;
use SygalApi\V1\Rest\InscriptionAdministrative\Extractor\InscriptionExtractor;
use SygalApiImpl\V1\Exception\ErrorDuringImportException;
use SygalApiImpl\V1\Facade\AbstractImportFacade;
use UnicaenDbImport\Config\ConfigException;
use UnicaenDbImport\Connection\ApiConnection;
use UnicaenDbImport\Domain\Destination;
use UnicaenDbImport\Domain\Import;
@@ -29,93 +32,101 @@ class ImportFacade extends AbstractImportFacade
        $this->inscriptionExtractor = new InscriptionExtractor();
    }

    /**
     * @throws \Exception
     */
    public function import(stdClass $data)
    {
        $this->destinationConnection->beginTransaction();
        $this->beginTransaction();
        try {
            $this->importIndividu($data);
            $this->importDoctorant($data);
            $this->importInscription($data);
            $this->destinationConnection->commit();
        } catch (ErrorDuringImportException $e) {
            // erreur gérée durant un import : commit nécessaire pour enregistrer les logs en bdd.
            $this->commit();
            throw $e;
        } catch (Exception $e) {
            $this->destinationConnection->rollback();
            // erreur grave imprévue durant l'import (ex : erreur d'écriture dans la table de log) : rollback requis.
            $this->rollback($e);
            throw $e;
        }
        // tout s'est bien passé, commit.
        $this->commit();
    }

    /**
     * @throws \Exception
     * @throws \SygalApiImpl\V1\Exception\ErrorDuringImportException Erreur durant l'import mais commit possible
     * @throws \Exception Erreur grave imprévue
     */
    private function importIndividu(stdClass $data)
    {
        $preparedData = $this->individuExtractor->extract($data);
        try {
        $import = $this->createImportIndividu($preparedData);
            $this->runImport($import);
        } catch (Exception $e) {
            throw new Exception("Une erreur est survenue lors de l'import de l'individu : " . $e->getMessage(), null, $e);
        $result = $this->runImport($import);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de l'import de l'individu : " . $e->getMessage(), null, $e
            );
        }

        $sourceId = $preparedData['source_id'];
        try {
        $synchro = $this->createSynchroIndividu($sourceId);
            $this->runSynchro($synchro);
        } catch (Exception $e) {
            throw new Exception("Une erreur est survenue lors de la synchro de l'individu : " . $e->getMessage(), null, $e);
        $result = $this->runSynchro($synchro);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de la synchro de l'individu : " . $e->getMessage(), null, $e
            );
        }
    }

    /**
     * @throws \Exception
     * @throws \SygalApiImpl\V1\Exception\ErrorDuringImportException Erreur durant l'import mais commit possible
     * @throws \Exception Erreur grave imprévue
     */
    private function importDoctorant(stdClass $data)
    {
        $preparedData = $this->doctorantExtractor->extract($data);
        try {
        $import = $this->createImportDoctorant($preparedData);
            $this->runImport($import);
        } catch (Exception $e) {
            throw new Exception("Une erreur est survenue lors de l'import du doctorant : " . $e->getMessage(), null, $e);
        $result = $this->runImport($import);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de l'import du doctorant : " . $e->getMessage(), null, $e
            );
        }

        $sourceId = $preparedData['source_id'];
        try {
        $synchro = $this->createSynchroDoctorant($sourceId);
            $this->runSynchro($synchro);
        } catch (Exception $e) {
            throw new Exception("Une erreur est survenue lors de la synchro du doctorant : " . $e->getMessage(), null, $e);
        $result = $this->runSynchro($synchro);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de la synchro du doctorant : " . $e->getMessage(), null, $e
            );
        }
    }

    /**
     * @throws \Exception
     * @throws \SygalApiImpl\V1\Exception\ErrorDuringImportException Erreur durant l'import mais commit possible
     * @throws \Exception Erreur grave imprévue
     */
    private function importInscription(stdClass $data)
    {
        $preparedData = $this->inscriptionExtractor->extract($data);
        try {
        $import = $this->createImportInscription($preparedData);
            $this->runImport($import);
        } catch (Exception $e) {
            error_log($e);
            throw new Exception("Une erreur est survenue lors de l'import de l'inscription : " . $e->getMessage(), null, $e);
        $result = $this->runImport($import);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de l'import de l'inscription : " . $e->getMessage(), null, $e
            );
        }

        $sourceId = $preparedData['source_id'];
        try {
        $synchro = $this->createSynchroInscription($sourceId);
            $this->runSynchro($synchro);
        } catch (Exception $e) {
            throw new Exception("Une erreur est survenue lors de la synchro de l'inscription : " . $e->getMessage(), null, $e);
        $result = $this->runSynchro($synchro);
        if ($e = $result->getFailureException()) {
            throw new ErrorDuringImportException(
                "Une erreur est survenue lors de la synchro de l'inscription : " . $e->getMessage(), null, $e
            );
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createImportIndividu(array $data): Import
    {
        $filter = new PrefixEtabColumnValueFilter([
@@ -125,8 +136,9 @@ class ImportFacade extends AbstractImportFacade
        $sourceId = $data['source_id'];
        $filter->setParams([PrefixEtabColumnValueFilter::PARAM_CODE_ETABLISSEMENT => $sourceId]);

        try {
            $source = Source::fromConfig([
            'name' => 'vxcvxcvxc',
                'name' => 'api',
                'connection' => new ApiConnection(),
                'select' => 'xxxxx',
                'source_code_column' => 'source_code',
@@ -143,19 +155,20 @@ class ImportFacade extends AbstractImportFacade
            $source->setData([$data]);

            return Import::fromConfig([
            'name' => 'individu',
                'name' => 'api_import_individu',
                'source' => $source,
                'destination' => $destination,
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createSynchroIndividu(string $sourceId): Synchro
    {
        $where = "d.source_id = ( select id from source where code = '$sourceId' )";

        try {
            $source = Source::fromConfig([
                'name' => 'Application',
                'code' => 'app',
@@ -172,7 +185,7 @@ class ImportFacade extends AbstractImportFacade
            ]);

            return Synchro::fromConfig([
            'name' => uniqid('synchro_'),
                'name' => 'api_synchro_individu',
                'source' => $source,
                'destination' => $destination,
                'operations' => [
@@ -181,11 +194,11 @@ class ImportFacade extends AbstractImportFacade
                    Operation::OPERATION_UNDELETE,
                ],
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createImportDoctorant(array $data): Import
    {
        $filter = new PrefixEtabColumnValueFilter([
@@ -196,8 +209,9 @@ class ImportFacade extends AbstractImportFacade
        $sourceId = $data['source_id'];
        $filter->setParams([PrefixEtabColumnValueFilter::PARAM_CODE_ETABLISSEMENT => $sourceId]);

        try {
            $source = Source::fromConfig([
            'name' => 'vxcvxcvxc',
                'name' => 'api',
                'connection' => new ApiConnection(),
                'select' => 'xxxxx',
                'source_code_column' => 'source_code',
@@ -210,23 +224,22 @@ class ImportFacade extends AbstractImportFacade
                'source_code_column' => 'source_code',
                'id_sequence' => false,
            ]);

            $source->setData([$data]);

            return Import::fromConfig([
            'name' => 'doctorant',
                'name' => 'api_import_doctorant',
                'source' => $source,
                'destination' => $destination,
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createSynchroDoctorant(string $sourceId): Synchro
    {
        $where = "d.source_id = ( select id from source where code = '$sourceId' )";

        try {
            $source = Source::fromConfig([
                'name' => 'Application',
                'code' => 'app',
@@ -241,30 +254,30 @@ class ImportFacade extends AbstractImportFacade
                'source_code_column' => 'source_code',
                'where' => $where,
            ]);

            return Synchro::fromConfig([
            'name' => uniqid('synchro_'),
                'name' => 'api_synchro_doctorant',
                'source' => $source,
                'destination' => $destination,
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createImportInscription(array $data): Import
    {
        $filter = new PrefixEtabColumnValueFilter([
            'source_code',
            //'source_id', // pas le source_id !
            'doctorant_id',
            'ecole_doctorale_id',
            //'source_id', // pas le source_id !
        ]);
        $sourceId = $data['source_id'];
        $filter->setParams([PrefixEtabColumnValueFilter::PARAM_CODE_ETABLISSEMENT => $sourceId]);

        try {
            $source = Source::fromConfig([
            'name' => 'vxcvxcvxc',
                'name' => 'api',
                'connection' => new ApiConnection(),
                'select' => 'xxxxx',
                'source_code_column' => 'source_code',
@@ -277,23 +290,22 @@ class ImportFacade extends AbstractImportFacade
                'source_code_column' => 'source_code',
                'id_sequence' => false,
            ]);

            $source->setData([$data]);

            return Import::fromConfig([
            'name' => 'inscription',
                'name' => 'api_import_inscription',
                'source' => $source,
                'destination' => $destination,
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }

    /**
     * @throws \UnicaenDbImport\Config\ConfigException
     */
    private function createSynchroInscription(string $sourceId): Synchro
    {
        $where = "d.source_id = ( select id from source where code = '$sourceId' )";

        try {
            $source = Source::fromConfig([
                'name' => 'Application',
                'code' => 'app',
@@ -308,11 +320,13 @@ class ImportFacade extends AbstractImportFacade
                'source_code_column' => 'source_code',
                'where' => $where,
            ]);

            return Synchro::fromConfig([
            'name' => uniqid('synchro_'),
                'name' => 'api_synchro_inscription',
                'source' => $source,
                'destination' => $destination,
            ]);
        } catch (ConfigException $e) {
            throw new InvalidArgumentException("Mauvaise config dans " . __METHOD__, null, $e);
        }
    }
}
 No newline at end of file
Loading