Docs
La Recherche⌘ K
  • Accueil
  • À propos de The Graph
  • Réseaux pris en charge
  • Contrats du Protocole
  • Subgraphs
    • Substreams
      • Token API
        • AI Suite
          • Indexing
            • Resources
              Subgraphs > Querying

              5 minutes

              Systèmes distribués

              Le graph est un protocole mis en œuvre sous la forme d’un système distribué.

              Les connexions échouent. Les demandes arrivent dans le désordre. Différents ordinateurs dont les horloges et les états ne sont pas synchronisés traitent les demandes correspondantes. Les serveurs redémarrent. Des réorgs se produisent entre les demandes. Ces problèmes sont inhérents à tous les systèmes distribués, mais ils sont exacerbés dans les systèmes fonctionnant à l’échelle mondiale.

              Considérez cet exemple de ce qui peut se produire si un client interroge un indexeur pour connaître les dernières données lors d’une réorganisation.

              1. L’indexeur ingère le bloc 8
              2. Demande transmise au client pour le bloc 8
              3. L’indexeur ingère le bloc 9
              4. L’indexeur ingère le bloc 10A
              5. Demande transmise au client pour le bloc 10A
              6. L’indexeur détecte la réorganisation à 10B et annule 10A
              7. Demande transmise au client pour le bloc 9
              8. L’indexeur ingère le bloc 10B
              9. L’indexeur ingère le bloc 11
              10. Demande transmise au client pour le bloc 11

              Du point de vue de l’indexeur, les choses progressent logiquement. Le temps avance, bien que nous ayons dû revenir en arrière sur un bloc oncle et faire avancer le bloc faisant l’objet d’un consensus par-dessus. En cours de route, l’indexeur répond aux demandes en utilisant le dernier état dont il a connaissance à ce moment-là.

              Mais du point de vue du client, les choses semblent chaotiques. Le client observe que les réponses concernaient les blocs 8, 10, 9 et 11 dans cet ordre. Nous appelons cela le problème de « l’oscillation du bloc ». Lorsqu’un client subit une oscillation de blocage, les données peuvent sembler se contredire au fil du temps. La situation s’aggrave lorsque l’on considère que les indexeurs n’ingèrent pas tous les derniers blocs simultanément et que vos requêtes peuvent être acheminées vers plusieurs indexeurs.

              Il est de la responsabilité du client et du serveur de travailler ensemble pour fournir des données cohérentes à l’utilisateur. Différentes approches doivent être utilisées en fonction de la cohérence souhaitée, car il n’existe pas de programme adapté à chaque problème.

              Il est difficile de raisonner sur les implications des systèmes distribués, mais la solution ne l’est pas nécessairement ! Nous avons établi des API et des modèles pour vous aider à naviguer dans certains cas d’utilisation courants. Les exemples suivants illustrent ces modèles tout en éludant les détails requis par le code de production (comme la gestion des erreurs et l’annulation) afin de ne pas obscurcir les idées principales.

              Demande de données actualisées

              The Graph fournit l’API block: { number_gte: $minBlock } qui assure que la réponse est pour un seul bloc égal ou supérieur à $minBlock. Si la requête est faite à une instance de graph-node et que le bloc min n’est pas encore synchronisé, graph-node retournera une erreur. Si graph-node a synchronisé le bloc min, il exécutera la réponse pour le dernier bloc. Si la requête est faite à une passerelle Edge & Node, la passerelle filtrera tous les Indexeurs qui n’ont pas encore synchronisé le bloc min et fera la requête pour le dernier bloc que l’Indexeur a synchronisé.

              Nous pouvons utiliser number_gte pour nous assurer que le temps ne recule jamais lors de l’interrogation des données dans une boucle. Voici un exemple :

              1/// Met à jour la variable protocol.paused avec la dernière valeur2/// connue dans une boucle en la récupérant à l'aide de The Graph.3async function updateProtocolPaused() {4  // Il n'y a pas de problème à commencer avec minBlock à 0. La requête sera servie5  // en utilisant le dernier bloc disponible. Définir minBlock à 06  // revient à ne pas utiliser cet argument.7  let minBlock = 089  for (;;) {10    // Programmer une promesse qui sera prête une fois que11    // le prochain bloc Ethereum sera probablement disponible.12    const nextBlock = new Promise((f) => {13      setTimeout(f, 14000)14    })1516    const query = `17        query GetProtocol($minBlock: Int!) {18            protocol(block: { number_gte: $minBlock }  id: "0") {19              paused20            }21            _meta {22                block {23                    number24                }25            }26        }`2728    const variables = { minBlock }29    const response = await graphql(query, variables)30    minBlock = response._meta.block.number3132    // TODO : Faire quelque chose avec les données de réponse ici au lieu de les enregistrer.33    console.log(response.protocol.paused)3435    // Dormir pour attendre le bloc suivant36    await nextBlock37  }38}

              Récupérer un ensemble d’éléments liés

              Un autre cas d’utilisation est la récupération d’un grand ensemble ou, plus généralement, la récupération d’éléments liés entre plusieurs requêtes. Contrairement au cas des sondages (où la cohérence souhaitée était d’avancer dans le temps), la cohérence souhaitée est pour un seul point dans le temps.

              Ici, nous utiliserons la méthode block: { hash: $blockHash } afin de rattacher tous nos résultats au même bloc.

              1/// Obtient une liste de noms de domaine à partir d'un seul bloc en utilisant la pagination2async function getDomainNames() {3  // Fixer un plafond pour le nombre maximum d'articles à retirer.4  let pages = 55  const perPage = 100067  // La première requête obtiendra la première page de résultats ainsi que le bloc8  // afin que les autres requêtes soient cohérentes avec la première.9  const listDomainsQuery = `10    query ListDomains($perPage: Int!) {11        domains(first: $perPage) {12            name13            id14        }15        _meta {16            block {17                hash18            }19        }20    }`2122  let data = await graphql(listDomainsQuery, { perPage })23  let result = data.domains.map((d) => d.name)24  let blockHash = data._meta.block.hash2526  let query27  // Continuer à rechercher des pages supplémentaires jusqu'à ce que nous atteignions la limite de28  // 5 pages au total (spécifiée ci-dessus) ou jusqu'à ce que nous sachions que nous avons atteint la dernière page29  // parce que la page contient moins d'entités qu'une page complète.30  while (data.domains.length == perPage && --pages) {31    let lastID = data.domains[data.domains.length - 1].id32    query = `33        query ListDomains($perPage: Int!, $lastID: ID!, $blockHash: Bytes!) {34            domains(first: $perPage, where: { id_gt: $lastID }, block: { hash: $blockHash }) {35                name36                id37            }38        }`3940    data = await graphql(query, { perPage, lastID, blockHash })4142    // Accumuler les noms de domaine dans le résultat43    for (domain of data.domains) {44      result.push(domain.name)45    }46  }47  return result48}

              Il convient de noter qu’en cas de réorganisation, le client devra réessayer à partir de la première demande de mise à jour du hachage du bloc vers un bloc qui n’a pas été supprimé.

              ⁠Edit on GitHub⁠

              Interroger à partir d'une applicationAPI GraphQL
              On this page
              • Demande de données actualisées
              • Récupérer un ensemble d’éléments liés
              The GraphStatusTestnetActifs de la MarqueForumSécuritéPolitique de confidentialitéConditions d'utilisation