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

Allow for type to be omitted when calculating Cache keys #102

Open
x-sheep opened this issue Feb 27, 2025 · 4 comments
Open

Allow for type to be omitted when calculating Cache keys #102

x-sheep opened this issue Feb 27, 2025 · 4 comments
Labels
enhancement New feature or request

Comments

@x-sheep
Copy link

x-sheep commented Feb 27, 2025

Use case

Given an endpoint that returns an interface type, it's currently not possible to set a fieldPolicy that will resolve the various implementation types.

interface Node @typePolicy(keyFields: "id") {
    id: ID!
}

type Actual implements Node {
    id: ID!
    name: String
}

type Query @fieldPolicy(forField: "node", keyArgs: "id") {
    node(id: ID!): Node # Cache will never find an Actual object before sending a request
}

I'm trying to use the node field to get a variety of types that have most fields in common. However, since those types are cached using their full type name, it isn't possible to retrieve the object from cache using the node field because only the Node interface is known.

Describe the solution you'd like

Inspired by the rejected RFC apollographql/apollo-ios-dev#549, I want to suggest @typePolicy and @fieldPolicy gain a new field named keyScope, with one of the following possible values:

  1. TYPE: The identifier is unique for the type, e.g. an auto-incrementing column from a database table.
  2. SERVICE: The identifier is unique across the current GraphQL Service, e.g. a type name combined with an auto-increnting column.
  3. UNIVERSAL: The identifier is unique across all GraphQL services, e.g. UUIDs generated through RFC 9562. Exact serialization details are unspecified, as long as all UUID information is present. Appending more information is allowed.

TYPE is the default. If the scope is not TYPE, cache keys should not contain the type name but only use the actual id as a cache key (possibly with a constant prefix).

The GraphQL best practice known as Global Object Identification requires that all ids are unique across the service. This is also a required part of the Relay spec.

@BoD BoD transferred this issue from apollographql/apollo-kotlin Feb 27, 2025
@BoD BoD added the enhancement New feature or request label Feb 27, 2025
@BoD
Copy link
Collaborator

BoD commented Feb 27, 2025

(I've transferred the ticket because new cache features will happen here.)

Thanks for this, this is interesting!

For your immediate use case, you may provide your own CacheKeyGenerator/CacheResolver as described here, and not include the type in the CacheKey.

Also, I'm wondering if there's a way to make the builtin TypePolicyCacheKeyGenerator/ FieldPolicyCacheResolver work as expected with interfaces/unions.

More thoughts about your proposal: do we need the distinction between service and universal?

@x-sheep
Copy link
Author

x-sheep commented Feb 27, 2025

do we need the distinction between service and universal?

Not for my use case, but I thought it would be a good idea to nail down this distinction in case a service becomes part of a federated graph. The term "global" could refer to either SERVICE or UNIVERSAL which could become a real problem when several subgraphs produce identifiers and call them global.

@martinbonnin
Copy link
Contributor

do we need the distinction between service and universal?

I want it for the day we have a Global supergraph 😄 Then I can cache my GitHub pull requests and Shopify inventory in the same cache 🚀 (probably not until a couple more decades so let's say I support UNIVERSAL softly for now and unless there are other strong arguments, it's probably better to live it out and add it later down the road when we actually need it, or when our grand children do 😄)

@x-sheep
Copy link
Author

x-sheep commented Feb 27, 2025

Obviously I'm not attached to immediately adding UNIVERSAL, but I think it would be a good idea to keep this new field an enum, and avoid the term "global" since it doesn't play well with federation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants