Giter VIP home page Giter VIP logo

gn2pg's Introduction

GN2PG Client

https://www.python.org/ https://www.postgresql.org/ https://python-poetry.org/ https://github.com/psf/black https://opensource.org/licenses/AGPL-3.0

This project provides an import data from GeoNature instances to a PostgreSQL database (client side). Widely inspired from ClientApiVN

Warning

The minimum version of the source GeoNature instance required for the incremental update must be a version 2.12.0

Project logo

Project Setup

GN2PG Client can be installed by running pip. It requires Python 3.7.4 or above to run.

pip install gn2pg-client

Issues

Please report any bugs or requests that you have using the GitHub issue tracker!

HowTo

Help

gn2pg_cli --help

Init config file

This command init a TOML config file within ~/.gn2pg hidden directory (in user HOME directory), named as you want. PLEASE DO NOT SPECIFY PATH!

gn2pg_cli --init <myconfigfile>

Config file is structured as this. [[source]] block can be duplicate as many as needed (one block for each source).

The data_type value on each source is used to characterize the type of data. This value is used to identify which triggers to be triggered when inserting, updating or deleting data. Current provided trigger configs are:

  • synthese_with_cd_nomenclature which provide triggers to insert basically data on synthese and generate basic metadatas (acquisition framework and datasets). Source query sample is provided in file geonature_export_sinp_with_cd_nomenclature.sql
  • synthese_with_metadata which provide triggers to insert data in synthese and populate most of the metadata data (acquisition frameworks, datasets, actors such as organisms and roles, territories, etc.). Source query sample is provided in file geonature_export_sinp_with_metadata.sql
# GN2PG configuration file

# Local db configuration
[db]
db_host = "localhost"
db_port = 5432
db_user = "<dbUser>"
db_password = "<dbPassword>"
db_name = "<dbName>"
db_schema_import = "schema"
    # Additional connection options (optional)
    [db.db_querystring]
    sslmode = "prefer"


# Source configuration,
# Ducplicate this block for each source (1 source = 1 export)
[[source]]
# Source name, will be use to tag stored data in import table
name = "Source1"
# GeoNature source login
user_name = "<monuser>"
# GeoNature source password
user_password = "<monPwd>"
# GeoNature source URL
url = "<http://geonature1/>"
# GeoNature source Export id
export_id = 1
# Data type is facultative. By default the value is 'synthese'. Therefore, triggers from to_gnsynthese.sql are not activated.
# If you want to insert your data into a GeoNature database please choose either 'synthese_with_cd_nomenclature' or 'synthese_with_metadata'.
# If not, delete the line.
data_type = "synthese_with_cd_nomenclature"


[[source]]
# Source configuration
name = "Source2"
user_name = "<monuser>"
user_password = "<monPwd>"
url = "<http://geonature2/>"
export_id = 1
data_type = "synthese_with_cd_nomenclature"

Tip

You can add variable in source block enable = false to disable a source

InitDB Schema and tables

To create json tables where datas will be stored, run :

gn2pg_cli --json-tables-create <myconfigfile>

Full download

To download all datas from API, run :

gn2pg_cli --full <myconfigfile>

Incremental download

To update data since last download, run :

gn2pg_cli --update <myconfigfile>

To automate the launching of updates, you can write the cron task using the following command, for example every 30 minutes.

*/30 * * * * /usr/bin/env bash -c "source <path to python environment>/bin/activate && gn2pg_cli --update <myconfigfile>" > /dev/null 2>&1

Debug mode

Debug mode can be activated using --verbose CLI argument

Logs

Log files are stored in $HOME/.gn2pg/log directory.

Import datas into GeoNature database

Default script to auto populate GeoNature is called "to_gnsynthese".

gn2pg_cli --custom-script to_gnsynthese <myconfigfile>

Tip

You can also replacing synthese script by your own scripts, using file path instead of to_gnsynthese.

Dashboard

A simple web dashboard can be run following dashboard docs.

Dashboard_Home

Dashboard_gn2pg_downloag_log

Contributing

All devs must be done in forks (see GitHub doc).

Pull requests must be pulled to dev branch.

Install project and development requirements (require poetry):

poetry install --with=docs --all-extras
poetry run pre-commit install

Make your devs and pull requests.

Test gn2pg_cli in dev mode by running this command:

poetry run gn2pg_cli <options>

Licence

GNU AGPLv3

Team

Logo LPOAuRA

  • @ophdlv (Natural Solution), contributor
  • @mvergez (Natural Solution), contributor
  • @andriacap (Natural Solution), contributor
  • @Adrien-Pajot (Natural Solution), contributor

With the financial support of the DREAL Auvergne-Rhône-Alpes and the Office français de la biodiversité.

gn2pg's People

Contributors

adrien-pajot avatar andriacap avatar camillemonchicourt avatar dependabot[bot] avatar hypsug0 avatar lpofredc avatar ophdlv avatar pierre56 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gn2pg's Issues

Sauts dans les offsets

Bonjour,

je constate en faisant un --full ce midi que j'ai des sauts dans les offsets, un peu par hasards.

2023-12-06 12:43:30,394 - INFO - store_postgresql:store_data - 1000 items have been stored in db from data of source cen74 (0 error occurred)
2023-12-06 12:43:30,427 - INFO - api:get_page - Download page https://geonature.xxx.fr/api/exports/api/3?limit=1000&orderby=id_synthese&offset=22
2023-12-06 12:43:30,494 - INFO - download:report - Storing 1000 datas (6000/68950 8.70 %) from CEN74 data
2023-12-06 12:44:01,754 - INFO - api:get_page - Download page https://geonature.xxx.fr/api/exports/api/3?limit=1000&orderby=id_synthese&offset=36

Déjà rencontré ? Une raison qui pourrait expliquer ça ?

Je suis sur un serveur mis à jour dernièrement, python 3.9 est bien installé, et j'interroge la BDD du CEN74 qui est bien à jour sur son utilitaire flask-sql-alchemy

gn2pg_import - error_count donnée en entrée invalide

Launching command gn2pg_cli --full myconfigfile, returns synax error (error_count data is not an integer)

sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTextRepresentation) ERREUR: syntaxe en entrée invalide pour le type integer : « data »
LINE 1: ...t, http_status, comment) VALUES ('flaviabase', 0, 'data', 0,...
^

[SQL: INSERT INTO gn2pg_import.download_log (source, controler, error_count, http_status, comment) VALUES (%(source)s, %(controler)s, %(error_count)s, %(http_status)s, %(comment)s)]
[parameters: {'source': 'flaviabase', 'controler': 0, 'error_count': 'data', 'http_status': 0, 'comment': 0}]

Implement incremental download

La mise en place de la mise à jour incrémentale des données requiert des modifications à GeoNature avec l'ajout d'une journalisation des données modifiées en synthèse dont les modalités restent à définir.

  • Une journalisation généralisée unique simple avec triggers indiquant pour chaque donnée le type de mise à jour (Delete, Insert, Update) et le timestamp de la modification. Scénario intéressant à court terme, performant côté source mais potentiellement lourd côté client en cas d'importante mise à jour.
  • Une journalisation plus poussée avec mention de l'export concerné (id_export) mais qui peut avoir des conséquences en termes de performances car nécessite, avant action sur la donnée en synthèse, d'identifier les exports concernés.

Cette journalisation nécessite également la mise à disposition, côté GeoNature source, d'une API spécifique consultable par intervalles de temps (début/fin avec un delta par défaut, ex. 10 jours, à définir en option?.

Il pourra être intéressant de définir un pas de temps limite de conservation de l'historique pour ne pas surcharger la bdd.

Bad data errors - Logs and email

With @DonovanMaillard we tried to add data with a cd_nom 'blue'.
Obviously this could not work :

Traceback (most recent call last):
  File "/home/geonatureadmin/.local/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1276, in _execute_context
    self.dialect.do_execute(
  File "/home/geonatureadmin/.local/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 608, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.InvalidTextRepresentation: ERREUR:  syntaxe en entrée invalide pour le type integer : « bleu »
CONTEXT:  fonction PL/pgSQL gn2pg.fct_tri_c_upsert_data_to_geonature_with_cd_nomenclature(), ligne 134 à instruction SQL

However, we thought that it was good to store all wrong lines in log and to send an email to the source database manager so that it can modify the data directly in its database.
Therefore, we could add the email in the config file.

Update - Utiliser les UUID

Il était initialement prévu de se baser sur les UUID des objets dans la synthèse pour mettre à jour les données si elles ont été modifiées dans la source.

Cependant, toutes les données d'un GeoNature n'ont pas forcément d'UUID et cela doit rester possible. Voir PnX-SI/GeoNature#1205

Cependant les UUID sont vraiment idéaux pour les échanges automatiques entre outils et notamment pour GN2GN.

Du coup peut-être à approfondir. Ou alors se baser sur les UUID sans les imposer ? Si une données n'a pas d'UUID dans la source, alors elle n'est pas transmise lors d'un GN2GN ?

Questions sur l'historisation GeoNature du fournisseur de données

PR intégrant une historisation des données de la synthèse (insert, update, delete):

* Les `delete` sont loggés dans la table gn_synthese.t_log_synthese par triggers

* Les `update` & `insert` ne sont pas loggés par triggers car déjà présents dans gn_synthese.synthese par les champs `meta_{create,update}_date`.

* Le tout est regroupé dans une vue gn_synthese.v_log_synthese.

L'API, désactible par l'option ['SYNTHESE']['LOG_API'] = False, est basée sur la classe GenericQuery donc avec des possibilités de requêtage avancées (action supérieure à une date spécifique par exemple).

Cette API nécessaire pour la mise à jour incrémentale de Gn2Pg.

Lien avec #789

Bonjour, Une simple question sur ce point.

L'API va chercher l'historique des actions sur une donnée elle-même, pour aller la répliquer sur la base "cliente" via gn2pg. Du coup l'incrémental ne se fait pas en allant checker "les données reçues hier VS les données reçues aujourd"hui'.

Je comprends bien l'intérêt pratique, mais ça veut dire que si je mets à jour ma vue qui sert le client via GN2PG, il faut refaire une synchro complète ? Puisque j'aurai finalement dans cette nouvelle vue, retiré des données dont la dernière action n'est pas forcément "detele", j'aurai de nouvelles données dont la création n'est pas postéieure à la dernière synchro etc ?

Originally posted by @DonovanMaillard in PnX-SI/GeoNature#1456 (comment)

GN2GN - Meta_update_date GeoNature synthese

When I imported data from another GeoNature to mine I checked if all variables were logical and I reported :
Create and update dates synthese

I launched gn2pg-cli --full <myconfigfile> at 2021-04-26 11:48 so the creation date is logical but not the update one.
As it is the first time this added to my synthesis I suggest to have create and update date identical. Otherwise, we can keep create and update dates as the one in the source GeoNature ?

What do you think ?

Nomenclatures - Utiliser les codes plutôt que les labels

Actuellement ce sont les labels qui sont utilisés pour retrouver les correspondances des nomenclatures.
Cependant ceci ne sont pas forcément très stables, et parfois modifiés sur une instance GeoNature.
Les codes des nomenclatures sont plus robustes.
De plus ils disposent déjà de leur fonction get_id_nomenclature (https://github.com/PnX-SI/Nomenclature-api-module/blob/master/data/nomenclatures.sql#L99)

Il faudrait donc plutôt utiliser ces codes plutôt que les labels.
Pour le moment ce sont les labels qui ont été utilisés car ce sont les labels qui sont utilisés dans l'export SINP fourni par défaut dans le module Export de GeoNature.
Cependant il faudrait peut-être privilégier de créer un autre export, éventuellement taillé sur mesure pour GN2GN, qui utiliserait les codes, et serait plus stable dans le temps et dédié aux échanges entre instances GeoNature.

Etude des performances et propositions d'améliorations

Bonjour,

Dans le cadre d'une prestation avec le PN des Ecrins pour le SINP , nous devions analyser le module GN2PG pour proposer des améliorations .

Voici ce que nous avons noté :

  • Il y a des appels séquentiels qui sont réalisés notamment dans les fonctions store et update du fichier download.py :

    GN2PG/gn2pg/download.py

    Lines 100 to 113 in ecd0444

    for p in pages:
    resp = self._api_instance.get_page(p)
    items = resp["items"]
    len_items = len(items)
    total_len = resp["total_filtered"]
    progress = progress + len_items
    logger.info(
    f"Storing {len_items} datas ({progress}/{total_len} "
    f"{round((progress/total_len)*100,2)}%)"
    f"from {self._config.name} {self._api_instance.controler}"
    )
    self._backend.store_data(
    self._api_instance.controler, resp["items"]
    )
    . Nous proposons de les paralléliser . Nous avons fait des tests préliminaires avec la librairie multiprocessing.

  • Il y a des listes qui pourraient être remplacées par des générateurs en utilisant des yield . Exemple de la liste d'URL créée dans la fonction _page_list du fichier api.py

    GN2PG/gn2pg/api.py

    Lines 193 to 197 in ecd0444

    for p in range(total_pages):
    offset_params = list(params)
    offset_params.append(("offset", p))
    page_list.append(self._url(kind, offset_params))
    return page_list

  • Le processus de récupération du nombre de pages total prend du temps . En effet une première requête est effectuée et récupére 1000 données (valeur renseignée par défaut) et ces dernières ne sont pas utilisées. Du coup,on a identifié 3 solutions possibles :

    1. Un paramétrage en dur dans la requête "GET" effectuée dans la fonction _page_list du fichier api.py ("limit"=1 et retrait des paramètres "order_by" et "offset")
           r = session.get(
           url=api_url,
           # --> params = {"limit":1}
           )
    1. Exploiter le premier appel pour récupérer les premiers items et donc n'effectuer que n-1 appels par la suite
    2. Créer une nouvelle route dans le module d'export pour obtenir que l'information qui nous intéresse ici, à savoir le nombre total de pages. Exemple : /api/exports/swagger/1/count

Nous avons aussi exploré deux autres pistes d'amélioration : factoriser quelques lignes de codes répétées (notamment dans le fichier gn2pg/download.py ), et un peu de refactorisation (par exemple : utilisation du paramètre params de la librairie requests)

Avec @ophdlv et @mvergez

Index unique sur uuid_role de la table t_roles obligatoire

Apparemment Gn2Pg nécessite de créer un index unique sur le champ uuid_role de la table utilisateurs.t_roles. Or, par défaut dans GeoNature, cet index n'existe pas.

Je n'ai pas trouvé mention du besoin de cet index dans la doc ou les fichiers SQL d'exemple de Gn2Pg.

J'ai rajouté l'index nécessaire avec la requête:

-- Add unique constraint to utilisateurs.t_roles on uuid_role
CREATE UNIQUE INDEX IF NOT EXISTS uidx_t_roles_uuid_role
    ON utilisateurs.t_roles (uuid_role) ;

Exemple de log d'erreur:

2022-05-29 23:17:53,479 - CRITICAL - store_postgresql:store_1_data - One error occured for data from source flavia with id_synthese = 1777427. Error message is (psycopg2.errors.InvalidColumnReference) ERREUR:  il n'existe aucune contrainte unique ou contrainte d'exclusion correspondant à la spécification ON CONFLICT
CONTEXT:  instruction SQL « INSERT INTO utilisateurs.t_roles (
            uuid_role,
            nom_role,
            prenom_role,
            email,
            champs_addi
        )
        VALUES (
            (_actor_role ->> 'uuid_actor')::UUID,
            _actor_role #>> '{identity,first_name}',
            _actor_role #>> '{identity,last_name}',
            _actor_role ->> 'email',
            jsonb_build_object('source', _source, 'module', 'gn2pg')
        )
        ON CONFLICT (uuid_role) DO NOTHING »
fonction PL/pgSQL gn2pg_flavia.fct_c_get_or_create_actors_in_usershub(jsonb,character varying), ligne 26 à instruction SQL
instruction SQL « INSERT INTO gn_meta.cor_dataset_actor (id_dataset, id_role, id_nomenclature_actor_role)
                VALUES ( _id_dataset
                       , gn2pg_flavia.fct_c_get_or_create_actors_in_usershub(i.item, _source)
                       , ref_nomenclatures.get_id_nomenclature('ROLE_ACTEUR', i.item ->> 'cd_nomenclature_actor_role'))
                ON CONFLICT DO NOTHING »
fonction PL/pgSQL gn2pg_flavia.fct_c_insert_dataset_actor(integer,jsonb,character varying), ligne 14 à instruction SQL
instruction SQL « SELECT gn2pg_flavia.fct_c_insert_dataset_actor(the_dataset_id, _ds_data -> 'actors', _source) »
fonction PL/pgSQL gn2pg_flavia.fct_c_get_or_insert_dataset_from_jsondata(jsonb,integer,character varying), ligne 46 à PERFORM
instruction SQL « SELECT gn2pg_flavia.fct_c_get_or_insert_dataset_from_jsondata(new.item #> '{jdd_data}', the_id_af, new.source) »
fonction PL/pgSQL gn2pg_flavia.fct_tri_c_upsert_data_to_geonature_with_metadata(), ligne 77 à instruction SQL

[SQL: INSERT INTO gn2pg_flavia.data_json (source, controler, type, id_data, uuid, item, update_ts) VALUES (%(source)s, %(controler)s, %(type)s, %(id_data)s, %(uuid)s, %(item)s, %(update_ts)s) ON CONFLICT ON CONSTRAINT pk_source_data DO UPDATE SET item = %(param_1)s, update_ts = %(param_2)s]
[parameters: {'source': 'flavia', 'controler': 'data', 'type': 'synthese_with_metadata', 'id_data': 1777427, 'uuid': UUID('f8cc435a-655c-415c-bd61-4b0eb537fea2'), 'item': '{"id_synthese": 1777427, "id_source": "685307", "id_perm_sinp": "f8cc435a-655c-415c-bd61-4b0eb537fea2", "id_perm_grp_sinp": "8c370f73-0dce-4a04-bb3e- ... (2937 characters truncated) ... pe_info_geo": "1", "methode_determination": null, "statut_validation": "2", "validation_date": null, "derniere_action": "2022-05-05 16:53:44.822852"}', 'update_ts': datetime.datetime(2022, 5, 29, 23, 17, 53, 473626), 'param_1': '{"id_synthese": 1777427, "id_source": "685307", "id_perm_sinp": "f8cc435a-655c-415c-bd61-4b0eb537fea2", "id_perm_grp_sinp": "8c370f73-0dce-4a04-bb3e- ... (2937 characters truncated) ... pe_info_geo": "1", "methode_determination": null, "statut_validation": "2", "validation_date": null, "derniere_action": "2022-05-05 16:53:44.822852"}', 'param_2': datetime.datetime(2022, 5, 29, 23, 17, 53, 473752)}]
(Background on this error at: https://sqlalche.me/e/14/f405)

'dict' object does not support indexing

Lauching gn2pg_cli --custom-script to_gnsynthese my_config returns

'dict' object does not support indexing , failed to apply script to_gnsynthese

pip installation seems to be ok and data synchronisation to data_json works, but an error occurred on psycopg2-binary installation : but seems to be solved with python3 -m pip install wheel before uninstall et reinstall psycopg2-binary.

GN2PG limit&offset

Nous avons essayé d'importer des données dans la synthèse de GeoNature à partir d'une API d'un autre GeoNature en utilisant GN2PG. Nous avons constaté que nous téléchargions moins de données dans la base (4 205 données) que le nombre total de données de l'export (7 110).

En cherchant d'où venait le problème, nous avons remarqué que certaines données étaient manquantes (par rapport aux données contenues dans le csv) et que certaines étaient répétées.

Le problème vient de l'API d'export de GeoNature et plus particulièrement au niveau de la requête avec une limite et offset.
D'après la documentation de Postgresql: https://www.postgresql.org/docs/9.3/queries-limit.html
"When using LIMIT, it is important to use an ORDER BY clause that constrains the result rows into a unique order. Otherwise you will get an unpredictable subset of the query's rows. "

Nous allons donc mettre un ticket sur le module d'export, et essayer de résoudre le problème.

Connection abort on gn_module_export > 1.5

Connection abort exception occure after " Successfully logged in into GeoNature" and PARAMS.

A token have been added on gn_module_export after version 1.5, may be the problem ?

Problème lors de l'import vers la synthèse de GeoNature via le script to_gnsynthese

Dans le cadre d’une prestation avec le PN des Ecrins nous devions proposer des améliorations pour le module GN2PG .

Nous avons d’abord fait un export vers un schéma postgresql que nous avons ensuite essayé d'importer vers la synthèse d'un GeoNature via la commande : gn2pg_cli --custom-script to_gnsynthese <myconfigfile>.

Pour rappel, ce script (to_gnsynthese.sql) crée des triggers qui insèrent chaque donnée importée dans la synthèse. Lors du lancement de la commande gn2pg_cli --full <myconfigfile> nous avons rencontré des erreurs d'insertion dans la synthèse. Elles étaient dues à un mauvais format de l'export. Effectivement, ce dernier ne contenait pas les informations nécessaires de chaque Jeu De Donnée/Cadre d'Acquisition (GN2PG attend ces informations au format json). Ce qui amène à la question suivante : souhaitez-vous que l'on crée un script sql pour insérer dans la synthèse en spécifiant le jeu de donnée (à l'instar du module d'import) ? Cela éviterait alors de créer un export spécifique à GN2PG et donc permettrait de le rendre plus adaptable aux exports déjà existants.

Avec @mvergez et @ophdlv

Clé/valeur UUID doit être optionnel

Aujourd'hui, le processus d'intégration des données en bdd requiert un champ d'UUID dans les données sources (par défaut, id_perm_sinp, même si l'UUID est null). Il devrait être possible d'intégrer des données dans clé/valeur UUID.

Datasets are not added correctly in GeoNature gn_meta.t_dataset

For the moment, for each line that is created or updated in the data_json, a dataset is created with a new id.
Therefore, for ten lines from the same dataset in the source, ten datasets are created in my database.
It is an issue coming from

CREATE OR REPLACE FUNCTION gn2pg_import.fct_c_get_or_insert_basic_dataset_from_uuid_name (_uuid uuid, _name text, _id_af int)

Line 58 should be :

BEGIN
    INSERT INTO gn_meta.t_datasets (unique_dataset_id, id_acquisition_framework, dataset_name, dataset_shortname, dataset_desc, marine_domain, terrestrial_domain, meta_create_date)
    SELECT
        _uuid

I will test it and add it in the PR #7

Erreur en fin d'update sur 'total_filtered'

La fin des update se termine sur une erreur du à la clé total_filtered manquante dans l'API de log des DELETE, présente dans la version initiale qui s'appuyait sur la class 'GenericQuery' de Utils-flask-SQLAlchemy.

https://github.com/PnX-SI/Utils-Flask-SQLAlchemy/blob/bb84968353982951fd24d47e815a104df7322521/src/utils_flask_sqla/generic.py#L284-L290.

2023-08-31 23:07:56,778 - DEBUG - store_postgresql:__exit__ - Closing database connection at exit from StorePostgresql
Traceback (most recent call last):
  File "/home/lpoaura/.local/bin/gn2pg_cli", line 8, in <module>
    sys.exit(run())
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/main.py", line 194, in run
    return main(sys.argv[1:])
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/main.py", line 187, in main
    update(cfg_ctrl)
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/helpers.py", line 138, in update
    update_1source(Data, cfg)
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/helpers.py", line 118, in update_1source
    downloader.update()
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/download.py", line 259, in update
    deleted_pages = self._api_instance.page_list(
  File "/home/lpoaura/.local/lib/python3.9/site-packages/gn2pg/api.py", line 189, in page_list
    total_filtered = resp["total_filtered"]
KeyError: 'total_filtered'

Screenshot 2023-09-07 at 16-27-54 https __geonature lpo-aura org

Quel nom pour l'application?

Cette application, initialement spécifiquement conçue pour les transfert de données entre instances GeoNature (synthèse à synthèse) s'avère finalement plus générique.

Le cœur de cette application permet de transférer n'importe quelle données (synthèse mais aussi tout autre données) issues du module d'exports dans une base de données PostgreSQL (GeoNature ou autre).

Seul le procédé de mise à jour incrémentale sera, pour le moment, spécifique à la synthèse.

De fait, se pose la question de trouver un nom plus proche de la réalité de cette application. nous sommes preneur de toutes idées 😃

Liste d'améliorations possibles

Je dresse ici, pour mémo, une liste des améliorations qui seraient intéressantes:

  • indiquer dans la base de données dès le démarrage du script le nombre de données à télécharger prévues. Cela permet de mettre en place un mécanisme de surveillance de l'avancement et d'avoir une estimation du temps de téléchargement à prévoir.
  • améliorer les logs de Gn2Pg, ce qui apparaît à l'écran n'est pas logué dans les fichiers. Il faudrait pouvoir définir un niveau de log dans le fichier de config et qu'il s'applique à tout le code de Gn2Pg.
  • envisager la possibilité de mettre en base de données les logs. Cela permettrait au Dashboard d'avoir plus d'intérêt et faciliterait la mise en place d'outils de surveillance du fonctionnement de Gn2Pg...
  • mettre en place un mécanisme de reprise sur erreur automatique en cas d'échec d'un téléchargement. Suivant l'erreur, Gn2Pg devrait pouvoir retenter un certain nombre de fois avec un temps de pause entre chaque tentative.
  • si le téléchargement a échoué (erreur réseau, base fournisseur injoignable, ...) et que Gn2Pg s'est arrêté, il faudrait mettre en place un mécanisme de reprise automatique du téléchargement à partir de la dernière donnée téléchargée.
  • Garder en base l'historique des lancements de Gbn2Pg et surtout les dates correspondant au champ last_ts de la table increment_log utilisée à chaque lancement.

Feat - Incremental download begin date

Hi @lpofredc ,
I don't know what you planned to do but after discussing with JP Milcent from the CBNA, I think it is interesting to configure a begin date of the incremental download (in the config file ?). For large dataset, it will allow a first manual import and then start incremental downloads from a defined date thanks to your log history table.

Was it your vision ?

Thanks for your opinion !

Deleting data does not works

Hi,

Deleting data does not work well

All seems to be ok on server "giver" side, deleted data are well stored and returned by dedicated route. Client side, gn2pg detect how many data it have to delete, and wich rows (message "deleting object with id XX" return id of data to delete with -v option). Nevertheless, data are not deleted into data_json table.

[BUG] Delete don't work when config source name contains upper cases

What is the bug or the crash?

Delete process use raw source name, while stored value is a slug.
In consequence, delete process can't find data to delete, searched in database by both source and id.

Steps to reproduce the issue

  • having a source with upper case or special characters

Versions

latest

Additional context

No response

StorePostgresql object has no attribute log

Hi,

I'm testing gn2pg app,

Setup and config file init were OK, but launching gn2pg_cli --full returns error :

Traceback (most recent call last):
File "/home/geonatureadmin/venv/bin/gn2pg_cli", line 8, in
sys.exit(run())
File "/home/geonatureadmin/venv/lib/python3.9/site-packages/gn2pg/main.py", line 201, in run
return main(sys.argv[1:])
File "/home/geonatureadmin/venv/lib/python3.9/site-packages/gn2pg/main.py", line 191, in main
full_download(cfg_ctrl)
File "/home/geonatureadmin/venv/lib/python3.9/site-packages/gn2pg/helpers.py", line 101, in full_download
full_download_1source(Data, cfg)
File "/home/geonatureadmin/venv/lib/python3.9/site-packages/gn2pg/helpers.py", line 81, in full_download_1source
downloader.store()
File "/home/geonatureadmin/venv/lib/python3.9/site-packages/gn2pg/download.py", line 88, in store
self._backend.log(
AttributeError: 'StorePostgresql' object has no attribute 'log'

Optimisation des triggers de mise à jour de la synthèse

Dans le cadre d'une prestation avec le Parc National des Ecrins, je me suis intéressée aux performances des triggers mis en place sur la table data_json pour mettre à jour la synthèse.

Contexte

Il y a au total quatre triggers, qui sont définis dans to_gnsynthese.sql :

  • 3 triggers pour les opérations d'INSERT/UPDATE, un par type de données (i.e., synthese_with_label, synthese_with_cd_nomenclature et synthese_with_metadata)
  • 1 trigger pour l'opération DELETE, prenant en charge les trois types de données.

Le jeu de données utilisé pour quantifier les performances était constitué de 1128 lignes. Il a été mesuré qu'en moyenne l'activation des triggers augmentait le temps d'exécution de 2,7 fois.
Une solution envisagée pour améliorer cela était de passer d'un traitement AFTER EACH ROW à un traitement AFTER EACH STATEMENT.

En outre, il a été identifié que :

  • certaines lignes étaient répétées (i.e., DROP TRIGGER IF EXISTS tri_c_upsert_data_to_geonature_with_nomenclature_label ON gn2pg_import.data_json présents l.165 et l.540 et DROP TRIGGER IF EXISTS tri_c_upsert_data_to_geonature_with_cd_nomenclature ON gn2pg_import.data_json présents l.553 et l.930)
  • des portions de codes étaient identiques entre les triggers et pourraient potentiellement être regroupées.

Dans ce contexte, trois solutions ont été étudiées et sont présentées dans la section ci-après.

Résultats des tests

1. Mise en place d'un traitement par statement et d'un trigger unique quelque soit le type de données.

Dans cette solution, trois triggers sont implémentés : INSERT, UPDATE, DELETE. Chacun prend en charge les trois types de données. Les opérations de INSERT et d'UPDATE ont dû être séparées car la OLD TABLE nécessaire lors de l'UPDATE, n'est pas définie lors de l'INSERT.
Les performances mesurées étaient comparables avec l'existant.

2. Mise en place d'un traitement par statement et conservation d'un trigger par type de données.

Dans cette solution, sept triggers ont été implémentés : un trigger INSERT + un trigger UPDATE pour chaque type de données, et un trigger DELETE général.
D'une part, les performances étaient comparables à l'existant et d'autre part, le code était beaucoup plus long.

3. Conservation du traitement par ligne et mise en place d'un trigger unique quelque soit le type de données.

Dans cette solution, seuls deux triggers sont mis en place : un pour l'INSERT/UPDATE et un pour le DELETE, chacun prenant en charge tous les types de données. Les performances mesurées avec cette solution sont comparables à l'existant.

Conclusion

Aucune des solutions mises en place n'a permis d'améliorer les performances.
Cependant, bien que la solution 2 ne présente aucun avantage par rapport à l'existant, les solutions 1 et 3 évitent les portions de codes répétées (d'autant plus pour la solution 3) et réduisent la longueur du code d'un facteur ~2.
Cela pourrait être avantageux pour simplifier le maintien du code.
Je n'ai pas joint les fichiers de ces solutions en raison de leur longueur (800-900 lignes) mais je peux vous les mettre à disposition si vous le souhaitez.

Bad recuperation for person as metadata actors

In export views, there is a coalesce on nom_organism / concat(nom_role, prénom_role), but trigger target two fields for persons : nom_role, prenom_role, wich have been concat in export.

The coalesce complicate the recuparation of nom/prenom

GN2PG - Don't fetch data your already have

GN2PG takes a non negligible time to import data (1h for 60000 in my case).
Further more, it reaches all the data that are available from the export every time you run it.

Therefore, it would interesting for GN2PG to fetch data that have been created or updated after the last valid import

As a user and not a developer I suppose that the export must be correctly configured in GeoNature and then API selects only the data with create or update date > last import date. You thus need to store the last complete import date.

Will be very interesting to automate import every day/week/month between two or more structures !

Première utilisation GN2PG - Corrections to_gnsynthese.sql et coquilles

Bonjour,
Après quelques temps de travail, je suis (pas tout seul) enfin arrivé à bout d'un import de GN2GN.
Cependant j'ai rencontré quelques embûches que je voulais partager et que je vais corriger dans une PR dès que possible.

En reprendant les étapes :
Mise en place du schéma dans ma base : OK
Mise en place des triggers pour insertion dans ma synthèse directement (en utilsant to_gnsynthese.sql) : PAS OK pour deux raisons.

D'une part la mise en place de la contrainte unique

CREATE UNIQUE INDEX IF NOT EXISTS uidx_synthese_id_source_id_entity_source_pk_value ON 
gn_synthese.synthese (id_source, entity_source_pk_value);

est impossible lorsque j'ai des doublons déjà présents dans ma synthèse.

J'ai du les supprimer à l'aide de
PnX-SI/GeoNature@02b704f

D'autre part, lorsque le cadre d'acquisition des données n'éxistait pas dans ma base, il fallait le créer. Or la création a besoin d'un champ meta_create_date qu'il a fallu rajouter à la fonction fct_c_get_or_insert_basic_af_from_uuid_namede telle sorte que le code ressemble à

INSERT INTO gn_meta.t_acquisition_frameworks (unique_acquisition_framework_id, acquisition_framework_name, acquisition_framework_desc, acquisition_framework_start_date, meta_create_date)
    SELECT
        _uuid,
        _name,
        'Description of acquisition framework : ' || _name,
        now(),
        now()
...

Une fois ça j'ai pu observer les données dans la synthèse.
Donc :
Import GNPG OK
Visualisation dans la synthèse OK

Il me reste à faire en sorte que le type dans la table data_json soit bien renseigné, parce que je le fais pour l'instant manuellement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.