Usage with Dataloader
rewritten opened this issue · 3 comments
The current dataloader integration seems to be breaking a number of assumptions, I wanted to check, before trying a pull-request, if my assumptions are correct.
-
The function
find_relevant_dataloader
at https://github.com/DivvyPayHQ/absinthe_federation/blob/v0.3.2/lib/absinthe/federation/schema/entities_field.ex#L299 finds any source that is registered in the dataloader, that has a nonempty (by the way, why nonempty?) map as itsbatches
key. This breaks in two ways,- It pries inside a source structure, which is private (only the Source protocol is guaranteed to exist). In my project we have sources where
batches
is a list. - A schema might have several registered sources, so the "first one that has batches" might not be the one with the responsibility of resolving the current entity. One may as well have a separate source per each entity for what is worth, and other dataloader sources for completely unrelated data needs.
- It pries inside a source structure, which is private (only the Source protocol is guaranteed to exist). In my project we have sources where
-
The
call_middleware
function only supports a single key, when entities might need a compound key key to be loaded. Or it may declare multiple keys (real case example: a "slug" key that is used to federate from some front-end-facing subgraph, and a separate "uuid" key that is used to federate from other internal subgraphs).
If you agree that this should be solved, I might attempt a pull-request.
After experimenting a bit, I found the solution to the other issues, and that requires having a very specific KV source (or the Ecto one) that responds to a specific interface.
It remains the issue of supporting multiple keys and compound keys, I will have a more specific attempt for it.
Additionally, there is a limitation that I am not completely sure to see the cause. I can make a source per entity, that has this load_function
def entities(%{__typename: "MyEntity"}, %MapSet{} = keys) do
# return a map for each key to an {:ok, entity}
end
# match the initial "marker" batch_key `{:_entities, %{__typename: "MyEntity", ...key}}`
# it should not be loaded anyways, it is to put a specific item in batches to recognize the source later
def entities(_, _), do: %{}
but resolving different entities in the same source does not work
def entities(%{__typename: "MyEntity"}, %MapSet{} = keys) do
# return a map for each key to an {:ok, entity}
end
def entities(%{__typename: "OtherEntity"}, %MapSet{} = keys) do
# return a map for each key to an {:ok, entity}
end
# match the initial "marker" batch_key `{:_entities, %{__typename: "MyEntity", ...key}}`
# it should not be loaded anyways, it is to put a specific item in batches to recognize the source later
def entities(_, _), do: %{}
, only one entity type is resolved.
I do not have full clarity on how this works, so I'm closing the issue until I can make more experiments.