Skip to content

Apollo's schema hints (apollo cache integration) #75

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

Closed
capaj opened this issue May 7, 2018 · 12 comments
Closed

Apollo's schema hints (apollo cache integration) #75

capaj opened this issue May 7, 2018 · 12 comments
Labels
Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved

Comments

@capaj
Copy link
Contributor

capaj commented May 7, 2018

I'd like to create my schema with: https://www.apollographql.com/docs/engine/caching.html#hints-to-schema so it would be nice if I could define any arbitrary graphql directive to be passed to the compiled schema.
Maybe like:

@directive('@cacheControl(maxAge: 240)')
@ObjectType()
class MyClass {
  ...
}

Which should result in

type MyClass @cacheControl(maxAge: 240) {
  ...
}
@MichalLytek
Copy link
Owner

AFAIK, graphql-js doesn't allow for easy registering server-side directives to schema.
There's extensionASTNodes field in ObjectType config but I need some research on this whether this is possible.

For things like caching and other stuff there is a middlewares feature with custom decorators support 😉

@MichalLytek MichalLytek added Enhancement 🆕 New feature or request Community 👨‍👧 Something initiated by a community labels May 7, 2018
@MichalLytek MichalLytek added this to the 1.0.0 release milestone May 7, 2018
@MichalLytek MichalLytek changed the title support apollo's schema hints Schema directives support (apollo's schema hints) May 7, 2018
@MichalLytek
Copy link
Owner

MichalLytek commented May 7, 2018

Ok, I've done some research and looks like right now there's now way to register directives using graphql-js way:

Right now directives are purely a feature of the GraphQL language and IDL, so a schema not created using IDL definitionally won't contain directives. When building a schema in code, you have the full power of the host programming environment, so directives shouldn't be necessary. Directives are a tool for supplying additional intent to be later interpreted by the host programming environment.

However, it looks like there's a possibility to add an integration with Apollo Cache - apollo-cache-control sets cacheControl key on GraphQLResolveInfo:
https://github.com/apollographql/apollo-cache-control-js/blob/master/src/index.ts

So in this case you can create a middleware with custom decorator that will do the same job placing cache hints into GraphQLResolveInfo.

@laukaichung
Copy link

laukaichung commented May 11, 2018

@19majkel94

I've made a middleware for apollo-cache-control after reading this post, but I still don't understand how it's supposed to work. I've set the maxAge to 60 seconds. The middleware seems to be working because I can see the cacheControl data in the extension field from the response.

But when I refresh the page within seconds, the resolver still queries the database. apollo-cache-control has no effects at all.

import {MiddlewareFn} from "type-graphql";

export function CacheControl(maxAge:number = 60): MiddlewareFn {
    return ({info:{cacheControl}}, next) => {
        cacheControl.setCacheHint({maxAge,scope:"PUBLIC"})
        return next();

    };
}
    @Query(returnType => [Item])
    @UseMiddleware(CacheControl())
    public getItems() {
       return dbGetData();
    }

@MichalLytek
Copy link
Owner

I haven't used apollo-cache-control yet, you should try this way in a simple example using graphql-js to see if this work at all and maybe open issue on apollo-cache-control-js repo:
https://github.com/apollographql/apollo-cache-control-js

Unfortunately, I have one's hands tied and I can't do anything until registering directives by code will be available in graphql-js:
graphql/graphql-js#1343

@laukaichung
Copy link

I just read that apollo engine is required in order to work with cache control. I haven't set up apollo engine config in graphql yoga so I will try it later.

@laukaichung
Copy link

laukaichung commented May 11, 2018

The caching finally works by adding Apollo Engine. https://github.com/graphcool/graphql-yoga/blob/master/examples/apollo-engine/index.js

    const port = 3000;
    
    const serverOptions: Options = {
        port,
        endpoint: "/graphql",
        playground: "/playground",
        tracing: true,
        cacheControl: true
    };


    const engine = new ApolloEngine({
        apiKey: process.env.APOLLO_ENGINE_KEY
    });

    const httpServer = graphQLServer.createHttpServer(serverOptions);

    engine.listen(
        {
            port,
            httpServer,
            graphqlPaths: ['/graphql'],

        },
        () =>
            console.log(
                `Server with Apollo Engine is running on http://localhost:3000`,
            ),
    )

@MichalLytek
Copy link
Owner

Thanks for the research 😉 I am going to add integration with apollo-cache-control and apollo-engine to the examples section, along with custom @CacheControl decorator.

@MichalLytek MichalLytek changed the title Schema directives support (apollo's schema hints) Apollo's schema hints (apollo cache integration) May 12, 2018
@MichalLytek MichalLytek added Question ❔ Not future request, proposal or bug issue and removed Community 👨‍👧 Something initiated by a community Enhancement 🆕 New feature or request labels May 12, 2018
@MichalLytek MichalLytek removed this from the 1.0.0 release milestone May 12, 2018
@MichalLytek MichalLytek added the Solved ✔️ The issue has been solved label Oct 22, 2018
@damons-sportsbet
Copy link

damons-sportsbet commented Mar 22, 2019

I really can't work out what the syntax would be for adding cache directives, are there any good examples of this yet?
edit - I read the whole bit from graphql-js and their reasons for not wanting to expose arbitrary directives, I get why this is hard now, I'm going to try implementing cache control through a middleware.
p.s. this library is great, thanks!

@clayrisser
Copy link

Does anyone have an example for cache control with type-graphql?

@omar-dulaimi
Copy link

Does anyone have an example for cache control with type-graphql?
@clayrisser

import { CacheHint } from 'apollo-cache-control';
import 'apollo-cache-control';

export const getCacheControl =
    ({ maxAge = 60, scope = 'PUBLIC' }: CacheHint) =>
    async ({ info }, next) => {
        info.cacheControl.setCacheHint({ maxAge, scope });

        return await next();
    };

then:

export default function buildSchema(): GraphQLSchema {
    return tq.buildSchemaSync({
        globalMiddlewares: [getCacheControl({})],
    });
}

As you can see this way it's globally enabled. The official example didn't work unfortunately. And trying to make it work for resolvers individually wasn't successful.

@oddgrd
Copy link

oddgrd commented Nov 7, 2021

The apollo-cache-control package has been deprecated. Do you still use this solution @omar-dulaimi , or did you figure out another way?

@Distortedlogic
Copy link

bump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question ❔ Not future request, proposal or bug issue Solved ✔️ The issue has been solved
Projects
None yet
Development

No branches or pull requests

8 participants