Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect: nested batch resolvers #121

Closed
pablodip opened this issue Aug 29, 2019 · 3 comments
Closed

Connect: nested batch resolvers #121

pablodip opened this issue Aug 29, 2019 · 3 comments

Comments

@pablodip
Copy link

Hello there!

We are trying out Pathom to see if we can use it at the company, and one of our main concerns right now is that we can't get to work nested batch resolvers with Connect.

Here you go an example in code:

(def users
  {::pc/sym     `users
   ::pc/output  [{:users [:user-id]}]
   ::pc/resolve (fn [env input]
                  {:users [{:user-id 3}
                           {:user-id 10}
                           {:user-id 18}]})})
(def user-resolver
  (pc/resolver
    `user-resolver
    {::pc/input     #{:user-id}
     ::pc/output    [:user-name {:user-groups [:group-id]}]
     ::pc/transform pc/transform-batch-resolver}
    (fn [env input]
      (->> input
           (mapv (fn [i]
                   {:user-name   (str "user" (:user-id i))
                    :user-groups (->> (range 3)
                                      (mapv (fn [_]
                                              {:group-id (rand-int 1000)})))}))))))

(def group-resolver
  (pc/resolver
    `group-resolver
    {::pc/input     #{:group-id}
     ::pc/output    [:group-name]
     ::pc/transform pc/transform-batch-resolver}
    (fn [env input]
      (->> input
           (mapv (fn [i]
                   {:group-name (str "group" (:group-id i))}))))))

If you perform the query [{:users [:user-name {:user-groups [:group-name]}]}])), user-resolver is called once (batched), but group-resolver is called three times (not batched even if the resolver allows batching).

Is there any way to configure Connect to handle those nested batch resolvers?

And if not, are there any plans to support that? We are quite worried about the number of queries to the database if resolvers cannot be batched nestedly.

Thanks a lot! :)

@wilkerlucio
Copy link
Owner

wilkerlucio commented Aug 29, 2019

Hello, so, nested batching is not something supported directly via Pathom, the reason is that pathom process queries piece by piece, and while processing list items it can do it in parallel (if using parallel parser). This makes quite tricky to implement a generic solution to handle that, I have some ideas but they are way ahead, I wouldn't count with Pathom to solve this.

With that said, please check how many times will actually occur to you, IME nested batches are quite rare (but of course that can change a lot from user to user). Currently, it is doing the batch on the second layer, but once for each item (so the blast radius still better than not having a batch on the second).

Another thing you can do is write manual optimizations for specific scenarios, you can create a resolver for that "optimized name", then you compute the things using manual optimal algorithm, and in the end, you add the metadata ::p/final true, so Pathom will not try to follow up on the processing. If you reach a point like this, I'll be happy to help you figure out how to use some pathom internals to help with the manual processing.

Makes sense?

@pablodip
Copy link
Author

the reason is that pathom process queries piece by piece, and while processing list items it can do it in parallel (if using parallel parser)

Is there any way to configure how the parallel parser parallelises? I think that it parallelises by default per property/individual item, but it could also parallelise per query or list of items. Could that make it simpler to find a generic solution to nested batching? A very common case I guess is to access the database in the resolvers, so this type of parallelisation could be great to optimise for that.

IME nested batches are quite rare (but of course that can change a lot from user to user)

I guess that if we aim to open an API with possible joins and nesting it would be great if we could do it efficiently. Otherwise the API (and the apps using it) might suffer depending on the amount of data or the kind of usage. Pathom (and EQL) is a very open system: you can do a lot of types of queries, and with a lot of nesting; in the end similar to a database, where not every query is efficient. But in and API I guess that efficiency should be taken into account, since it is a public thing. How should the design of an API in Pathom be efficient? For example if we leave inefficient nested batching in an API, it might suffer if we return a lot of results in a resolver or the user performs deep nestings. How should that be avoided while keeping an open API? Limiting the level of nesting in a parser or any other way?

The example I showed you has just one join: users > groups. How would you do that example so that it doesn't need nested batching?

Another thing you can do is write manual optimizations for specific scenarios

Yeah, I have been able to solve nested batching for our models. However, it is a bit hacky, since all the nested processing happens in the same resolver, so a lot of the power of Connect is lost I guess. At least it now supports any level of nested batching in models, but not sure how it may affect Pathom, Connect or composability with other resolvers.

you add the metadata ::p/final true, so Pathom will not try to follow up on the processing

I didn't need to use this in the end, since everything queried is returned, just in the same resolver. Let's hope that is okay. :)

@wilkerlucio
Copy link
Owner

Yeah, that's just a hard problem, there is no way to just configure the parallel, it's already pretty complex to do what it does now. If you want to open the API, use rate limiters, that's the only thing I know that works, so you create an incentive for your users to don't overuse it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants