Docs
Sök⌘ K
  • Home
  • Om The Graph
  • Nätverk som stöds
  • Protocol Contracts
  • Subgrafer
    • Underströmmar
      • Token API
        • AI Suite
          • Indexing
            • Resources
              Subgrafer > Querying

              5 minutes

              Distribuerade System

              The Graph är ett protokoll implementerat som ett distribuerat system.

              Anslutningar misslyckas. Förfrågningar anländer i fel ordning. Olika datorer med osynkroniserade klockor och tillstånd bearbetar relaterade förfrågningar. Servrar startar om. Omorganiseringar inträffar mellan förfrågningar. Dessa problem är inneboende för alla distribuerade system men förvärras i system som opererar globalt.

              Betrakta detta exempel på vad som kan inträffa om en klient undersöker en Indexer för den senaste datan under en omorganiseringar.

              1. Indexer bearbetar block 8
              2. Förfrågan serveras till klienten för block 8
              3. Indexer bearbetar block 9
              4. Indexer bearbetar block 10A
              5. Förfrågan serveras till klienten för block 10A
              6. Indexer upptäcker omorganiseringar till 10B och rullar tillbaka 10A
              7. Förfrågan serveras till klienten för block 9
              8. Indexer bearbetar block 10B
              9. Indexer bearbetar block 11
              10. Förfrågan serveras till klienten för block 11

              Ur Indexerns synvinkel fortskrider saker logiskt framåt. Tiden går framåt, även om vi var tvungna att rulla tillbaka ett uncle-block och spela in blocket under konsensus framåt ovanpå det. Under vägen serverar Indexern förfrågningar med den senaste informationen den känner till vid den tiden.

              Ur klientens synvinkel verkar dock saker kaotiska. Klienten observerar att svaren var för block 8, 10, 9 och 11 i den ordningen. Vi kallar detta “block wobble”-problemet. När en klient upplever block wobble kan data verka motsäga sig över tiden. Situationen förvärras när vi tänker på att Indexers inte alla bearbetar de senaste blocken samtidigt, och dina förfrågningar kan routas till flera Indexers.

              Det är klientens och serverns ansvar att samarbeta för att ge användaren konsekvent data. Olika metoder måste användas beroende på önskad konsekvens, eftersom det inte finns ett rätt program för varje problem.

              Att resonera kring följderna av distribuerade system är svårt, men lösningen behöver inte vara det! Vi har etablerat API:er och mönster för att hjälpa dig hantera några vanliga användningsfall. Följande exempel illustrerar dessa mönster, men utesluter fortfarande detaljer som krävs av produktionskod (som felhantering och avbokning) för att inte försvåra huvudidéerna.

              Polla efter uppdaterad data

              The Graph provides the block: { number_gte: $minBlock } API, which ensures that the response is for a single block equal or higher to $minBlock. If the request is made to a graph-node instance and the min block is not yet synced, graph-node will return an error. If graph-node has synced min block, it will run the response for the latest block. If the request is made to an Edge & Node Gateway, the Gateway will filter out any Indexers that have not yet synced min block and make the request for the latest block the Indexer has synced.

              We can use number_gte to ensure that time never travels backward when polling for data in a loop. Here is an example:

              1/// Updates the protocol.paused variable to the latest2/// known value in a loop by fetching it using The Graph.3async function updateProtocolPaused() {4  // It's ok to start with minBlock at 0. The query will be served5  // using the latest block available. Setting minBlock to 0 is the6  // same as leaving out that argument.7  let minBlock = 089  for (;;) {10    // Schedule a promise that will be ready once11    // the next Ethereum block will likely be available.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: Do something with the response data here instead of logging it.33    console.log(response.protocol.paused)3435    // Sleep to wait for the next block36    await nextBlock37  }38}

              Hämta en uppsättning relaterade objekt

              Ett annat användningsfall är att hämta en stor uppsättning eller mer generellt att hämta relaterade objekt över flera förfrågningar. Till skillnad från fallet med att hämta uppdaterade data (där önskad konsekvens var att gå framåt i tiden), är önskad konsekvens här att få data från en enda tidpunkt.

              Here we will use the block: { hash: $blockHash } argument to pin all of our results to the same block.

              1/// Gets a list of domain names from a single block using pagination2async function getDomainNames() {3  // Set a cap on the maximum number of items to pull.4  let pages = 55  const perPage = 100067  // The first query will get the first page of results and also get the block8  // hash so that the remainder of the queries are consistent with the first.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  // Continue fetching additional pages until either we run into the limit of28  // 5 pages total (specified above) or we know we have reached the last page29  // because the page has fewer entities than a full page.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    // Accumulate domain names into the result43    for (domain of data.domains) {44      result.push(domain.name)45    }46  }47  return result48}

              Observera att i händelse av en omorganisation måste klienten försöka igen från den första begäran för att uppdatera blockhashen till ett icke-farbrorblock.

              ⁠Edit on GitHub⁠

              Querying from an AppGraphQL API
              On this page
              • Polla efter uppdaterad data
              • Hämta en uppsättning relaterade objekt
              The GraphStatusTestnetBrand AssetsForumSecurityPrivacy PolicyTerms of Service