Repository: mercurius-js/mercurius
Pull request #719 (2022-02-03 16:38:28)

Fixes issue with batchedQueries overriding loader
When using `allowBatchedQueries` the loader would get overwritten for each query being processed
which would ultimately prevent the loaders being reuses for the whole batch.

The fix is pretty native, and only overwrittes the reply's loader if not provided if in allowBatchedQueries mode.

The behaviour for non `allowBatchedQueries` should be preserved.


flovilmart: 🎉 

Patch:
diff --git a/index.js b/index.js
index 56c17f9..1500d38 100644
--- a/index.js
+++ b/index.js
@@ -305,7 +305,9 @@ const plugin = fp(async function (app, opts) {
 
     context = Object.assign(context, { reply: this, app })
     if (app[kFactory]) {
-      this[kLoaders] = app[kFactory].create(context)
+      if (!opts.allowBatchedQueries || !this[kLoaders]) {
+        this[kLoaders] = app[kFactory].create(context)
+      }
     }
 
     return app.graphql(source, context, variables, operationName)


Test patch:
diff --git a/test/loaders.js b/test/loaders.js
index 530ac11..6cac9cf 100644
--- a/test/loaders.js
+++ b/test/loaders.js
@@ -40,6 +40,8 @@ const schema = `
 
   type Query {
     dogs: [Dog]
+    puppies: [Dog]
+    elders: [Dog]
   }
 
   type Subscription {
@@ -51,6 +53,12 @@ const resolvers = {
   Query: {
     dogs (_, params, { reply }) {
       return dogs
+    },
+    puppies (_, params, { reply }) {
+      return [dogs[0]]
+    },
+    elders (_, params, { reply }) {
+      return dogs.slice(2, dogs.length)
     }
   }
 }
@@ -64,6 +72,24 @@ const query = `{
   }
 }`
 
+const puppiesQuery = `{
+  puppies {
+    name,
+    owner {
+      name
+    }
+  }
+}`
+
+const eldersQuery = `{
+  elders {
+    name,
+    owner {
+      name
+    }
+  }
+}`
+
 test('loaders create batching resolvers', async (t) => {
   const app = Fastify()
 
@@ -136,6 +162,71 @@ test('loaders create batching resolvers', async (t) => {
   })
 })
 
+test('loaders create batching resolvers with batchedQueries', async (t) => {
+  const app = Fastify()
+
+  const loaders = {
+    Dog: {
+      async owner (queries, { reply }) {
+        // note that the second entry for max is cached
+        t.same(queries, [{
+          obj: {
+            name: 'Max'
+          },
+          params: {}
+        }, {
+          obj: {
+            name: 'Buddy'
+          },
+          params: {}
+        }])
+        return queries.map(({ obj }) => {
+          return { ...owners[obj.name] }
+        })
+      }
+    }
+  }
+
+  app.register(GQL, {
+    schema,
+    resolvers,
+    loaders,
+    allowBatchedQueries: true
+  })
+
+  const res = await app.inject({
+    method: 'POST',
+    url: '/graphql',
+    body: [{ query: puppiesQuery }, { query: eldersQuery }]
+  })
+
+  t.equal(res.statusCode, 200)
+  t.same(JSON.parse(res.body), [{
+    data: {
+      puppies: [{
+        name: 'Max',
+        owner: {
+          name: 'Jennifer'
+        }
+      }]
+    }
+  }, {
+    data: {
+      elders: [{
+        name: 'Buddy',
+        owner: {
+          name: 'Tracy'
+        }
+      }, {
+        name: 'Max',
+        owner: {
+          name: 'Jennifer'
+        }
+      }]
+    }
+  }])
+})
+
 test('disable cache for each loader', async (t) => {
   const app = Fastify()