Message originally sent by slack user U783MOJYF8Z
We have a query layer implementation that analyzes the query upfront and generates a pseudo-optimal set of database queries (one per component) but it’s pretty unwieldy right now
Message originally sent by slack user U783MOJYF8Z
We have a query layer implementation that analyzes the query upfront and generates a pseudo-optimal set of database queries (one per component) but it’s pretty unwieldy right now
Message originally sent by slack user U783MOJYF8Z
TBD, currently nobody at Shopify is working on this.
Message originally sent by slack user U783UION177
So we’ve been using this gem: https://github.com/exAspArk/batch-loader
Message originally sent by slack user U783UION177
Here’s an example from the readme:
def load_user(post)
BatchLoader.for(post.user_id).batch do |user_ids, loader|
User.where(id: user_ids).each { |user| loader.call(user.id, user) }
end
end
Message originally sent by slack user U783MOJYF8Z
yeah, I think that’s approximately the same
Message originally sent by slack user U783UION177
So in your example, we might do something like:
class TireQuery
def by_car(car_id)
BatchLoader.for(car_id).batch do |car_ids, loader|
Tire.where(car_id: car_ids).each { |tire| loader.call(tire.id, tire) }
end
end
end
Message originally sent by slack user U783MOJYF8Z
Message originally sent by slack user U783UION177
so the caller of TireQuery doesn’t need to know about batch loading
Message originally sent by slack user U783MOJYF8Z
thank you for sharing
Message originally sent by slack user U783MOJYF8Z
It’s interesting, I think our batchloader implementation is too caught up in graphQL
Message originally sent by slack user U783UION177
So I lifted this idea from Dan Schafer’s talk here:
https://www.youtube.com/watch?v=etax3aEe2dA
Message originally sent by slack user U783UION177
it’s an interesting idea to think of batch loading as a solution to n+1s independently of GQL
Message originally sent by slack user U783MOJYF8Z
How do you handle pagination in that case? Is there an abstraction for that or do you need to manually implement on every query that can be paginated?
Message originally sent by slack user U783UION177
Currently it’s implemented on every query individually. But it’s on the list.
Message originally sent by slack user U783UION177
Not every query, but those that need it I should say.
Message originally sent by slack user U783UION177
So in your example, CarsQuery would need it, TiresQuery would not.
Message originally sent by slack user U783MOJYF8Z
assuming the number of tires per car is bounded
Message originally sent by slack user U783UION177
true
Message originally sent by slack user U783MOJYF8Z
I’ll think about generalizing our batch loaders so they can be separated from the graphql layer. It’s an interesting approach.
Message originally sent by slack user U783UION177
Let me know how it goes! Still early days for us with this architecture, so I’ll report back any trouble we run into.