Dynamic Resolvers
danger
Dynamic resolvers feature in Pathom is currently in research/experimental stage, please avoid relying on this feature for critical parts of your system until there is time to build confidence in it.
What are dynamic resolvers?
Dynamic resolvers is a feature of Pathom that enables the definition of remote complex sources of information.
Dynamic resolvers are used for:
- Integrate a Pathom instance with another Pathom instance
- Integrate Pathom with GraphQL servers
- Integrate Pathom with Datomic
important
Dynamic resolvers are an advanced feature of Pathom, this page describes the motivations and how it works, but for most users you can take full advantage of dynamic resolvers using driver implementations like the ones linked before, without understand the implementation details.
What dynamic resolvers can do?
To understand the problem dynamic resolvers solve, let's first go through a manual process call a remote Pathom service.
Here is the code for the remote service:
Now let's consider we have a different server, and we want to consume and extend
the user data to add the :user/ip
of each user.
In this case we are going get the information writing resolvers to forward some queries to our previous server.
With this setup we can run the following query combining the sources:
It works! But there are several inefficiencies in this process. For start let's look at the trace graph from this query:
The trace show us that to complete this request, it called the remote server four times. One for the users, plus one per company (given we have 3 different companies).
Some key points:
- We have to manually integrate each resolver, which means every change on the server might require changes on the clients
- Excessive round trips, which adds significant overhead
Now try to imagine how this would scale, with hundreds of resolvers and maybe multiple services.
That's were dynamic resolvers come in. Dynamic resolvers can leverage the planning algorithms of Pathom to calculate a request to an external service. When we think about Pathom integrating with Pathom, this translates as having the external index, but instead of processing it locally, its filtered and send to a remote service.
Let's redo our client code, but this time using the foreign Pathom feature, which provides tools to integrate a Pathom system with another:
Now let's run the same query and check the trace:
Note this time there was only a single request sent to the remote server. To handle this Pathom is taking the query and the remote server in consideration to find the optimal query to request, reducing the round trips.
How dynamic resolvers work
Dynamic resolvers have two main parts.
The first is the dynamic resolver
itself, it's like a normal resolver, but with
::pco/dynamic-resolver? true
. One difference from static resolvers, is that dynamic resolvers
will also include a foreign ast
. This AST describes the request for the dynamic
resolver to use.
The second part are auxiliar resolvers
. Those resolvers don't have an implementation,
they are used to calculate the sub-query to send to the dynamic resolver.
We can make an adaptation of our previous manual example to implement it using dynamic resolvers:
We did a little change, we are going to get information from a single users, so it's simpler to inspect:
In the following component you can see the final plan, and the steps to get to it.
Try going back to the === Optimize ===
path, where you will be able to see three
nodes for remote-dynamic
.
tip
Use the combobox on the left to switch between displaying the node resolver name and the node id.
The merge at the step Merge chained same dynamic resolvers.
is one interesting to note.
In this case the first node will get the :company/id
from the :user/id
, the second
will use the :company/id
to fetch the :company/name
.
In this situation, Pathom understands that this dynamic source already know about
the middle transitions, so we can remove the middle parts. This results in an end
node that will have :user/id
as input and :company/name
as the output, skipping
the :company/id
fetch part.
A different kind of merging happens at the step Merging sibling resolver calls to resolver remote-dynamic
.
This time is different, it's a sibling relationship merge. In this case Pathom merges the foreign ast of the nodes, combining then in a single request.
tip
Click on the nodes in the graph to see their data details, you can follow how they change at each step of the graph definition.
Other data sources
The previous example demonstrates how Pathom uses dynamic resolvers to combine request demands of a foreign source.
One important thing to note is that the dynamic resolver idea is not be strict to Pathom usages. Instead, you can think of a generic solution for sources that could support this kind of request, or something adaptive.
The simplest example that supports this kind of shape query is GraphQL.
We can also use a shape like this to translate to other formats like SQL. The Walkable library is a good example on how to translate a shape request into something that's not native adaptive to it, like SQL.
GraphQL
The library Pathom 3 GraphQL has an implementation to incorporate GraphQL data sources into the Pathom system. Learn more at the GraphQL tutorial.