Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CompletableFuture in FederatedTypeResolver, standardize entities resolver with other subgraph implementations #1514

Conversation

samuelAndalon
Copy link
Contributor

@samuelAndalon samuelAndalon commented Aug 12, 2022

📝 Description

With the idea of proving support for returning a CompletableFuture in FederatedTypeResolver
and match other subgraphs implementations a new sealed interface is added

sealed interface FederatedTypeResolver {
    val typeName: String
}

this will be the basic interface of 2 interfaces

  1. The currently supported FederatedTypeResolver is renamed to FederatedTypeSuspendResolver, with support of suspendable function to be executed in a coroutine
interface FederatedTypeSuspendResolver<out T> : TypeResolver {
    override val typeName: String
    suspend fun resolve(
      environment: DataFetchingEnvironment, 
      representation: Map<String, Any>
    ): T?
}
  1. Added a new interface called FederatedTypePromiseResolver that will provide support to return a CompletableFuture allowing compatibility with a DataLoader
interface FederatedTypePromiseResolver<T> : TypeResolver {
    fun resolve(
      environment: DataFetchingEnvironment, 
      representation: Map<String, Any>
    ): CompletableFuture<T?>
}

Clients will have the freedom to decided which interface to use for their resolvers and graphql-kotlin will be smart enough to decide how to execute them.

The execution logic will be capable of executing suspend resolvers or promise resolvers concurrently, specially useful if you have support for data loaders for only certain entities

example representations for multiple types, request to _entities field

UserResolver implementing FederatedTypeResolver
PromiseResolver implementing FederatedTypePromiseResolver

[
  { "__typename": "User", "userId": 123 },
  { "__typename": "User", "userId": 456 },
  { "__typename": "Author", "authorId": 1 },
  { "__typename": "Author", "authorId": 2 },
]

This is going to be a breaking change as it changes the signature of the current FederatedTypeResolver by simplifying the logic, before it was providing a list of representations, and now it will provide a representation (internally graphql-kotlin will ensure the ordering).

All this with the effort of matching other subgraph implementations like Apollo Server
https://www.apollographql.com/docs/federation/api/apollo-subgraph/#__resolvereference

graphql-kotlin

object : FederatedTypeSuspendResolver<User> {
  override val typeName: String = "User"
    suspend fun resolve(
      environment: DataFetchingEnvironment, 
      representation: Map<String, Any>
    ): User? {
      // representation will always have at least the `id` and the `__typename` here
    }
}
object : FederatedTypePromiseResolver<User> {
  override val typeName: String = "User"
    fun resolve(
      environment: DataFetchingEnvironment, 
      representation: Map<String, Any>
    ): CompletableFuture<User?> {
      // representation will always have at least the `id` and the `__typename` here
    }
}

apollo-server

const resolvers = {
  User: {
    __resolveReference(representation, env) {
      // representation will always have at least the `id` and the `__typename` here
    }
  }
};

A couple of tests simulating async operations and delays were added to ensure ordering is properly maintained

🔗 Related Issues

#1506

samvazquez added 7 commits August 8, 2022 12:36

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@samuelAndalon samuelAndalon added the module: generator Issue affects the schema generator and federation code label Aug 12, 2022
@samuelAndalon samuelAndalon changed the title feat: support CompletableFuture return in FederatedTypeResolver feat: support CompletableFuture return FederatedTypeResolver Aug 12, 2022
@samuelAndalon samuelAndalon added the changes: minor Changes require a minor version label Aug 12, 2022
@@ -124,6 +124,19 @@ data class User(
@ExternalDirective val name: String
)

/*
type Author {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the code the type is actually

type Author @extends @key(fields: "authorId") {
  authorId: Int! @external
  name: String: @external

If both fields are external -> should it be @key(fields: "authorId", resolvable: false)? or should there be at least a single local field?

data += null
errors += result
} else {
data += result
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should else also keep track of errors in the list?

@samuelAndalon samuelAndalon changed the title feat: support CompletableFuture return FederatedTypeResolver feat: support returning CompletableFuture FederatedTypeResolver Aug 12, 2022
@samuelAndalon samuelAndalon added changes: major Changes require a major version and removed changes: minor Changes require a minor version labels Aug 17, 2022
@samuelAndalon samuelAndalon marked this pull request as ready for review August 17, 2022 21:15
@samuelAndalon samuelAndalon changed the title feat: support returning CompletableFuture FederatedTypeResolver feat: CompletableFuture in FederatedTypeResolver, standardize resolver with other subgraph implementations Aug 17, 2022
@samuelAndalon samuelAndalon changed the title feat: CompletableFuture in FederatedTypeResolver, standardize resolver with other subgraph implementations feat: CompletableFuture in FederatedTypeResolver, standardize entities resolver with other subgraph implementations Aug 20, 2022
@samuelAndalon samuelAndalon merged commit ab08cdd into ExpediaGroup:master Sep 13, 2022
@samuelAndalon samuelAndalon deleted the feat/federated-type-resolver-promise branch September 13, 2022 04:37
@hrkfdn hrkfdn mentioned this pull request Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changes: major Changes require a major version module: generator Issue affects the schema generator and federation code
Development

Successfully merging this pull request may close these issues.

None yet

4 participants