pathom

:pathom: https://github.com/wilkerlucio/pathom/ & https://pathom3.wsscode.com & https://roamresearch.com/#/app/wsscode
imre 2021-01-25T09:48:22.021800Z

Hey Wilker, I was wondering if you could point me in the right direction with this.

{:foo/people
 [:foo.person/name
  :foo.person/age
  :foo.person/family-tree]}
Imagine the above. I am trying to wrap a library call which is roughly (input, calculate-family-tree?) -> people. Now, family tree calculation is expensive, so when it is not needed, I'd like to pass false there. Is this solvable only by looking at the query itself in the resolver, or is it possible to make this work by writing multiple resolvers with different output definitions, one resolver also returning family trees, the other not. The aim is that there is only one call made to the lib and calculate-family-tree? is false where we don't need to return it.

dehli 2021-01-25T13:37:02.022800Z

If you have a resolver that only outputs :foo.person/family-tree and then another resolver for the other attributes I think that would solve the issue. If the client doesnโ€™t specify family-tree in the query, then pathom wonโ€™t execute the expensive query. Does this answer the question?

imre 2021-01-25T13:42:33.023100Z

I'm not sure that would work. Clients either want [name age family-tree] or [name age].

imre 2021-01-25T13:43:56.023300Z

And while family-tree is the most expensive to calculate, the other 2 are also somewhat costly, so we only want to make one call to the underlying lib. Retrieving family-tree separately from the other 2 won't work for us I'm afraid.

imre 2021-01-25T14:36:26.023500Z

One alternative we considered was to make 2 top-level keys, :foo/people and :foo/people-with-family-tree, which works but feels a little clunky.

wilkerlucio 2021-01-25T19:24:46.024Z

hello @imre, not sure if I got it right, but the thing you say is that to compute :foo/people you like to know ahead of time if the user asked for family-tree in the sub?

wilkerlucio 2021-01-25T19:25:06.024200Z

my normal reaction to this would be to have one resolver for each attribute there (name, age, family tree)

wilkerlucio 2021-01-25T19:25:56.024400Z

the only case I think you really need to see it before is that if your sub request depends on it, in this case its more like Datomic or GraphQL integrations (where we need to figure what parts of the sub-query must be delegated), does this sounds like your case?

imre 2021-01-25T19:33:55.024600Z

One resolver per attr would be best, yes, but the library we are wrapping returns all 3 of these in one call getpeople(input, family-tree?) -> people

imre 2021-01-25T19:34:21.024800Z

and the call is expensive, and even more expensive if we tell it to also return the family tree

imre 2021-01-25T19:35:34.025Z

so regardless of the desired output (whether it's a single prop or all 3) we only want to make one lib call per request

imre 2021-01-25T19:36:08.025200Z

and when the request doesn't specify family-tree as output, pass false to the lib call so it isn't calculated

wilkerlucio 2021-01-25T19:37:49.025400Z

gotcha, that to me aligns a lot on how dynamic resolvers work, this is something I'll work more once the tools and basics are out

wilkerlucio 2021-01-25T19:38:04.025600Z

for now, like you said, you can look at the ast and make this decision

wilkerlucio 2021-01-25T19:38:25.025800Z

I think I did something similar for the Youtube API, where they accept the "parts" to say which pieces you want, in this case I also look at the query to decide it

wilkerlucio 2021-01-25T19:38:46.026Z

what's really tricky is if you don't depend on this attribute directly, but instead you are trying to get some attribute that depends on it

wilkerlucio 2021-01-25T19:38:54.026200Z

on this case, the simple lookup on the AST wouldn't be enough

wilkerlucio 2021-01-25T19:39:11.026400Z

that's where dynamic resolvers will be really helpful, because they can do these attribute calculations for you (and it does it at the same planning phase as the static resolvers stuff)

imre 2021-01-25T19:40:54.026700Z

Gotcha, thank you. What do you think about the approach where we'd have 2 resolvers, one returning {:foo/people [:name :age]} and another returning {:foo/people-with-tree [:name :age :tree]}?

imre 2021-01-25T19:42:15.026900Z

I wonder if you'd consider this more or less fragile in terms of composition than the look-at-ast way?

wilkerlucio 2021-01-25T19:48:18.027300Z

are you in pathom 2 or 3?

imre 2021-01-25T19:48:44.027500Z

2

wilkerlucio 2021-01-25T19:48:52.027700Z

I think you can do with two resolvers, but you would need pathom 3, to set the resolver priority

wilkerlucio 2021-01-25T19:49:10.027900Z

also, pathom 2 doesnt look at subqueries for process, pathom 3 does

imre 2021-01-25T19:49:26.028100Z

I see. Thank you for the insight!

wilkerlucio 2021-01-25T19:49:40.028300Z

so {:foo/people [:name :age]} needs to have higher priority if you do it this way

wilkerlucio 2021-01-25T19:49:48.028500Z

ah, sorry

wilkerlucio 2021-01-25T19:50:11.028700Z

if you use different names foo/people and foo/people-with-tree, that works fine (in pathom 2 or 3)

wilkerlucio 2021-01-25T19:50:27.028900Z

if you don't mind having this caveat for your interface, its good

Janos 2021-01-25T19:52:58.029100Z

Hey Wilker, I've been trying to use this helper fn for the dynamic resolver for this problem: https://github.com/wilkerlucio/pathom/blob/master/src/com/wsscode/pathom/connect.cljc#L670

Janos 2021-01-25T19:54:43.029400Z

Unfortunately we would need nested attributes in the response like in your latest example {:foo/people [:name :age]}

Janos 2021-01-25T19:55:40.029700Z

For this query that fn would only return :foo/people attribute

Janos 2021-01-25T19:59:42.029900Z

But I guess I could write some custom code ๐Ÿ˜Š

wilkerlucio 2021-01-25T20:12:34.030100Z

yeah, if you need, go forward, Pathom 2 isn't getting any updates on the dynamic side of things, and for Pathom 3 things are quite different, so whatever happens in Pathom 3 is gonna be different from what you looking at now

๐Ÿ‘ 1
wilkerlucio 2021-01-25T21:00:53.033700Z

hello people! for the adventurous, the new Pathom Viz with trace support for Pathom 3 is outย ๐ŸŽ‰! You can download it at:ย https://github.com/wilkerlucio/pathom-viz/releases/tag/v2021.1.25, remember to use the latest connector and pathom 3 as well. Documentation around debugging (with and without Pathom Viz) is my next task, should be out later this week! Even if you don't use Pathom 3 yet, I recommend upgrading, I updated the views with Clojure readonly to use the new Clojure-mode from nextjournal, and its great! the biggest difference for me is that it supports folding, and when looking at big structures that's a big deal. Also I made all the printed maps to be sorted, making easier to find the data. Remember Pathom Viz is compatible with both Pathom 2 and 3. Please let me know if have any issues with this release.

๐Ÿ‘ 1
๐ŸŽ‰ 3