| This is an interesting way to tackle it, but in my scenario, the company id is data from the users table. So without fetching the user first, you don't know what their company ID is. If we don't have the users data, we can't pass the company id with the user ID. This is not a problem if you are doing an explicit query because you can fetch user + company data at the same time. But if you're using the three resolvers above and your only way to guarantee the path chosen is to already have the company id, that won't be possible. Here's another thing I ran into with Pathom. Adding keys may make a previous desired path choice change. Let's say we have our three resolvers return the following. - GetUser - provides :user/email - GetCompany - provides :company/phone_number - GetUserWithCompany - Provides :user/email :company/phone_number I query the environment by giving it a user ID and asking for the phone number that belongs to that users company. (p.eql/process env
{:users/id 16230}
[:company/phone_number])
It pings the third resolver. That's great! It got the information I want in one node.But now what if we also want the users email? (p.eql/process env
{:users/id 16230}
[:company/phone_number
:users/email])
You would think this would just use the same resolver because it provides both of these keys. But it doesn't. It will call the other two resolvers.The reason it does this in my example is I had made a bridge between user and company before I made the more efficient resolver that gets all of that data at once. (def user-customer-bridge
(pbir/alias-resolver :users/customer_id :customers/id))
We needed this bridge before, otherwise we just had two separate user and company queries that couldn't connect at all. The bridge lets that data be joined. But when the bridge is still here, Pathom, for whatever reason, will get the users data first and use the cached result to get the rest of the data, instead of just using our new resolver that gets it all at once. The only solution here is either to set priorities on the resolvers, or to remember to remove the bridge when adding new resolvers.You might think this is petty and arbitrary, and maybe it is. Maybe I am holding it wrong. But it is exactly the kind of thing I ran into just doing test scripts on my own with very simple schemas. Imagine working with 12 people and having hundreds of tables. I suppose the nice thing about Pathom is if you really want to override the path, you can just fetch that stuff manually and then query the environment with the data you got manually. |
In the first case, the situation looks largely the same. I mean you can either uses the same nested inputs strategy but have a special key that triggers the fat-query resolver. Something like :employed-user-id.
The other alternative is using nested outputs. You have the resolver returned a keyed bundle. Something like {:fat-request [:users/email :company/phone_number]}. The downstream resolver then consumers a :fat-request and unpacks it using nested inputs.
As for the second example. I'm a little confused on some of the specifics. Writing out the resolver mappings more explicitly.. I'm inferring this is what's going on:
- GetUser - :users/id -> :users/email :company/id
- GetCompany - :company/id -> :company/phone_number
- GetUserWithCompany - :users/id -> :users/email :company/phone_number (<- this is a shortcircuit bypassing :company/id)
From this I can see why the first request triggers number 3. You could of course make the third resolver return a bundled output which may simplify things.
The second request.. I get a bit confused here.
1. I'm a bit confused about the bridge. Maybe there's a typo? Or are you saying `customer` is some completely separate namespace that's interfering with the behavior? In the text you seem to imply you're aliasing company/id and user/id.. but that would be a bit crazy :)
2. You then say "and use the cached result to get the rest of the data". So you have cached resolvers and there is memory from previous requests?
Is it internally, after the first request, remembering the :company/id associated with this :users/id? So it triggers the first two resolvers instead of the third one (but why was the :company/phone_number and users/email not in the cache?)
> Imagine working with 12 people and having hundreds of tables.
Yeah, I think at this point in time there is no sense of best-practices or common programming patterns. From reading the docs and issues, I don't even get the sense Pathom's author has a good sense of how best to hook things up. So we're in the `goto` era of using Pathom and you can end up with a messy web of resolvers. Playing around with the system.. I'm left feeling like there is some emergent logic and ways to organize code. But maybe there are corner cases where it all breaks down and you start to miss imperative programming. My gut reaction is that if I see two separate paths on the same inputs/outputs .. then I'm immediately thinking - "can I redesign my system to avoid this?"
As a simple thought experiment. Say you want to inject stuff in to a pipeline (So some A -> B -> C -> D becomes A -> B -> ZZ -> D). Pathom's author suggests using the Priority attribute. https://pathom3.wsscode.com/docs/resolvers/#prioritization
But you have other alternatives...
- You can also add a dummy key :take-zz-branch. You have resolverC that takes :B and you have resolverZZ that takes :B and :take-zz-branch. Precedence rules .. should .. make it take the branch (unless it for some reason requires fewer inputs?).
- You can make resolverZZ output some dummy key :zz-was-run. If you request :zz-was-run then I think it should also take the branch? (or maybe it runs both branches).
Maybe there are other methods I've not considered. But at this point I'm not clear which method is best!