faustjs icon indicating copy to clipboard operation
faustjs copied to clipboard

Bug: Infinite looping GraphQL requests with usePage and useQuery

Open mediashane opened this issue 3 years ago • 15 comments

When navigating between pages that retrieve data using usePage and useQuery the request cache appears to not totally empty between queries, resulting in the new query containing elements from the previous query - in particular it appears that data accessed/mapped through $on seem to be sticky.

If the page being navigated to doesn't contain the 'sticky' data from the previous query, the GraphQL query loops over and over again, preventing the response of all the data that does belong on the new page. If the new page does contain a matching component that consumes the same data, the cached data from the previous old query is injected.

If a page is navigated to directly, either by using instead of a Next link, or by entering the URL directly, or by reloading the page, the looping request bug is not encountered.

Applicable Versions

  • @faustjs/core version: "^0.14.1"
  • @faustjs/react version: NA
  • @faustjs/next version: "^0.14.0"
  • WordPress version: 5.8.1

Steps To Reproduce

  1. Visit https://elizabeth-eakins-2021-koalition.vercel.app/ and open the Network tab
  2. Navigate to 'Our Story' route via the header menu (page loads normally)
  3. Navigate to 'Rugs' route via the header menu, and observe the Network tab to see looping GraphQL requests that ask for component data that belong to the previous request (in this particular example, a component named Page_Pagebuilder_Modules_HeroLeftJustified that belongs on the 'Our Story' page, but is not on the 'Rugs' page)
  4. Note that the looping request also prevents the proper retrieval of the data that belongs in the current query (in this example, the Hero image on the 'Rugs' page is not properly retrieved).

Link to code example: usePage() or useQuery().page({ id: '/', idType: PageIdType.URI, })

The current behavior

New GraphQL requests loop infinitely when it contains stale data from the previous query request

The expected behavior

New GraphQL requests do not contain stale data from the previous query, and returns data from just the current query

mediashane avatar Jan 01 '22 01:01 mediashane

Hello @mediashane Happy new year. I was able to replicate the above issue using the steps to reproduce only the first time I visited the link you mentioned. Subsequently though, everything loaded fine at least for the time being even when I cleared the browser cache or when I used a different browser.

My hypothesis is that this is somehow related to Vercel but I'm not sure. I will try to visit the page again today to see if I can replicate again.

theodesp avatar Jan 04 '22 10:01 theodesp

Hi @theodesp ! Thanks for jumping in. I tried again today to replicate the above issue following the steps described and was able to successfully replicate on Chrome and Firefox with Windows 10 (though my colleagues using MacOS report similar results). Something else to note is that we also encounter the same issue when working locally, for example with npm run build + npm run start, which may or may not eliminate Vercel from being the culprit. Here are some screenshots that may help diagnose the problem, and please let me know if there is any other information I can provide to help us sleuth a resolution:

Chrome chromeLoop

Firefox fireFoxLoop

Thank you!

mediashane avatar Jan 05 '22 01:01 mediashane

Hello @mediashane I can verify the issue as follows:

  1. When I visit the Our story page the first time I can inspect the GraphQL request which loads correctly:
{"query":"query($id1:ID!$idType2:PageIdType$id3:ID!$idType4:RugIdType){page0:page(id:$id1 idType:$idType2){__typename id pageBuilder{__typename modules{__typename ...on Page_Pagebuilder_Modules_HeroRightJustified{textSubline textHeadline textMediaLabel textColor mediaIcon{__typename id mediaItemUrl}image{__typename id mediaItemUrl}}...on Page_Pagebuilder_Modules_TwoColumnContent{flexDirection includeParagraph alt textHeadline textParagraph backgroundColor headlineColor paragraphColor image{__typename id mediaItemUrl}}...on Page_Pagebuilder_Modules_OneColumnContent{includeParagraph textHeadline textParagraph textColor image{__typename id mediaItemUrl}}}}}rug0:rug(id:$id3 idType:$idType4){__typename rug{__typename modules{__typename collection{__typename ...on Rug_collection{id rug_collection{__typename title}}}}}id}}","variables":{"id1":"our-story","idType2":"URI","id3":"/our-story","idType4":"URI"}}
  1. I Navigate to 'Rugs' route via the header menu and I observe the looping request with the following GraphQL request:
{"query":"query($id1:ID!$idType2:PageIdType){page0:page(id:$id1 idType:$idType2){__typename pageBuilder{__typename modules{__typename ...on Page_Pagebuilder_Modules_HeroLeftJustified{media{__typename id mediaItemUrl}}}}id}}","variables":{"id1":"rugs","idType2":"URI"}}

and the response from the server each time is:

{"data":{"page0":{"__typename":"Page","pageBuilder":{"__typename":"Page_Pagebuilder","modules":[{"__typename":"Page_Pagebuilder_Modules_HeroCenterButton"},{"__typename":"Page_Pagebuilder_Modules_CenteredText"},{"__typename":"Page_Pagebuilder_Modules_CardList"}]},"id":"cG9zdDoxMQ=="}},"extensions":{"debug":[{"type":"DEBUG_LOGS_INACTIVE","message":"GraphQL Debug logging is not active. To see debug logs, GRAPHQL_DEBUG must be enabled."}]}}
  1. I reload the page and now whenever I follow the same flow( following the same steps as before I can see the page loads correctly). I can see the following GraphQL request:
{"query":"query($first1:Int$where2:RootQueryToMenuItemConnectionWhereArgs$id3:ID!$idType4:PageIdType$id5:ID!$idType6:RugIdType){menuItems0:menuItems(first:$first1 where:$where2){__typename nodes{__typename id label}}page0:page(id:$id3 idType:$idType4){__typename id pageBuilder{__typename modules{__typename ...on Page_Pagebuilder_Modules_HeroCenterButton{textOverline textHeadline buttonLabel textColor hoverTextColor media{__typename id mediaItemUrl}}...on Page_Pagebuilder_Modules_CenteredText{backgroundColor textColor textSize fontFamily cta{__typename ...on Cta{id ctaText{__typename cta}}}}...on Page_Pagebuilder_Modules_CardList{mobileSizeWide cards{__typename title description stickerText showSticker image{__typename id mediaItemUrl}link{__typename url target}}}}}}rug0:rug(id:$id5 idType:$idType6){__typename rug{__typename modules{__typename collection{__typename ...on Rug_collection{id rug_collection{__typename title}}}}}id}}","variables":{"first1":100,"where2":{"location":"PRIMARY"},"id3":"rugs","idType4":"URI","id5":"/rugs","idType6":"URI"}}

Not sure exactly why the loop is happening though AFIK the retry operations are used only in useTransactionQuery hook.

I will log a bug in our internal process tracker to investigate further. I will post any updates in this thread.

In the meantime would you be able to provide a sample React query for the two pages? For example the query of the OurStory page that triggers the Page_Pagebuilder_Modules_HeroLeftJustified and the query of the Rugs page that shows the use data accessed/mapped through $on?

Thank you in advance.

theodesp avatar Jan 05 '22 11:01 theodesp

Hi @theodesp , sure thing! We're using Next.js, so we use two basic hooks for retrieving page data.

For pages generated using [...pageUri].tsx we use the following:

const { usePage } = client;
const page = usePage();

For index.tsx we use:

const pageData = useQuery().page({
    id: '/',
    idType: PageIdType.URI,
  });

We then then access the page's attached Advanced Custom Fields modules like so: page?.pageBuilder?.modules. Within those modules we access basic component data like so: const { cards, labelColor, textColor, textLinkLabel, textLinkUrl, sectionLabel } = Page_Pagebuilder_Modules_HeroLeftJustified;

If the component data was added via WordPress admin using ACF's Flexible or Repeater content types, we access the data using $on, like so: Page_Pagebuilder_Modules_TwoColumnGallery?.rugAttributes?.$on?.Rug_attribute?.rugAttribute?.textHeadline.

In circumstances that ACF Flexible or Repeater component data is delivered in an array, we sometimes access specific entries in that array like so: Page_Pagebuilder_Modules_ThreeImageButtons.featureCards[0]?.$on?.Feature?.features?.image?.mediaItemUrl.

Under the hood, the GraphQL queries themselves are generated using npm run generate, created by GQty. Here is the query for Page_Pagebuilder_Modules_HeroLeftJustified:

Page_Pagebuilder_Modules_HeroLeftJustified: {
    __typename: { __type: 'String!' },
    fieldGroupName: { __type: 'String' },
    media: { __type: 'MediaItem' },
    textColor: { __type: 'String' },
    textHeadline: { __type: 'String' },
    textOverline: { __type: 'String' },
    textParagraph: { __type: 'String' },
  },

Navigation between pages is generally done using the basic next/link.

The plugins we use to make all this work are: FaustWP, WP GraphQL, Advanced Custom Fields PRO and WPGraphQL for Advanced Custom Fields.

Hope this helps! Let me know if there's any other data I can provide that would help us solve the issue. Thanks!

mediashane avatar Jan 07 '22 21:01 mediashane

Hi @theodesp , it looks like this was fixed downstream: https://github.com/gqty-dev/gqty/issues/520

If we're using Faust, what would your recommendation be for getting this fix into our project? Will we have to wait for another release cycle for Faust? Thank you!

mediashane avatar Jan 17 '22 02:01 mediashane

Hi @theodesp , it looks like this was fixed downstream: gqty-dev/gqty#520

If we're using Faust, what would your recommendation be for getting this fix into our project? Will we have to wait for another release cycle for Faust? Thank you!

that issue was not related with gqty, it was with https://github.com/supabase/pg_graphql, which doesn't seem to do anything with faustjs. no change was applied to gqty to fix that issue


I tried following the reproduction steps of this issue navigating to https://elizabeth-eakins-2021-koalition.vercel.app/ and the looping doesn't happen

PabloSzx avatar Jan 17 '22 17:01 PabloSzx

Steps to reproduce it in Vercel (staging)

1- Enter in https://elizabeth-eakins-2021-koalition.vercel.app/ 2- click “our story” 3- Click “Rugs” 4- Click “From the farm” See the LOOP in dev tools

aitoraznar avatar Jan 17 '22 17:01 aitoraznar

Steps to reproduce it in Vercel (staging)

1- Enter in https://elizabeth-eakins-2021-koalition.vercel.app/ 2- click “our story” 3- Click “Rugs” 4- Click “From the farm” See the LOOP in dev tools

is it possible to create a local development environment reproducing the issue? that way I can actually debug

PabloSzx avatar Jan 17 '22 17:01 PabloSzx

Yeah, It couldn't be possible to make it this week. But we'll definitely do it for the next week. Many thanks. Gracias.

aitoraznar avatar Jan 18 '22 07:01 aitoraznar

Hi @PabloSzx ! We've set up a Github repo and Vercel deploy that reproduces the bug. I'll also attach a video that shows steps to repro and the bug itself in action.

Github repo: https://github.com/mediashane/graphql-bug After cloning, create a .env file in the base directory of the project and copy + save the contents of .env.local.sample into it. This will configure your local development environment to point towards the live WordPress backend. Then just npm install, npm run build and npm run start.

Here is a Vercel deploy of the repo linked above, where you can jump straight to reproducing the bug without cloning the repo: https://graphql-bug.vercel.app

Steps to reproduce it in Vercel (staging):

  1. Navigate to https://graphql-bug.vercel.app,
  2. Open Network Dev Tools tab
  3. Click “Our Story”
  4. Click “Rugs”
  5. Click “From the Farm”

If you don't see the looping GraphQL requests the first time, return to the home page, do a cache clearing reload and follow the sequence again. There are other occasions that this looping starts, but this is a sequence that we've found reproduces the bug consistently.

We're using the plugin WP GraphQL to expose our WordPress data, and Faust + GQty to do our queries and generate our schema locally. We think this issue is closely related to the issue you encountered and solved here: https://github.com/gqty-dev/gqty/issues/520

Here is the video: https://user-images.githubusercontent.com/14046192/150017319-3c419d6a-5484-4129-b8bf-49802477b033.mp4

Thank you in advance for all of your work, and let us know if there's anything else we can do to help!

mediashane avatar Jan 18 '22 21:01 mediashane

Hello @mediashane I was also trying to clone the repo and try it locally. Unfortunately the local dev setup fails with a GraphQL Error during pre-rendering:

[GQtyError: Internal server error] {
  graphQLErrors: [ { message: 'Internal server error', extensions: [Object] } ]
}
[   =] info  - Generating static pages (15/22)[GQtyError: Cannot query field "paragraphText" on type "Page_Pagebuilder_Modules_CenteredText".] {
  graphQLErrors: [
    {
      message: 'Cannot query field "paragraphText" on type "Page_Pagebuilder_Modules_CenteredText".',
      extensions: [Object],
      locations: [Array]
    }
  ]
}

Is it possible to get an updated ACF export of the models as I could try to test it locally with a vanilla Wordpress install by importing the ACF models?

theodesp avatar Jan 24 '22 12:01 theodesp

Hello @mediashane I was also trying to clone the repo and try it locally. Unfortunately the local dev setup fails with a GraphQL Error during pre-rendering:

[GQtyError: Internal server error] {
  graphQLErrors: [ { message: 'Internal server error', extensions: [Object] } ]
}
[   =] info  - Generating static pages (15/22)[GQtyError: Cannot query field "paragraphText" on type "Page_Pagebuilder_Modules_CenteredText".] {
  graphQLErrors: [
    {
      message: 'Cannot query field "paragraphText" on type "Page_Pagebuilder_Modules_CenteredText".',
      extensions: [Object],
      locations: [Array]
    }
  ]
}

Is it possible to get an updated ACF export of the models as I could try to test it locally with a vanilla Wordpress install by importing the ACF models?

Executing npm run generate you should have an updated Typescript schema.

aitoraznar avatar Jan 24 '22 12:01 aitoraznar

Hi @theodesp I just deployed an updated schema as well, so that should fix the error you're getting, but @aitoraznar 's suggestion will also work. We're actively building out a site using this backend, so the schema is changing frequently as we progress. Thank you!

mediashane avatar Jan 24 '22 23:01 mediashane

Looks like a lot of progress is being made here as well: https://github.com/gqty-dev/gqty/issues/558

mediashane avatar Jan 24 '22 23:01 mediashane

@mediashane we are currently investigating the issue and documenting the steps in https://github.com/gqty-dev/gqty/issues/558

theodesp avatar Jan 25 '22 09:01 theodesp

Hey @mediashane. We have a new version of Faust that does not use GQty. Maybe you can port some of your code to check it out. This should not create those issues.

theodesp avatar Oct 20 '22 12:10 theodesp

Closing this since it's a non-issue in the latest version of Faust.

Guidance on how to migrate

josephfusco avatar Jan 05 '23 17:01 josephfusco