我正在尝试在某些字段上设置静态缓存控件,如此处
所做的那样根据我的理解,我需要使用指令,因此我使用以下嵌套文档来声明指令
所以,我构建了一个cacheControl指令,这就是我的GraphQLModule.forRootAsync在buildSchemaOptions中的内容:
buildSchemaOptions: {
directives: [
new GraphQLDirective({
name: 'cacheControl',
locations: [
DirectiveLocation.FIELD_DEFINITION,
DirectiveLocation.OBJECT,
DirectiveLocation.INTERFACE,
DirectiveLocation.UNION
],
args: {
maxAge: { type: GraphQLInt },
scope: {
type: new GraphQLEnumType({
name: 'CacheControlScope',
values: {
PUBLIC: {
astNode: {
kind: 'EnumValueDefinition',
description: undefined,
name: {
kind: 'Name',
value: 'PUBLIC'
},
directives: []
}
},
PRIVATE: {
astNode: {
kind: 'EnumValueDefinition',
description: undefined,
name: {
kind: 'Name',
value: 'PRIVATE'
},
directives: []
}
}
}
})
},
inheritMaxAge: { type: GraphQLBoolean }
}
})
]
}
它确实在模式中创建了指令:
directive @cacheControl(maxAge: Int, scope: CacheControlScope, inheritMaxAge: Boolean) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
enum CacheControlScope {
PUBLIC
PRIVATE
}
现在,我尝试在 @ObjectType 中的字段声明中使用它,如下所示:
import { Directive, Field, Int, ObjectType } from '@nestjs/graphql'
@ObjectType('User')
export class User {
@Directive('@cacheControl(maxAge:60)')
@Field(() => Int)
id!: number
@Directive('@cacheControl(maxAge:60)')
@Field()
text!: string
}
但是当执行一些查询来获取所有用户时,它似乎没有缓存任何内容 - 并且不发送缓存控制标头并每次执行整个查询。 我尝试做一个转换器,但不确定如何为解析器实现缓存。 我错过了什么?
我能够在 NestJS 中实现此功能。关键是确保任何子对象类型也指定了
maxAge
或设置了 inheritMaxAge: true
。这对于解析器 Query
和 ResolveField
来说是一样的。
代码:
app.module.ts
import { ApolloServerPluginCacheControl } from '@apollo/server/plugin/cacheControl';
import responseCachePlugin from '@apollo/server-plugin-response-cache';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule, Int } from '@nestjs/graphql';
import { DirectiveLocation, GraphQLBoolean, GraphQLDirective, GraphQLEnumType } from 'graphql';
import { ParentResolver } from './parent.resolver';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
plugins: [ApolloServerPluginCacheControl(), responseCachePlugin()],
buildSchemaOptions: {
directives: [
new GraphQLDirective({
name: 'cacheControl',
args: {
maxAge: { type: Int },
scope: {
type: new GraphQLEnumType({
name: 'CacheControlScope',
values: {
PUBLIC: {},
PRIVATE: {},
},
}),
},
inheritMaxAge: { type: GraphQLBoolean },
},
locations: [
DirectiveLocation.FIELD_DEFINITION,
DirectiveLocation.OBJECT,
DirectiveLocation.INTERFACE,
DirectiveLocation.UNION,
DirectiveLocation.QUERY,
],
}),
],
},
}),
],
providers: [ParentResolver]
})
export class AppModule {}
cache-control.decorator.ts
import { Field, ObjectType, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { CacheControl } from './cache-control.decorator';
@ObjectType()
export class ParentSchema {
@Field()
field: string;
}
@ObjectType()
export class ChildSchema {
@Field()
field: string;
}
@Resolver(() => ParentSchema)
export class ParentResolver {
@CacheControl({ maxAge: 100 })
@Query(() => Parent, { name: 'parent' })
async getParent(): Promise<ParentSchema> {
return {
field: 'field-a',
};
}
// need to make sure that the child field also specifies cache control settings
@CacheControl({ inheritMaxAge: true })
@ResolveField('child', () => ChildSchema)
async getChild(): Promise<ChildSchema> {
return { field: 'field-b' };
}
}
parent.resolver.ts
import { Field, ObjectType, Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { CacheControl } from './cache-control.decorator';
// cache control hints can be applied to types
@CacheControl({ maxAge: 100 })
@ObjectType()
export class ParentSchema {
@Field()
foo: string;
}
// need to make sure child types also specify cache control hints
@CacheControl({ inheritMaxAge: true })
@ObjectType()
export class ChildSchema {
@Field()
bar: string;
}
@Resolver(() => ParentSchema)
export class ParentResolver {
// OR cache control hints can be applies to resolvers
@CacheControl({ maxAge: 100 })
@Query(() => Parent, { name: 'parent' })
async getParent(): Promise<ParentSchema> {
return {
foo: 'biz',
};
}
// need to make sure that the child field also specifies cache control hints
@CacheControl({ inheritMaxAge: true })
@ResolveField('child', () => ChildSchema)
async getChild(): Promise<ChildSchema> {
return { bar: 'baz' };
}
}