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.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?
I'm not sure that would work. Clients either want [name age family-tree]
or [name age]
.
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.
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.
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?
my normal reaction to this would be to have one resolver for each attribute there (name, age, family tree)
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?
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
and the call is expensive, and even more expensive if we tell it to also return the family tree
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
and when the request doesn't specify family-tree as output, pass false
to the lib call so it isn't calculated
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
for now, like you said, you can look at the ast and make this decision
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
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
on this case, the simple lookup on the AST wouldn't be enough
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)
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]}
?
I wonder if you'd consider this more or less fragile in terms of composition than the look-at-ast way?
are you in pathom 2 or 3?
2
I think you can do with two resolvers, but you would need pathom 3, to set the resolver priority
also, pathom 2 doesnt look at subqueries for process, pathom 3 does
I see. Thank you for the insight!
so {:foo/people [:name :age]}
needs to have higher priority if you do it this way
ah, sorry
if you use different names foo/people
and foo/people-with-tree
, that works fine (in pathom 2 or 3)
if you don't mind having this caveat for your interface, its good
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
Unfortunately we would need nested attributes in the response like in your latest example {:foo/people [:name :age]}
For this query that fn would only return :foo/people
attribute
But I guess I could write some custom code ๐
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
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.