ballerina-platform / ballerina-library

The Ballerina Library
https://ballerina.io/learn/api-docs/ballerina/
Apache License 2.0
137 stars 58 forks source link

GraphQL Cache is Caching Fields Separately for Record Types with No Optional Values #6652

Closed ThisaruGuruge closed 3 months ago

ThisaruGuruge commented 3 months ago

Description: Consider the following GraphQL service:

import ballerina/graphql;
import ballerina/io;

@graphql:ServiceConfig {
    cacheConfig: {
        maxSize: 5
    },
    graphiql: {
        enabled: true
    }
}
service on new graphql:Listener(9090) {
    resource function get profiles() returns Profile[]|error {
        io:println("Fetching profiles from the database...");
        return [
            {name: "John", age: 30, contact: "0123456789"},
            {name: "Doe", age: 25, contact: "9876543210"},
            {name: "Jane", age: 35, contact: "1234567890"}
        ];
    }
}

type Profile record {|
    string name;
    int age;
    string contact;
|};

In the above example, the cache size is set to 5. But this will execute the resource function each time a request arrives because the cache size is exhausted. The reason is that each record field is cached as a separate cache entry, so there will be a total of 10 cache entries (3*3 fields + top-level resource value). Since the cache limit is 5, caches will be evicted and the subsequent responses have to be fetched again.

This behaviour can be improved only when the GraphQL resource is returning a record type with no optional fields. For other cases such as record types with optional fields or service types, there's no way to cache at the top level and not cache the sub-fields since the different requests will populate different fields which might cause some field values to become null in the cache.