| It doesn't seem petty at all. These are the fundamental primitives of how you want to decouple and organize code. You have to look at them through small examples. 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! |
When I say cached result I misspoke, I mean Pathom, rather than running the one resolver that gets everything, will first see the resolver that gets only the user and grab that. Then it will consider :user/email satisfied and look for other resolvers. It seems to not look for the resolver that solves all the requested data, and instead goes first come first serve.
> 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.
> 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)
I think that these tricks can work sometimes, but you might be surprised what odd behavior can come up if you rely on this. In your pathom query, the order of your requested data matters.
I couldn't tell you why it shakes out this way. Something about the bridge and requesting `:customers/phone_number` first must be coercing Pathom to take the longer path to :customers/phone_number, even though the other resolver can get everything in one shot. This is the kind of subtle behavior that is unintuitive and could blow up production if you trigger the wrong resolver in the wrong hot path. So I don't see a reasonable argument for using Pathom in an application that needs reliability unless you make the resolved paths part of the test suite. Although, I still think it could be a powerful combination with something like Sqlite or Datalevin where many reads don't matter as much.