hermes-server

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

Boris Lechner 2025-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

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-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

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-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

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-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

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-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

É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-06-11 66f7e63e72f4bfd068a9d867f89952da021fefd6

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.