Skip to content

Commit

Permalink
Resolve multiple federated entities in a single entityResolve call (#…
Browse files Browse the repository at this point in the history
…1709)

* Resolve multiple federated entities in a single entityResolve call

Entity resolver functions can only process one entity at a time. But often we want to resolve all the entities at once so that we can optimize things like database calls. And to do that you need to add you'd need to add batching with abstractions like dataloadgen or batchloader. The drawback here is that the resolver code (the domain logic) gets more complex to implement, test, and debug.

An alternative is to have entity resolvers that can process all the representations in a single call so that domain logic can have access to all the representations up front, which is what Im adding in this PR.

There are a few moving pieces here:
1. We need to define the directive `directive @entityResolver(multi: Boolean) on OBJECT`.
2. Then federated entities need to be annotated to enable the functionality.  E.g. `type MultiHello @key(fields: "name") @entityResolver(multi: true)`
3. When that's configured, the federation plugin will create an entity resolver that will take a list of representations.

Please note that this is very specific to federation and entity resolvers. This does not add support for resolving fields in an entity.

Some of the implementation details worth noting. In order to efficiently process batches of entities, I group them by type so that we can process groups of entities at the same time. The resolution of groups of entities run concurrently in Go routines.  If there is _only_ one type, then that's just processed without concurrency. Entities that don't have multiget enabled will still continue to resolve concurrently with Go routines, and entities that have multiget enabled just get the entire list of representations.

The list of representations that are passed to entity resolvers are strongly types, and the type is generated for you.

There are lots of new tests to ensure that there are no regressions and that the new functionality still functions as expected. To test:
1. Go to `plugin/federation`
2. Generate files with `go run github.com/99designs/gqlgen --config testdata/entityresolver/gqlgen.yml`
3. And run `go test ./...`. Verify they all pass.

You can look at the federated code in `plugin/federation/testdata/entityresolver/gederated/federation.go`

* Added `InputType` in entity to centralize logic for generating types for multiget resolvers.

* reformat and regenerate

Signed-off-by: Steve Coffman <steve@khanacademy.org>

Co-authored-by: Steve Coffman <steve@khanacademy.org>
  • Loading branch information
MiguelCastillo and StevenACoffman committed Nov 13, 2021
1 parent 80713b8 commit 50292e9
Show file tree
Hide file tree
Showing 14 changed files with 1,373 additions and 256 deletions.
111 changes: 90 additions & 21 deletions example/federation/accounts/graph/generated/federation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

111 changes: 90 additions & 21 deletions example/federation/products/graph/generated/federation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 50292e9

Please sign in to comment.