Comments (5)
Do we need to guarantee that the list of entities we are returning come in the same order as list of representations?
Yes.
But i cannot see this mentioned anyhow in the docs for this module. Is this issue handled somehow else by the library?
Its an implementation detail. fed-jvm
is one of many subgraph libraries and they all should adhere to the same spec -> see docs for details.
from federation-jvm.
Ok, i agree that this is an implementation detail, and that fed-jvm is one of many subgraph libraries.
But the design of this particular library encourages breaking the rule of preserving order - that is why i asked to mention in docs that the fetchEntities should maintain order.
Furthermore, do you have any hints how to integrate fetchEntities with Spring's BatchLoaderRegistry used for batch fetching entities?
from federation-jvm.
But the design of this particular library encourages breaking the rule of preserving order - that is why i asked to mention in docs that the fetchEntities should maintain order.
Can you elaborate what part of the design encourages breaking the rule of preserving order
? Entity data fetcher gets a list of entity representations and list is an ordered collection of items (GraphQL does not support sets). Hence I am curious how would you map a list to an out-of-order list?
Furthermore, do you have any hints how to integrate fetchEntities with Spring's BatchLoaderRegistry used for batch fetching entities?
DISCLAIMER: I am not an expert on data loaders as I haven't used it much, answer below is based on my understanding of how it works together.
In general, using the data loader should be the same as with any other data fetcher/resolver -> i.e. you can access data loader through DataFetchingEnvironment#getDataLoader(<name>)
.
If your service resolves single entity type then it is pretty simple as you can just use single loadMany
data loader call to return appropriate future. Otherwise, it becomes problematic as you would need to dispatch multiple data loaders which hits the problem described here. It is possible to work around it but it is somewhat messy.
One potential alternative is to NOT use the data loader when fetching entities -> simply create POJOs in your entity data fetcher using provided representation details and then use the data loader for resolving the heavy computation fields.
Also an FYI, using Spring GraphQL 1.3 is going to simplify this integration (docs). Unsure whether it addresses the multiple data loader calls though.
@EntityMapping
public Book book(DataFetchingEnvironment environment, @Argument int id) {
return environment.getDataLoader("book").load(id);
}
from federation-jvm.
By encouraging i mean the fact that library makes one work with the list of representations, not with individual representation - which naturally makes one want to group and batch those representations.
But you are right that this 1.3 version is going to fix the exact problem i am having - I am unable to find a way to delegate the representation loading to those dataloaders, since to handle the representations i would need to call multiple data loaders
@Override
public Object get(DataFetchingEnvironment env) throws Exception {
List<Map<String, Object>> representations = env.getArgument(_Entity.argumentName);
return representations
.stream()
.map(
representation ->
Optional.ofNullable(env.getDataLoader((String) representation.get(TYPENAME)))
.orElseThrow(() -> new NoDataLoaderForTypeException((String) representation.get(TYPENAME)))
.load(representation)
)
.collect(Collectors.toSet());
}
from federation-jvm.
So I ended writing a DataFetcher like this
@RequiredArgsConstructor
public class FederatedEntitiesDataFetcher implements DataFetcher<CompletableFuture<List<Object>>> {
private static final String TYPENAME = "__typename";
private final String modelPackage;
@Override
public CompletableFuture<List<Object>> get(DataFetchingEnvironment env) throws Exception {
List<Map<String, Object>> representations = env.getArgument(_Entity.argumentName);
var representationLoaders =
representations.stream()
.map(
representation ->
getDataLoader(env, representation).load(getKeyFieldValue(representation)))
.toList();
return CompletableFuture.allOf(representationLoaders.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> representationLoaders.stream().map(CompletableFuture::join).toList());
}
private DataLoader<Object, Object> getDataLoader(
DataFetchingEnvironment env, Map<String, Object> representation) {
return Optional.ofNullable(env.getDataLoader(modelPackage + "." + representation.get(TYPENAME)))
.orElseThrow(() -> new NoDataLoaderForTypeException((String) representation.get(TYPENAME)));
}
private static Object getKeyFieldValue(Map<String, Object> representation) {
return representation.entrySet().stream()
.filter(e -> !e.getKey().equals(TYPENAME))
.findFirst()
.map(Entry::getValue)
.orElseThrow(
() -> new MalformedRepresentationException((String) representation.get(TYPENAME)));
}
}
It is important to return a single CompletableFuture from a DataFetcher, and also to verify that keys in Map returned in registerMappedBatchLoader match the types for keys that are the input to that method.
This works with representations of different entities in the same query.
Posting this for anyone who might have a similar problem
from federation-jvm.
Related Issues (20)
- _service query should return non-nullable _Service type
- Composed directives must be consistently named across subgraph implementations and not use @federation__ prefix HOT 1
- Protobuf-java version is not correct in Maven Library for 2.X HOT 2
- Enable full CI/CD HOT 1
- Update Spring example to use the Apollo Router HOT 1
- Classpath issue on 2.1.0 HOT 2
- _entities error HOT 10
- @link appears to fail on "extend schema" HOT 4
- GraalVM Reachability Metadata for Apollo Federation JVM
- Add support for Federation v2.3 spec HOT 4
- @inaccessible directives no longer returned in _service { sld } query, after release 0.7.0 HOT 5
- Feature Request: Support Error Masking Behavior
- 'link' directive definition is missing 'for' parameter HOT 2
- generateServiceSDL in ServiceSDLPrinter - invalid includeDirectives configfuration? HOT 1
- Action Required: Fix Renovate Configuration
- Federation 2.6 support HOT 1
- Importing and renaming @key directive HOT 1
- Federation scalars declared in the schema file don't get wired up by the transformer HOT 3
- Add configuration options to transformation of sdl or check for federation directives HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from federation-jvm.