You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
I believe a common requirement for GraphQL is proper edge caching with per query cache duration, and having this functionality embedded in the framework would make user's life much easier.
Describe the solution you'd like
We tackled this problem by defining a CacheableQuery, which extends Query, and contain a edgeCacheDuration field as follows.
Then whenever defining a query class, we have something like:
@Component
class MyCacheableQuery : CacheableQuery {
override val edgeCacheDuration: CacheDuration = CacheDuration.FIVE_MINUTES
...
}
Then we define a CacheControlFilter, which scans a request body (or retrieves the preparsed document if it's an APQ GET with hash only) and finds the minimum edgeCacheDuration and sets it in the control header. Something like the following:
override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
val response = exchange.response
val request = exchange.request
val decoratedResponse = object : ServerHttpResponseDecorator(response) {
override fun writeWith(body: Publisher<out DataBuffer>): Mono<Void> {
if (request.isGetPersistedQuery()) {
request.getAutomaticPersistedQueryExtension()?.let { extensions ->
val entry = apqCache.get(extensions.sha256Hash)
if (entry != null) {
entry.document.definitions
.filterIsInstance<OperationDefinition>()
.filter { it.operation == OperationDefinition.Operation.QUERY }
.flatMap {
it.selectionSet.getSelectionsOfType(Field::class.java).map { field -> field.name }
}
.minOfOrNull { edgeCacheDuration.getValue(it) }?.let { duration ->
headers.cacheControl = "max-age=$duration"
}
}
}
}
return super.writeWith(body)
}
}
val decoratedRequest = object : ServerHttpRequestDecorator(request) {
override fun getBody(): Flux<DataBuffer> =
super.getBody().doOnNext { dataBuffer ->
val body = dataBuffer.toString(StandardCharsets.UTF_8)
val duration = extractQueries(body).minOfOrNull { edgeCacheDuration.getValue(it) } ?: 0
if (duration > 0) decoratedResponse.headers.cacheControl = "max-age=$duration"
}
}
return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())
}
Describe alternatives you've considered
This feature can probably be achieved by using apollo server, for example, but in many cases, apollo server usage is not really needed/desired, and a simpler solution can be done directly in the graphql framework within the application.
Additional context
n/a
The text was updated successfully, but these errors were encountered:
Is your feature request related to a problem? Please describe.
I believe a common requirement for GraphQL is proper edge caching with per query cache duration, and having this functionality embedded in the framework would make user's life much easier.
Describe the solution you'd like
We tackled this problem by defining a CacheableQuery, which extends Query, and contain a edgeCacheDuration field as follows.
Then whenever defining a query class, we have something like:
Then we define a CacheControlFilter, which scans a request body (or retrieves the preparsed document if it's an APQ GET with hash only) and finds the minimum edgeCacheDuration and sets it in the control header. Something like the following:
Describe alternatives you've considered
This feature can probably be achieved by using apollo server, for example, but in many cases, apollo server usage is not really needed/desired, and a simpler solution can be done directly in the graphql framework within the application.
Additional context
n/a
The text was updated successfully, but these errors were encountered: