Skip to content

consider memoizing getArgumentValues #383

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

Open
mnpenner opened this issue May 6, 2016 · 3 comments
Open

consider memoizing getArgumentValues #383

mnpenner opened this issue May 6, 2016 · 3 comments

Comments

@mnpenner
Copy link

mnpenner commented May 6, 2016

Maybe I don't understand something, but I didn't think it would be necessary for GraphQLScalarType.parseLiteral to be called every time a field argument is resolved.

e.g., given this GraphQL query:

{
  clients(limit: 10) {
    id,
    fullName,
    birthDate,
    deathDate,
    age(asOf: "Jan 1st, 1987 @ 04:12:34.456 -0500")
  }
}

And this field:

export default new GraphQLObjectType({
    name: 'Client',
    description: `Person served`,
    fields: () => ({
        age: {
            type: GraphQLString,
            description: `Age in "#y #m" format`,
            args: {
                asOf: {
                    type: DateTime,
                    description: `Date to calculate age from`
                }
            },

            resolve: (client, {asOf}) => {
                dump(asOf.format('D-MMM-YYYY @ H:mm:ss.SSS Z'));
                ...

And this custom type:

export default new GraphQLScalarType({
    name: "DateTime",
    description: `Scalar type representing a date and time with offset, serialized as a string in ISO-8601 date format.\n\ne.g. \`"2016-05-05T20:16:06Z"\``,
    serialize(value) {
        let date;
        if(_.isNumber(value)) {
            if(value === 0) {
                return null;
            }
            date = moment.unix(value);
        } else {
            date = moment(value);
        }
        if(!date.isValid()) {
            throw new GraphQLError(`Serialization error: ${value} is not a valid date`)
        }
        return date.format();
    },
    parseValue(value) {
        // see https://gist.github.com/olange/f6c57d3ca577955fc3a51aa62f88c948
        // or https://github.com/soundtrackyourbrand/graphql-custom-datetype/blob/master/datetype.js
        // but parse it with moment.js
        throw new GraphQLError(`parseValue(${value}) not implemented`)
    },
    parseLiteral(ast) {
        if(ast.kind !== Kind.STRING && ast.kind !== Kind.INT) {
            throw new GraphQLError(`Parse error: expected date string, got ${JSON.stringify(ast.value)}`, [ast]);
        }

        let result = parseDate(ast.value);

        if(!result.isValid()) {
            throw new GraphQLError(`Invalid date: ${JSON.stringify(ast.value)}`);
        }

        return result;
    }
});

The asOf argument is parsed every time resolve is called -- i.e., 10 times for this one query because I've limited the results to 10. It so happens that my parseDate function is slow, this is kind of painful. I can memoize it on my end, but I didn't think that should be necessary.

Why aren't all the literals parsed just once when the query is received?

@leebyron
Copy link
Contributor

leebyron commented May 7, 2016

Sounds like there's an opportunity for memoization here.

@mnpenner
Copy link
Author

mnpenner commented May 7, 2016

Isn't the GraphQL query converted into an AST? And aren't all literals parsed at that time? This would be necessary for error-checking. I'm just wondering why the parsed literal isn't already in memory by the time resolve() is called.

@yaacovCR
Copy link
Contributor

// TODO: find a way to memoize, in case this field is within a List type.
const args = getArgumentValues(
fieldDef,
fieldNodes[0],
exeContext.variableValues,
);

Just looking at it quickly, you could use memoize3, but it should be possible to use something like memoize2 as the fieldDef is always the same for that field node.

@yaacovCR yaacovCR changed the title parseLiteral called each time field is resolved consider memoizing getArgumentValues Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants