absinthe-graphql/dataloader

Check if record already loaded when running

Closed this issue · 1 comments

I've run into a problem where loading the same item from the same source with the same batch key, but after dataloader has already ran, causes the record to be fetched again. Example:

post(id: 1) {
  children {
    parentPost { ... }
  }
}

In the resolver for the "post" query, I load the record with dataloader instead of just using raw ecto because I want its children to be able to read it without fetching it again. When I run the above query, it runs the SELECT ... FROM posts WHERE id = ANY([1, ...]). Then it runs the query to get its children and when resolving the parentPost field, it runs the SELECT ... FROM posts WHERE id = ANY([1, ...]) query again. The example isn't great because it looks like fetching parentPost is unnecessary, but I don't actually have that field, I just need to get the parent to perform some logic on each child post.

Looking at dataloader's code, it looks like when run_batches/1 calls run_batch/2 function (not the customizablerun_batch/5), run_batch/2 never checks to see if the record has already been loaded, that check only happens in load

if fetched?(source.results, batch_key, item_key) do

Is this intended behavhior, or could this be fixed?

EDIT: Opened up the debugger and it looks like the checking in load should be enough, now I just have to figure out why fetched?/3 is returning false

Okay this one was my bad. The id that I used as the item key when I first fetched it was from the arguments on the query which resulted in a string id. The id that I was using later was from an association which gave me an integer id. I used my own IDTranslator that calls String.to_integer/1 on the id and now it works.