Chapitre 1

Hermes

Cette section contient une brève présentation d’Hermes et de ses fonctionnalités, puis définit ses concepts clés et détaille le fonctionnement de ses principaux processus.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Sous-sections de Hermes

Présentation

Qu’est-ce qu’Hermes ?

Hermes est un outil de capture des changements de données (CDC) depuis n’importe quelles sources vers n’importe quelles cibles.

Flux de fonctionnement simplifié

Le serveur Hermes interrogera régulièrement les sources de données et générera un différentiel entre le nouvel ensemble de données et le précédent issu du cache. Chaque différence sera convertie en un message d’événement et envoyée à un bus de messages (e.g. Kafka, RabbitMQ…).

Les clients recevront et traiteront chaque message d’événement pour propager les données vers leurs cibles respectives.

flowchart LR
  subgraph Datasources["Sources de données"]
    direction LR
    RefOracle
    RefPostgreSQL
    RefLDAP
    RefEtc
  end
  subgraph Hermes-server
    direction LR
    hermes-server
  end
  subgraph External_dependencies["Dépendences externes"]
    direction LR
    MessageBus
  end
  subgraph Hermes-clients
    direction LR
    hermes-client-ldap
    hermes-client-aspypsrp-ad
    hermes-client-webservice
    hermes-client-etc["..."]
  end
  subgraph Targets["Cibles"]
    direction LR
    LDAP
    ActiveDirectory
    webservice
    etc
  end
  RefOracle[(Oracle)]-->|Données|hermes-server
  RefPostgreSQL[(PostgreSQL)]-->|Données|hermes-server
  RefLDAP[(LDAP)]-->|Données|hermes-server
  RefEtc[(...)]-->|Données|hermes-server
  hermes-server-->|Événements|MessageBus(("Bus de message"))
  MessageBus-->|Événements|hermes-client-ldap
  MessageBus-->|Événements|hermes-client-aspypsrp-ad
  MessageBus-->|Événements|hermes-client-webservice
  MessageBus-->|Événements|hermes-client-etc
  hermes-client-ldap-->|Met à jour|LDAP[(LDAP)]
  hermes-client-aspypsrp-ad-->|Met à jour|ActiveDirectory[(Active Directory)]
  hermes-client-webservice-->|Met à jour|webservice[(Web service <i>nom</i>)]
  hermes-client-etc-->|Met à jour|etc[("...")]

  classDef external fill:#fafafa,stroke-dasharray: 5 5
  class Datasources,External_dependencies,Targets external

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Fonctionnalités

  • Ne nécessite aucune modification du ou des modèles de données sources (e.g. pas besoin d’ajouter une colonne last_updated)
  • Multi-source, avec possibilité de fusionner ou d’agréger des données, et éventuellement de définir des contraintes de fusion/agrégation
  • Capable de gérer plusieurs types de données, avec des liens (clés étrangères) entre elles, et d’appliquer des contraintes d’intégrité
  • Capable de transformer des données avec des filtres Jinja dans les fichiers de configuration : pas besoin d’éditer du code Python
  • Gestion des erreurs propre, pour éviter les problèmes de synchronisation, et un mécanisme optionnel d’auto-remédiation des erreurs
  • Propose une corbeille sur les clients pour les données supprimées
  • Insensible à l’indisponibilité et aux erreurs sur chaque lien (source, bus de messages, cible)
  • Facile à étendre par conception. Tous les éléments suivants sont implémentés en tant que plugins (liste des plugins existants) :
    • Sources de données
    • Filtres d’attributs (filtres de données)
    • Clients (cibles)
    • Bus de messages
  • Les modifications apportées au modèle de données sont faciles et sûres à intégrer et à propager, que ce soit sur le serveur ou sur les clients

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Concepts clé

Source de données

Une source depuis laquelle le serveur va collecter des données. Cela peut être tout ce qui contient des données : base de données, annuaire LDAP, service Web, fichier plat…

Plugin source de données

Un plugin Hermes chargé de collecter des données à partir d’un type de source de données spécifique et de les fournir au serveur.

Serveur

application hermes-server : interroge les sources de données à intervalles réguliers et convertit tous les changements entre les données récentes et les données précédentes en événements qui seront envoyés sur un bus de messages par un plugin producteur de bus de messages.

Bus de messages

Service externe comme Apache Kafka ou RabbitMQ qui collecte les événements du serveur et les fournit aux clients dans le même ordre que celui où ils ont été émis.

Plugin producteur de bus de messages

Un plugin Hermes exécuté par le serveur, chargé d’émettre des événements sur un type de bus de messages spécifique.

Plugin consommateur de bus de messages

Un plugin Hermes exécuté par les clients, chargé de consommer des événements depuis un type de bus de messages spécifique.

Client

application hermes-client : consomme les événements du bus de messages via le plugin consommateur de bus de messages et appelle les méthodes appropriées implémentées sur le plugin client pour propager les changements de données sur la cible.

Corbeille

Si activée dans la configuration, le client ne supprimera pas immédiatement les données mais les stockera dans la corbeille pendant le nombre de jours configuré. Si les données sont ajoutées à nouveau durant ce délai, le client les restaurera depuis la corbeille. Sinon, une fois la limite de rétention de la corbeille atteinte, les données seront supprimées.

Selon l’implémentation choisie sur le plugin client, cela peut permettre de nombreux scénarios, e.g. désactiver un compte ou le garder actif pendant une période de grâce.

File d’erreurs

Lorsqu’une exception est levée lors du traitement d’un événement sur le plugin client, l’événement est stocké dans une file d’erreurs. Tous les événements suivants concernant les mêmes objets de données ne seront pas traités mais stockés dans la file d’erreurs jusqu’à ce que le premier soit traité avec succès. Le traitement des événements dans la file d’attente d’erreurs est relancé périodiquement.

Auto remédiation

Parfois, un événement peut être stocké dans la file d’erreurs en raison d’un problème de données (e.g. un nom de groupe avec un point terminal génèrera une erreur sur Active Directory). Si le point terminal est ensuite supprimé du nom de groupe sur la source de données, l’événement modified sera stocké dans la file d’erreurs et ne sera pas traité tant que le précédent n’aura pas été traité, ce qui ne pourra jamais se produire sans procéder à une opération risquée et non-souhaitable : l’édition manuelle du fichier cache du client.

L’auto remédiation résout ce type de problèmes en fusionnant les événements d’un même objet dans la file d’erreurs. Elle n’est pas activée par défaut, car elle peut perturber l’ordre de traitement normal des événements.

Plugin client

Un plugin Hermes exécuté par le client, chargé d’implémenter des méthodes simples de traitement d’événements visant à propager les changements de données vers un type de cible spécifique.

Plugin d’attribut

Un plugin Hermes exécuté par le serveur ou le client qui sera utilisable comme un nouveau filtre Jinja, permettant de modifier des données.

Initsync

Un client ne peut pas commencer à traiter de nouveaux événements en toute sécurité sans disposer de l’ensemble du jeu de données complet préalable. Ainsi, le serveur est capable d’envoyer une séquence d’événements spécifique appelée initsync qui contiendra le modèle de données serveur et l’ensemble de données. Un client déjà initialisé l’ignorera silencieusement, mais un client non initialisé le traitera pour initialiser sa cible en ajoutant toutes les entrées fournies par la séquence initsync, puis commencera ensuite à traiter normalement les événements suivants.

Modèle de données (datamodel)

Comme il existe des différences entre eux, veuillez consulter modèle de données serveur et modèle de données client.

Type de données

Également nommé “type d’objet”. Un type de données avec son mapping d’attributs qui sera géré par Hermes.

Clé primaire

L’attribut type de données qui permet de distinguer une entrée d’une autre. Il doit évidemment être unique.

Modèle de données serveur

Configuration des types de données que le serveur doit gérer, avec leurs mapping d’attributs respectifs. Le nom de l’attribut distant est le nom de l’attribut utilisé sur la source de données.

Le modèle de données du serveur est construit en spécifiant les éléments suivants :

Politique de conflit de fusion

Définit le comportement si un même attribut obtient des valeurs différentes sur différentes sources de données.

Contraintes de fusion

Permet de déclarer des contraintes pour garantir la cohérence des données lors de la fusion des données, lorsque le serveur interroge plusieurs sources de données.

Clés étrangères

Permet de déclarer des clés étrangères dans un type de données, que les clients utiliseront pour appliquer leur politique de clés étrangères. Voir Clés étrangères pour plus de détails.

Contraintes d’intégrité

Permet de déclarer des contraintes entre plusieurs types de données pour assurer la cohérence des données.

Attributs à ne mettre qu’en cache

Attributs du modèle de données qui seront uniquement stockés dans le cache, mais ne seront ni envoyés dans les événements, ni utilisés lors de la comparaison avec le cache.

Attributs secrets

Attributs du modèle de données qui contiendront des données sensibles, comme des mots de passe, et ne doivent jamais être stockés dans le cache ni affichés dans les journaux. Ils seront tout de même envoyés aux clients, à moins qu’ils ne soient également définis comme attributs locaux.

Remarque

Comme ces attributs ne sont pas mis en cache, ils seront considérés comme ajoutés CHAQUE fois que le serveur interrogera les sources de données.

Attributs locaux

Attributs du modèle de données qui ne seront pas envoyés dans les événements, mis en cache ni utilisés lors de la comparaison avec le cache, mais qui pourront être utilisés dans les templates Jinja.

Modèle de données client

Configuration des types de données que le client doit gérer, avec leur mapping d’attributs. Le nom de l’attribut distant est le nom de l’attribut utilisé sur le modèle de données du serveur.

Information

Si vous vous demandez pourquoi ce mapping est nécessaire, voici pourquoi :

  1. il permet la transformation des données locales via des filtres Jinja et les plugins d’attribut sur le client.
  2. il permet de réutiliser (et de partager) les plugins client sans nécessiter de modification du modèle de données serveur ni du code du plugin, mais simplement en modifiant le fichier de configuration client.

Le modèle de données client est construit en spécifiant les éléments suivants :

Mapping d’attributs

Également appelé “attrsmapping”. Mapping (clé/valeur) qui associe le nom de l’attribut interne (en tant que clé) à celui distant (en tant que valeur). Le distant peut être un modèle Jinja pour transformer des données avec des filtres Jinja et des plugins d’attribut.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Fonctionnement

Explications sur le fonctionnement ou la structure de certains composants clés.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Sous-sections de Fonctionnement

hermes-server

Explications sur le fonctionnement ou la structure de certains composants clés d’hermes-server.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Sous-sections de hermes-server

Workflow

hermes-server

  • 1. charge son cache local
  • 2. vérifie si son schéma de données a changé depuis la dernière exécution, et émet les événements supprimés résultants (le cas échéant), ainsi que le nouveau schéma de données
  • 3. récupère toutes les données requises par son modèle de données depuis la ou les sources de données
    • 3.1. applique les contraintes de fusion
    • 3.2. fusionne les données
    • 3.3. remplace les incohérences et les conflits de fusion par les valeurs en cache
    • 3.4. applique les contraintes d’intégrité
  • 4. génère un différentiel entre son cache et les données distantes récupérées
  • 5. boucle sur chaque type de différence : ajout, modification, suppression
    • 5.1. pour chaque type de différence, boucle sur chaque type de données selon leur ordre de déclaration dans le modèle de données, à l’exception du type de différence supprimé, pour lequel il s’agit de l’ordre de déclaration inverse
      • 5.1.1. boucle sur chaque différence du type de données actuel
        • 5.1.1.1. génère l’événement correspondant
        • 5.1.1.2. émet l’événement sur le bus de messages
        • 5.1.1.3. si l’événement a été émis avec succès :
          • 5.1.1.3.1. exécute l’action commit_one du modèle de données le cas échéant
          • 5.1.1.3.2. met à jour le cache pour refléter la nouvelle valeur de l’élément affecté par l’événement
  • 6. une fois que tous les événements ont été émis
    • 6.1. exécute l’action commit_all du modèle de données le cas échéant
    • 6.2. enregistre le cache sur le disque
  • 7. attend updateInterval et recommence à partir de l’étape 3. si l’application n’a pas été invitée à s’arrêter

Si une exception est levée à l’étape 2., cette étape est recommencée jusqu’à ce qu’elle réussisse.

Si une exception est levée aux étapes 3. à 7., le cache est enregistré sur le disque et le serveur recommence à partir de l’étape 3..

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Contraintes d'intégrité

Hermes-server peut gérer plusieurs types de données, avec des liens (clés étrangères) entre eux, et peut leur appliquer des contraintes d’intégrité.

Illustrons cela avec un cas d’utilisation typique d’utilisateurs / groupes / membres de groupes.

classDiagram
    direction BT
    GroupsMembers <-- Users
    GroupsMembers <-- Groups
    class Users{
      user_id
      ...
    }
    class Groups{
      group_id
      ...
    }
    class GroupsMembers{
      user_id
      group_id
      integrity() _SELF.user_id in Users_pkeys and _SELF.group_id in Groups_pkeys
    }

Dans ce scénario, les entrées dans GroupsMembers qui ont un user_id qui n’existe pas dans Users, ou un group_id qui n’existe pas dans Groups seront ignorées silencieusement.

Pour plus de détails, veuillez consulter integrity_constraints dans la configuration d’hermes-server.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Agrégation de données multi-sources

Dans un scénario multi-sources, Hermes peut aggréger les entrées provenant de plusieurs sources comme si elles provenaient d’une seule, et éventuellement appliquer des contraintes d’agrégation pour garantir la cohérence des données.

Prenons un cas d’utilisation, avec un ensemble de données universitaires utilisées par Hermes pour gérer les comptes utilisateurs. Les données du personnel et des étudiants sont stockées sur deux sources de données distinctes. Hermes pourra fusionner les deux sources de données dans un seul type Users virtuel, tout en s’assurant qu’il n’y ait pas de collision entre les clés primaires.

Ici, nous avons deux sources de données distinctes pour un même type de données.

classDiagram
    direction BT
    Users <|-- Users_employee
    Users <|-- Users_students
    class Users{
      user_id
      login
      mail
      merge_constraints() s.user_id mustNotExist in e.user_id
    }
    class Users_students{
      s.user_id
      s.login
      s.mail
    }
    class Users_employee{
      e.user_id
      e.login
      e.mail
    }

Dans ce scénario, les entrées dans Users_students qui ont un user_id qui existe dans Users_employee seront ignorées silencieusement. Mais les entrées dans Users_employee qui ont un user_id qui existe dans Users_students seront toujours traitées.

Pour plus de détails, veuillez consulter pkey_merge_constraint et merge_constraints dans la configuration d’hermes-server.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Fusion de données multi-sources

Dans un scénario multi-sources, Hermes peut recomposer des entrées provenant de plusieurs sources en fusionnant leurs données et en définissant éventuellement des contraintes de fusion pour assurer la cohérence des données.

Prenons un cas d’utilisation, où Hermes gère des comptes utilisateurs. Les données principales et le nom du profil wifi sont stockés sur deux sources de données distinctes. Hermes pourra agréger les deux sources de données dans un seul objet Users virtuel, tout en s’assurant que les clés primaires de la seconde source existent dans la première.

Ici, nous avons deux sources de données distinctes pour une même entrée.

classDiagram
    direction BT
    Users <|-- Users_main
    Users <|-- Users_auxiliary
    class Users{
      user_id
      login
      mail
      wifi_profile
      merge_constraints() a.user_id mustAlreadyExist in m.user_id
    }
    class Users_auxiliary{
      a.user_id
      a.wifi_profile
    }
    class Users_main{
      m.user_id
      m.login
      m.mail
    }

Dans ce scénario, les entrées dans Users_auxiliary qui ont un user_id qui n’existe pas dans Users_main seront ignorées silencieusement. Mais les entrées dans Users_main qui ont un user_id qui n’existe pas dans Users_auxiliary seront traitées, et donc l’entrée Users résultante n’aura pas de valeur wifi_profile.

Pour plus de détails, veuillez consulter pkey_merge_constraint et merge_constraints dans la configuration d’hermes-server.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Événements émis

Catégories d’événements

Un événement appartient toujours à l’une de ces catégories :

  • base: événement standard, peut être de type :

    • dataschema: propage le nouveau schéma de données aux clients, après une mise à jour du modèle de données du serveur
    • added: une nouvelle entrée a été ajoutée au type de données spécifié, avec des attributs et des valeurs spécifiés
    • removed: l’entrée de la clé primaire spécifiée a été supprimée du type de données spécifié
    • modified: l’entrée de la clé primaire spécifiée a été modifiée. Contient uniquement les attributs ajoutés, modifiés et supprimés avec leurs nouvelles valeurs
  • initsync: indique que l’événement fait partie d’une séquence initsync, peut être de type :

    • init-start: début d’une séquence initsync, contient également le schéma de données actuel
    • added: une nouvelle entrée a été ajoutée au type de données spécifié, avec les attributs et les valeurs spécifiés. Lorsque le serveur envoie le contenu de son cache pour initialiser les clients, les entrées ne peuvent qu’être ajoutées
    • init-stop: fin d’une séquence initsync

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Fichiers cache

_hermes-server.json

Contient l’état du serveur :

  • lastUpdate: datetime.datetime | None

    Date et heure de la dernière mise à jour.

  • errors: dict[str, dict[str, dict[str, Any]]]

    Dictionnaire contenant les erreurs actuelles, pour pouvoir notifier de tout changement.

  • exception: str | None

    Chaîne contenant la dernière trace d’exception.

_dataschema.json

Contient le schéma de données, construit depuis le modèle de données. Ce fichier cache permet au serveur de traiter l’étape 2. de Workflow.

DataType.json

Un fichier par type de données déclaré dans Datamodel, contenant le cache des données de ce type de données, sous forme de liste de dictionnaires. Chaque dictionnaire de la liste représente une entrée.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

hermes-client

Explications sur le fonctionnement ou la structure de certains composants clés d’hermes-client.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Sous-sections de hermes-client

Workflow

hermes-client

  • 1. charge son modèle de données à partir du fichier de configuration
  • 2. s’il existe, charge le modèle de données précédent depuis le cache
  • 3. le cas échéant, notifie les avertissements du modèle de données : type distant et attributs distants présents dans le modèle de données, mais pas dans le schéma de données
  • 4. si un schéma distant existe dans le cache, charge la file d’erreurs depuis le cache
  • 5. si le client n’a pas encore été initialisé (aucune séquence initSync complète n’a encore été traitée) :
    • 5.1. traite la séquence initSync, si une séquence initSync complète est disponible sur le bus de messages
    • 5.2. redémarre à partir de l’étape 5.
  • 6. si le client a déjà été initialisé (une séquence initSync complète a déjà été traitée) :
    • 6.1. s’il s’agit de la première itération de la boucle (l’étape 7. n’a jamais été atteinte) :
      • 6.1.1. si le modèle de données dans la configuration diffère de celui mis en cache, traite la mise à jour du modèle de données :
        • 6.1.1.1 génère les événements de suppression pour toutes les entrées des types de données supprimés, les traite et purge les fichiers de cache de ces types de données
        • 6.1.1.2 génère un différentiel entre les données mises en cache construites sur le modèle de données précédent et les mêmes données converties au nouveau modèle de données, puis génère les événements correspondants et les traite
    • 6.2. si errorQueue_retryInterval est écoulé depuis la dernière tentative, réessaye de traiter les événements présents dans la file d’erreurs
    • 6.3. si trashbin_purgeInterval est écoulé depuis la dernière tentative, purge les objets expirés de la corbeille
    • 6.4. boucle sur tous les événements disponibles sur le bus de messages et traite chacun d’eux pour appeler sa méthode de gestion des événements correspondante lorsqu’elle existe dans le plugin client
  • 7. lorsqu’au moins un événement a été traité ou si l’application a été invitée à s’arrêter :
    • 7.1. enregistre les fichiers cache de la file d’erreurs, de l’application, des données
    • 7.2. appelle la méthode de gestion de l’événement spécial onSave lorsqu’elle existe dans le plugin client
    • 7.3. notifie tout changement dans la file d’erreurs
  • 8. redémarre à partir de l’étape 5. si l’application n’a pas été invitée à s’arrêter

Si une exception est levée à l’étape 6.1.1, elle sera considérée comme une erreur fatale, notifiée et le client s’arrêtera.

Si une exception est levée aux étapes 5. à 6., elle est notifiée, son événement est ajouté à la file d’erreurs et le client redémarre à partir de l’étape 7..

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Traitement des événements

Comme le modèle de données sur le serveur diffère de celui sur le client, les clients doivent convertir les événements distants reçus sur le bus de messages en événements locaux. Si l’événement local résultant est vide (le type de données ou les attributs modifiés dans l’événement distant ne sont pas définis sur le modèle de données client), l’événement est ignoré.

Lors de la mise à jour du modèle de données client, le client peut générer des événements locaux qui n’ont pas d’événement distant correspondant, i.e. pour mettre à jour une valeur d’attribut calculée avec un modèle Jinja qui vient d’être modifié.

flowchart TB
  subgraph Hermes-client
    direction TB
    datamodelUpdate[["mise à jour du modèle de données"]]
    remoteevent["Événement distant"]
    localevent["Événement local"]
    eventHandler(["Méthode de gestion de l'événement du plugin client"])
  end
  datamodelUpdate-->|génère|localevent
  MessageBus["Bus de message"]-->|fournit|remoteevent
  remoteevent-->|convertit en|localevent
  localevent-->|passe à la bonne|eventHandler
  eventHandler-->|traite|Target["Cible"]

  classDef external fill:#fafafa,stroke-dasharray: 5 5
  class MessageBus,Target external

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Clés étrangères

Il arrive que les objets soient liés entre eux par des clés étrangères. Lorsqu’une erreur survient sur un objet dont la clé primaire fait référence à celle d’un ou plusieurs autres objets “parents”, il peut être souhaitable d’interrompre le traitement de tout ou partie des événements de ces objets parents jusqu’à ce que ce premier événement ait été correctement traité. Cela peut être réalisé en ajoutant les événements des objets parents à la file d’attente des erreurs au lieu de tenter de les traiter.

La première chose à faire est de déclarer les clés étrangères via hermes-server.datamodel.data-type-name.foreignkeys dans la configuration d’hermes-server. Le serveur ne fera rien d’autre avec ces clés étrangères que de les propager aux clients.

Ensuite, il faut définir la politique à appliquer aux clients via hermes-client.foreignkeys_policy dans chaque configuration hermes-client. Il y en a trois possibles :

  • disabled : Aucun événement, la politique est désactivée. Probablement pas pertinent dans la plupart des cas, mais pourrait peut-être être utile à quelqu’un un jour.
  • on_remove_event : Uniquement sur les événements removed. Devrait suffire dans la plupart des cas.
  • on_every_event : Sur tous les types d’événements (added, modified, removed). Pour assurer une cohérence parfaite quoi qu’il arrive.

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Auto remédiation

Parfois, un événement peut être stocké dans la file d’erreurs en raison d’un problème de données (e.g. un nom de groupe avec un point terminal génère une erreur sur Active Directory). Si le point terminal est ensuite supprimé du nom de groupe sur la source de données, l’événement modified sera stocké dans la file d’erreurs et ne sera pas traité tant que le précédent n’aura pas été traité, ce qui ne pourra jamais se produire sans procéder à une opération risquée et non-souhaitable : l’édition manuelle du fichier cache du client.

L’auto remédiation résout ce type de problèmes en fusionnant les événements d’un même objet dans la file d’erreurs. Elle n’est pas activée par défaut, car elle peut perturber l’ordre de traitement normal des événements.

Exemple

Prenons comme exemple un groupe créé avec un nom invalide. Comme son nom est invalide, le traitement de sa création échouera et l’événement sera stocké dans la file d’erreurs comme ceci :

flowchart TB
  subgraph errorqueue [File d'erreurs]
    direction TB
    ev1
  end

  ev1["`**événement 1**
    &nbsp;
    *eventtype*: added
    *objType*: ADGroup
    *objpkey*: 42
    *objattrs*: {
    &nbsp;&nbsp;grp_pkey: 42
    &nbsp;&nbsp;name: 'NomInvalide.'
    &nbsp;&nbsp;desc: 'Demo group'
    }`"]

  classDef leftalign text-align:left
  class ev1 leftalign

Comme l’erreur a été notifiée, quelqu’un corrige le nom du groupe dans la source de données. Cette modification entraîne un événement modified correspondant. Cet événement modified ne sera pas traité, mais ajouté à la file d’erreurs puisque son objet a déjà un événement dans la file d’erreurs.

  • sans auto-remédiation, tant que le premier événement n’aura pas été traité avec succès, le deuxième ne sera même pas tenté. La correction est bloquée.
  • avec l’auto-remédiation, la file d’erreurs fusionne les deux événements, puis lors du prochain traitement de la file d’erreurs, l’événement résultant sera traité avec succès.
flowchart TB
  subgraph errorqueuebis [avec auto remédiation]
    direction TB
    ev1bis
  end

  subgraph errorqueue [Sans auto remédiation]
    direction TB
    ev1
    ev2
  end

  ev1["`**événement 1**
    &nbsp;
    *eventtype*: added
    *objType*: ADGroup
    *objpkey*: 42
    *objattrs*: {
    &nbsp;&nbsp;grp_pkey: 42
    &nbsp;&nbsp;name: 'NomInvalide.'
    &nbsp;&nbsp;desc: 'Demo group'
    }`"]

  ev2["`**événement 2**
    &nbsp;
    *eventtype*: modified
    *objType*: ADGroup
    *objpkey*: 42
    *objattrs*: {
    &nbsp;&nbsp;modified: {
    &nbsp;&nbsp;&nbsp;&nbsp;name: 'NomValide'
    &nbsp;&nbsp;}
    }`"]

  ev1bis["`**événement 1**
    &nbsp;
    *eventtype*: added
    *objType*: ADGroup
    *objpkey*: 42
    *objattrs*: {
    &nbsp;&nbsp;grp_pkey: 42
    &nbsp;&nbsp;name: 'NomValide'
    &nbsp;&nbsp;desc: 'Demo group'
    }`"]

  classDef leftalign text-align:left
  class ev1,ev2,ev1bis leftalign

Boris Lechner 2025-05-05 e022507882f1c7d53ec4dc72b08922261dfdd25f

Fichiers cache

_hermes-client-name.json

Contient l’état du client :

  • queueErrors: dict[str, str]

    Dictionnaire contenant l’ensemble des messages d’erreurs des objets en file d’erreurs, pour pouvoir notifier de tout changement.

  • datamodelWarnings: dict[str, dict[str, dict[str, Any]]]

    Dictionnaire contenant les avertissements actuels du modèle de données, pour pouvoir notifier de tout changement.

  • exception: str | None

    Chaîne contenant la dernière trace d’exception.

  • initstartoffset: Any | None

    Contient l’offset du premier message de la séquence initSync sur le bus de messages.

  • initstopoffset: Any | None

    Contient l’offset du dernier message de la séquence initSync sur le bus de messages.

  • nextoffset: Any | None

    Contient l’offset du prochain message à traiter sur le bus de messages.

_hermesconfig.json

Cache de la configuration précédente, utilisé pour pouvoir construire le modèle de données précédent et pour générer les expressions Jinja avec les plugins d’attributs.

_dataschema.json

Cache du dernier schéma de données, reçu d’hermes-server.

_errorqueue.json

Cache de la file d’erreurs.

RemoteDataType.json

Un fichier par type de données distantes, contenant toutes les entrées distantes, telles qu’elles ont été traitées par le client sans générer d’erreur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que RemoteDataType_complete__.json

RemoteDataType_complete__.json

Un fichier par type de données distantes, contenant toutes les entrées distantes, telles qu’elles sont sur le serveur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que RemoteDataType.json

trashbin_RemoteDataType.json

Uniquement si la corbeille est activée. Un fichier par type de données distant, contenant toutes les entrées distantes qui se trouvent dans la corbeille, telles qu’elles ont été traitées par le client sans générer d’erreur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que trashbin_RemoteDataType_complete__.json

trashbin_RemoteDataType_complete__.json

Uniquement si la corbeille est activée. Un fichier par type de données distant, contenant toutes les entrées distantes qui se trouvent dans la corbeille, telles qu’elles sont sur le serveur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que trashbin_RemoteDataType.json

__LocalDataType.json

Un fichier par type de données local, contenant toutes les entrées locales, telles qu’elles ont été traitées par le client sans générer d’erreur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que __LocalDataType_complete__.json

__LocalDataType_complete__.json

Un fichier par type de données local, contenant toutes les entrées locales, telles qu’elles sont sur le serveur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que __LocalDataType.json

__trashbin_LocalDataType.json

Uniquement si la corbeille est activée. Un fichier par type de données local, contenant toutes les entrées locales qui se trouvent dans la corbeille, telles qu’elles ont été traitées par le client sans générer d’erreur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que __trashbin_LocalDataType_complete__.json

__trashbin_LocalDataType_complete__.json

Uniquement si la corbeille est activée. Un fichier par type de données local, contenant toutes les entrées locales qui se trouvent dans la corbeille, telles qu’elles sont sur le serveur.

Lorsque la file d’erreurs est vide, doit avoir le même contenu que __trashbin_LocalDataType.json