Fork me on GitHub
#pathom
<
2024-05-21
>
itaied10:05:14

hey all, I'm new to pathom, and reading the https://pathom3.wsscode.com/docs/resolvers/#nested-inputs about nested input, it says:

When Pathom is planning, it will verify if a sub-query part reachable. If there is no available path to fulfill the nested part, the planner will discard that path, avoiding running unnecessary work on the runner.

You can try this by asking for a nested property that doesn't exist. 
I have taken the example and tried reaching a missing attribute, changing :player/score to :player/score2:
(pco/defresolver top-players-avg
  "Compute the average score for the top players using nested inputs."
  [{:keys [game/top-players]}]
  ; we have to make the nested input explicit
  {::pco/input [{:game/top-players [:player/score2]}]}
  {:game/top-players-avg-score
   (let [score-sum (transduce (map :player/score2) + 0 top-players)]
     (double (/ score-sum (count top-players))))})
when executing, I'm getting:
; Execution error (ExceptionInfo) at com.wsscode.pathom3.connect.planner/verify-plan!* (planner.cljc:1694).
; Pathom can't find a path for the following elements in the query: [:player/score2] at path [:game/top-players]
why is that?

favila11:05:24

Your input lacks :player/score2? What did you expect to happen?

itaied11:05:40

I thought it would just ignore it. Maybe I have understood the following wrong:

When Pathom is planning, it will verify if a sub-query part reachable. If there is no available path to fulfill the nested part, the planner will discard that path, avoiding running unnecessary work on the runner.

caleb.macdonaldblack11:05:02

I’m super confused also. I have no clue what the docs are trying to say here

itaied11:05:00

and while at it, why does it state that batch resolvers solve the N+1 problem? there are still N+1 reqs, they are just executed concurrently

favila12:05:24

> and while at it, why does it state that batch resolvers solve the N+1 problem? there are still N+1 reqs, they are just executed concurrently batch resolvers are executed only once but receive multiple sibling inputs and return multiple sibling outputs. Because the resolver controls the “mapv”, it can do something other than what would happen for a single input and output. Eg select * from t where id=? N+1 query per input can be where id in (…) single query for all.

👍 1
wilkerlucio12:05:00

hello, about the sub-query part reachable, its when planning for nested inputs, consider this example:

(ns com.wsscode.pathom3.demos.sub-query-reachable
  (:require [com.wsscode.pathom3.connect.indexes :as pci]
            [com.wsscode.pathom3.connect.operation :as pco]
            [com.wsscode.pathom3.interface.eql :as p.eql]))

(def users-db
  {1 {:user/id   1
      :user/name "John"}
   2 {:user/id   2
      :user/name "Doe"}})

(pco/defresolver users []
  {:app/users [{:user/id 1}
               {:user/id 2}]})

(pco/defresolver products []
  {:app/products [{:product/id 1}]})

(pco/defresolver user-by-id [{:user/keys [id]}]
  {::pco/output [:user/name]}
  (get users-db id))

(pco/defresolver all-user-names [{:keys [app/users]}]
  {::pco/input [{:app/users [:user/name]}]}
  {:app/all-user-names (reduce str (map :user/name users))})

(def env
  (-> {}
      (pci/register [users user-by-id products all-user-names])))

(comment
  (p.eql/process env [:app/all-user-names]) ; => {:app/all-user-names "JohnDoe"})

wilkerlucio12:05:33

all-user-names has a nested input, which works fine, because it asks for :user/name from :app/users, which is reachable using the :user/id that's inside :app/users nested itens

wilkerlucio12:05:59

now, if we switch the all-user-names to try to pull from products instead, like:

(pco/defresolver all-user-names [{:keys [app/products]}]
  {::pco/input [{:app/products [:user/name]}]}
  {:app/all-user-names (reduce str (map :user/name products))})

wilkerlucio12:05:48

now, the items under :app/products only have :product/id, which means it can't reach for :user/name in that context. this will cause the plan to fail because it finds no path that can reach the nested requirement

caleb.macdonaldblack12:05:53

@U066U8JQJ That makes sense. Regarding the docs however: > If there is no available path to fulfill the nested part, the planner will discard that path, avoiding running unnecessary work on the runner.

caleb.macdonaldblack12:05:20

> avoiding running unnecessary work on the runner I think that part is not helpful?

caleb.macdonaldblack12:05:39

And then that whole statement is kinda pointless. If the path for the nested data cannot be reached, then your nested data cannot be reached

wilkerlucio12:05:42

I guess I had too many impl details in my head, the point I was trying to make there is that because the planner fails early (by projecting the nested path and realizing there is no path) we don't have to run the top resolver to find out the missing data later, thats why I said > avoiding running unnecessary work on the runner

wilkerlucio12:05:04

but I can see it can get clearer

caleb.macdonaldblack12:05:32

That was my best guess. It looks relevant internally, but not at the consumer level

👍 1