Note Technique de spécification d'interface
#
1. Contexte
L'objet du présent document est de définir le contrat d'interface en termes d'API REST entre le portail RUDI et un nœud producteur RUDI.
Le portail RUDI étant décomposé en micro-services, la communication entre un nœud producteur et le portail RUDI se fait au travers du micro-services « µKollect ».
#
2. Collecte des métadonnées
La collecte des métadonnées est réalisée par le module « Mise à jour catalogue ».
Le module fonctionne selon 2 modes :
- Mode « notification » (ou push depuis le nœud producteur)
- Mode « moissonnage » (ou pull depuis le portail)
1.1. Collecte en mode « Notification »
En mode « notification », le diagramme de séquence d'appel est le suivant :
Figure 1 - Diagramme de séquence "notification"
Comme l'indique le schéma ci-dessus, le nœud producteur peut appeler le module de collecte (µKollect) du portail RUDI afin de déposer une demande de collecte. Cette demande comporte :
- L'identifiant unique du jeu de données
- La nature de la modification : création, modification des métadonnées ou suppression d'un jeu de données.
- Les métadonnées du jeu de données
Lors de la réception de ce message, le module de collecte va l'ajouter dans la pile des demandes à traiter persistée en base de données et envoie un accusé de réception au nœud producteur.
Le module de collecte va dépiler de manière asynchrone la liste des messages afin de réaliser les opérations demandées.
A l'issue du traitement, le module de collecte envoie au nœud producteur un rapport d'intégration indiquant le résultat de l'intégration et éventuellement des informations de qualité des métadonnées.
1.2. Collecte en mode « Moissonnage »
En mode « moissonnage », le diagramme de séquence d'appel est le suivant :
Figure 2 - Diagramme de séquence "moisonnage"
Comme l'indique le schéma ci-dessus, le module de collecte des données du portail RUDI commence par appeler le nœud producteur afin de collecter par leur identifiant unique tous les jeux de données dont les métadonnées ont été modifiées depuis la dernière date de collecte réussie.
Les modifications peuvent être des créations, des mises à jour ou des suppressions de jeux de données.
Pour chaque jeu de données créé ou modifié qui a été identifié par l'opération précédente, le module de collecte appelle le nœud producteur afin de récupérer les métadonnées.
Le module de collecte traite ensuite de manière asynchrone l'intégration des données et la suppression des jeux de données.
Pour chaque jeu de données traité, le module de collecte envoi au nœud producteur d'origine un rapport d'intégration indiquant le résultat de l'intégration.
Ce rapport d'intégration à vocation à permettre à un nœud producteur de ne fonctionner que par moissonnage et d'être ainsi informé qu'un jeu de données particulier a été intégré dans le portail.
#
3. contrat d'interface Portail / nœud PRODUCTEUR
3.1. Périmètre
Le contrat d'interface RUDI/Producteur porte sur les grands thèmes suivants :
- Jeux de données
- L'interface proposée doit permettre au portail RUDI d'accéder aux données des jeux de données publiés dans le portail RUDI par un nœud producteur.
- Chaque jeu de données doit être identifié de manière unique au sein de RUDI.
- Métadonnées
- L'interface proposée doit permettre au portail RUDI :
- La collecte des métadonnées d'un jeu de données proposé par le producteur à partir de l'identifiant unique
- La notification de l'intégration des métadonnées d'un jeu de données
- L'interface proposée par RUDI doit permettre aux producteurs de notifier la modification des métadonnées d'un jeu de données.
- Données
- L'interface proposée doit permettre au portail RUDI de récupérer les données d'un jeu de données.
- Cette récupération doit pouvoir être réalisée en fonction de l'utilisateur humain ou non ayant demandé les données mais aussi si possible en prenant en compte les notions de pagination, de tri et de filtrage par critère temporel, géographique et par mots-clefs.
- Consentement
- L'interface proposée doit permettre au portail RUDI de transférer au producteur de données, les informations de consentement recueillies par RUDI auprès des utilisateurs. Ce consentement doit être pris en compte lors de la récupération des données.
- Supervision
- L'interface proposée doit permettre au portail RUDI de superviser le nœud du producteur afin de prendre en compte la qualité de service associée.
Pour certains producteurs, le contrat d'interface doit aussi couvrir le thème suivant :
- Appariement
L'interface proposée doit permettre au portail RUDI et au producteur de réaliser l'appariement (mise en correspondance) d'un utilisateur RUDI et d'un utilisateur connu du système du producteur)
3.2. Schéma de données
3.2.1. Format des dates
Les dates sont au format ISO-8601 et prennent la forme :
- YYYY-MM-DD pour les dates
- Exemple : 2020-12-14
- YYYY-MM-DDTH24:MI:SS.nano pour les « date+heure » - ce format est nommé « Timestamp » dans le reste du document.
- Exemple : 2020-12-14T09:56:34.592384024
- YYYY-MM-DDTH24:MI:SS.nano<+/- timezone offset ou Z pour UTC> pour les « date+heure avec time-zone » - ce format est nommé « Timestamp avec time-zone » dans le reste du document.
- Exemple : 2020-12-14T09:56:34.592384024+0100
3.2.2. Rapport d'intégration – #/components/schemas/Report
3.2.2.1. Généralité
Le rapport d'intégration est de la forme suivante :
{
'report\_id': '',
'submission\_date': '',
'treatment\_date': '',
'method' : ('POST'|'PUT'|'DELETE')
'version':'',
'global\_id': '',
'resource\_title': '',
'integration\_status': ('OK'|'KO'),
'comment': '',
'errors': [
{
'error\_code': '',
'error\_message': ''
'field\_name': '',
}
]
}
3.2.2.2 Détail des données
Le tableau ci-dessous présente les données présentes dans le rapport d'intégration et leurs caractéristiques.
Nom balise | Description | Niveau | Obligatoire | Type | Taille |
---|---|---|---|---|---|
report_id | Identifiant du rapport d'intégration | 1 | Oui | UUID v4 | |
submission_date | Date de soumission de la demande d'intégration | 1 | Oui | Timestamp | |
treatment_date | Date de traitement de l'intégration du jeu de donnéesdans Rudi | 2 | Oui | Timestamp | |
version | Numéro de la version de l'API utilisée par le nœud producteur pour communiquer avec le portail RUDI | 1 | Oui | Numérique | 2 |
method | Méthode de soumission utilisée | 1 | Oui | Enuméré | 6 |
resource_id | Identifiant du jeu de donnéesdans le système Rudi | 2 | Oui | UUID v4 | |
title | Nom du jeu de données | 2 | Non | Texte | Identique à lAPI |
Integration_status | État de l'intégration du jeu de donnéesdans Rudi. 2 valeurs possibles :·OK : l'intégration du jeu de données s'est bien déroulée·KO : l'intégration du jeu de données est en erreur | 2 | Oui | Enuméré | 2 |
comment | Commentaire sur l'état de l'intégration. Formaté.·Si etat_integration = OK, commentaire = l'intégration du jeu de données"nom_jeu_de_donnee" s'est bien déroulée le "date_traitement_jdd_Rudi".·Si etat_integration = KO, commentaire = l'intégration du jeu de données"nom_jeu_de_donnee" ne s'est pas déroulée correctement, le "date_traitement_jdd_Rudi. Veuillez consulter les erreurs ci-dessous et après correction des erreurs, renvoyer votre jeu de données. Pour plus d'information, vous pouvez contacter votre administrateur Rudi.". | 2 | Oui | Texte | 255 |
errors | Liste des erreurs rencontrées lors de l'intégration du jeu de données. L'objectif est de lister l'ensemble des erreurs rencontrées sur le jeu de données afin d'éviter de multiple envoi pour un même jeu de données(à chaque envoi, une nouvelle erreur est rencontrée). | 2 | Fonction de « status » :·Non si etat_integration = 1·Oui si etat_integration = 0 | Liste dobjets | Infini |
error_code | Code technique de l'erreur(Cf. 3.2.2.3) | 3 | Oui | Texte | 7 |
field_name | Nom du champ concerné par l'erreur (le cas échéant) | 3 | Non | Texte | 30 |
error_message | Descriptif de l'erreur(Cf 3.2.2.3) | 3 | Oui | Texte | 255 |
3.2.2.3. Détail des erreurs possibles
Le tableau ci-dessous liste les différents cas d'erreur possibles.
code_erreur | commentaire_erreur |
---|---|
ERR-101 | Le format du fichier de métadonnées transmis est incorrect. |
ERR-102 | La balise "nom_balise" est inconnue |
ERR-103 | Le paramètre "nom_parametre" est manquant |
ERR-104 | Autres erreurs d'intégration |
ERR-105 | Erreur inconnue: l'erreur n'a pas été reconnue, veuillez contacter l'administrateur Rudi afin d'analyser l'erreur. |
ERR-106 | La version de metadonnées "api_version" n’est pas supportée. La version courante est X.X.X |
ERR-1XX | …. Erreurs de base, à définir. |
ERR-201 | Le type du champ "nom_champ" n'est pas le bon (format attendu : "format attendu" / format reçu : "format_reçu" ) |
ERR-202 | Le champ "nom_champ" est manquant alors qu'il est obligatoire. |
ERR-203 | La longueur du champ dépasse la limite autorisée: la taille attendue est "taille_champ_Rudi" pour "nom_champ" alors que la longueur de la valeur envoyée est " taille_champ_envoye"). |
ERR-2XX | …. Erreurs sur le type du champ, à définir. |
ERR-301 | Des caractères ne sont pas acceptés dans le "nom_champ" |
ERR-302 | La valeur saisie ne correspond pas au référentiel des valeurs attendues pour le champ "nom_champ" (valeur saisie : "valeur_saisie" / référentiel attendu : "liste des valeurs attendue séparées par des virgules" |
ERR-303 | La valeur saisie "valeur_saisie" pour le champ "nom_champ" ne correspond pas à un code de concept SKOS connu |
ERR-304 | La valeur saisie "valeur_saisie" pour le champ "nom_champ" est déjà utilisée |
ERR-3XX | … Erreur en lien avec les valeurs d'un champ, à définir. |
ERR-403 | Le nœud fournisseur authentifié n’est pas le créateur du jeu de données |
ERR-500 | Une erreur technique est survenue. Veuillez contacter l’administrateur Rudi pour analyser l’erreur. |
ERR-XXX | … Autres types d'erreurs, autres erreurs, à définir. |
3.2.3. Identifiant Rudi
L'identifiant d'un jeu de données RUDI est une chaîne de caractères composée comme suit :
<UUID v4>
L'expression régulière permettant de définir un tel champ est la suivante :
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
3.2.4** Métadonnées d'un jeu de données – Rudi #/components/schemas/Metadata**
Cet objet représente l'ensemble des métadonnées d'un jeu de données (Cf. 4.1).
3.2.5. Liste de métadonnées – #/component/schemas/MetadataList
{
'total': <int64>,
'items': [
#/components/schemas/Metadata
]
}
Nom balise | Description | Niveau | Obligatoire | Type | Taille |
---|---|---|---|---|---|
total | Nombre total d'éléments répondant à la requête | 1 | Oui | Int64 | |
items | Liste des métadonnées | 1 | Oui | List d'objet de type Metadata |
3.3. URL d'accès et gestion du versionnement
Les différentes API sont exposées avec une URL de la forme : <host>/<prefixe>
- <prefixe> prendra la forme api par défaut mais peut prendre d'autres formes si plusieurs typologie d'API sont exposées.
- Exemple <host>/api
L'API dans sa version la plus récente sera exposée en <host>/<prefixe>/*
Cela signifie que la version la plus récente de l'API est accessible directement sans changement de code des appelants.
Les API dans les versions plus anciennes seront exposées en
<host><prefixe><version>/*
- <version> prendra la forme v<Majeur> ou v<Majeur>.<Mineur>
- Exemple : <host>/api/v1 ou <host>/api/v1.1
Cela signifie que les modifications de niveau « Révision » n'ont pas d'impact sur la version de l'API.
Dans la mesure du possible, seul le niveau <Majeur> sera utilisé.
3.4. Contrat d'interface Jeu de données & Métadonnées
3.4.1. Service Portail
3.4.1.1. URL & préfixe
Les différents services décrits ci-après seront accessibles avec le préfixe « api ».
- Exemple <host>/api/*
##
3.4.1.2. Création d'un jeu de données
Description :
Soumission d'une demande de création d'un jeu de données par ses métadonnées
POST <>/resources
Body :
- #/components/schemas/Metadata
Code retour :
- 200 : prise en compte de la demande
- report_id : UUID V4
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
3.4.1.3. Modification des métadonnées d'un jeu de données
Description :
Soumission d'une demande de modification d'un jeu de données par ses métadonnées
PUT <>/resources
Body :
- #/components/schemas/Metadata
Code retour :
- 200 : prise en compte de la demande
- report_id : UUID V4
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu dans la métadonnée est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
3.4.1.4. Suppression d'un jeu de données
Description :
Soumission d'une demande de suppression d'un jeu de données
DELETE <>/resources/{global_id}
Code retour :
- 200 : prise en compte de la demande
- report_id : UUID V4
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu dans la métadonnée est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
3.4.1.5. Obtention d'un Identifiant RUDI
Description :
Demande de génération d'un identifiant RUDI (UUID v4).
L’identifiant RUDI généré tiendra compte des informations contenues dans le token JWT d'authentification pour déduire le producteur.
GET <>/resources/id_generation
Code retour :
- 200 : prise en compte de la demande
- #/components/schémas/RudiId
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu dans la métadonnée est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
3.4.2. Service Noeud
3.4.2.1. URL & préfixe
Les différents services décrits ci-après seront accessibles avec le préfixe « api ».
- Exemple <host>/api/*
3.4.2.2. Recherche des jeux de données
Description :
Recherche des jeux de données
GET <>/resources
Query :
- limit : int32
- offset : int32
- update_date_min : timestamp
- update_date_max : timestamp
- <à compléter>
Code retour :
- 200 : prise en compte de la demande
- #/components/schémas/ResourceListInfo
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 410 :
- $ref: "#/components/responses/Error410Gone"
- 423 :
- $ref: "#/components/responses/Error423Locked"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
<à compléter>
3.4.2.3. Obtention d'un jeu de données
Description :
Obtention des métadonnées d'un jeux de données
GET <>/resources/{global_id}
Code retour :
- 200 : prise en compte de la demande
- #/components/schémas/RudiId
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 410 :
- $ref: "#/components/responses/Error410Gone"
- 423 :
- $ref: "#/components/responses/Error423Locked"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
3.4.2.4. Réception d'un résultat d'intégration
Description :
Réception de l'intégration d'une demande réalisée par les services 3.4.1.2, 3.4.1.3, 3.4.1.4..
PUT <>/resources/{global_id}/report
Body : #/components/schemas/Report
Code retour :
- 200 : Prise en compte du rapport
- 400 :
- $ref: "#/components/responses/Error400BadRequest"
- 401 :
- $ref: "#/components/responses/Error401Unauthorized"
- 403 :
- $ref: "#/components/responses/Error403Forbidden"
- 404 : le global_id contenu dans la métadonnée est inconnu
- $ref: "#/components/responses/Error404NotFound"
- 406 :
- $ref: "#/components/responses/Error406NotAcceptable"
- 408 :
- $ref: "#/components/responses/Error408RequestTimeout"
- 429 :
- $ref: "#/components/responses/Error429TooManyRequests"
- 500 :
- $ref: "#/components/responses/Error500InternalServer"
- 503 :
- $ref: "#/components/responses/Error503ServiceUnavailable"
Les codes suivants impliquent que le portail doit retenter de notifier le nœud producteur du traitement de sa demande :
400, 401, 408, 429, 503
Le portail retentera l'opération 5 fois à 1 heure d'intervalle.
Au-delà de ce délai, une alerte doit être remontée côté portail pour une prise charge humaine.
3.4.3. Exemple de séquencement des appels
3.4.3.1. Notification
Le mécanisme de notification prend place lorsqu'un nœud producteur souhaite informer le portail de la publication (ou republication) d'un jeu de données.
Par exemple, lors de la création d'un nouveau jeu de données par le producteur, le séquencement des appels entre portail et nœud producteur est le suivant :
- Obtention par le nœud d'un token JWT. Ce Point sera détaillé par ailleurs
- Si le producteur le souhaite, il peut demander un identifiant unique auprès du portail (GET <>/resources/generation_id). Cet identifiant unique est appelé « global_id ».
- Attribution par le nœud producteur de l'identifiant au nouveau jeu de données
- Soumission par le nœud d'une demande de création (POST <>/resources) avec la structure de métadonnées attendue
- Réponse du portail par un code 200 avec un identifiant unique correspondant à la demande. Cet identifiant est appelé « report_id ».
- Le portail traite la demande de manière asynchrone (mais dans l'ordre des demandes) et à l'issue de ce traitement le portail appelle le nœud d'origine pour lui transmettre le rapport d'intégration (PUT <>/resources/report/{global_id}
- Réponse du portail par un code 200
- Ou pour les codes 400, 401, 408, 429, 503, 5 nouvelles tentatives possibles espacées d'une heure
3.4.3.2. Moissonnage
Le mécanisme de moissonnage intervient lorsqu'un nœud producteur ne met pas en œuvre le mécanisme de notification. Dans ce cas de figure, le portail, pour réaliser la mise à jour des métadonnées des différentes jeux, vient chercher, sur chaque nœud producteur, les jeux de données dont les métadonnées ont changé.
Le séquencement des appels entre Portail et nœud producteur est le suivant :
- Obtention par le portail d'un token JWT
- Demande auprès du nœud par le portail des différents jeux de données modifiés depuis une date connue du portail (GET <>/resources avec des paramètres et de la pagination)
- Réponse du nœud par un code 200 avec une liste d'éléments
- Pour chaque élément reçu grâce à l'appel précédent, contrôle de la date de dernière modification par rapport à la date connue du portail pour ce jeu de données
- Si le jeu de données doit être mis à jour, récupération des métadonnées du jeu (GET <>/resources/{global_id})
- Réponse du nœud par un code 200 avec les métadonnées du jeu de données
- Enregistrement dans la file d'attente d'une activité de mise à jour (création/modification/suppression)
- Le portail traite la demande et à l'issue de ce traitement le portail appelle le nœud d'origine pour lui transmettre le rapport d'intégration (PUT <>/resources/report/{global_id}
- Réponse du portail par un code 200 ou
- Ou pour les codes 400, 401, 408, 429, 503, 5 nouvelles tentatives possibles espacées d'une heure
#
4. Annexes
4.1. Annexe – Structure des métadonnées
Version de l'API au moment de l'écriture de ce document:
https://app.swaggerhub.com/apis/OlivierMartineau/RUDI-PRODUCER/1.0.3
Dernière version de l'API:
https://app.swaggerhub.com/apis/OlivierMartineau/RUDI-PRODUCER