Skip to content

Adding Entry Point for custom coercion on standard scalars #3145

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

Conversation

rciummo-linkedin
Copy link

@rciummo-linkedin rciummo-linkedin commented Mar 22, 2023

I want to add an entry point for custom coercion in ValuesResolver.json

Essentially, I'd want to keep the current coerceVariableValues and add another flavor of it that takes a Function<Object, Object> preCoercionFunction.

This would get passed to ValuesResolverConversion.externalValueToInternalValueForVariables where if not-null, would translate the value right before this line here

At linkedIn, our APIs pass around a custom null class instance to represent null (say Data.NULL) instead of the java null. This is an issue for us even pre-v20 because this Data.null instance is converting to a string "null" instead of java null. To work around this we are rebuilding the entire rawVariables map to convert Data.NULL to null before parsing our raw input variables. However, we have found that this may be causing performance issues so we would like a way to be able to do our custom conversions while still using the grapql native scalars.

Beyond that, migrating to v20 for us is a challenge because of the stricter string coercer. Ideally a new type would be made for non-strings that fail string coercion in v20. The reason we want to not build our own new scalars is because currently our APIs are using schemas with the native scalars and creating a new type would make all of our schema backwards incompatible which is not an option for us.

@rciummo-linkedin rciummo-linkedin changed the title Adding Entry Point for custom coercion. Adding Entry Point for custom coercion on standard scalars Mar 24, 2023
@bbakerman
Copy link
Member

bbakerman commented Mar 27, 2023

So just some thoughts as I think about this change - I just want to list them but I havent yet drawn conclusions from them per se

  • I understand your need for this static call back hook
    • but its it generally applicable?
  • ValuesResolver et al is @Internal
    • we do this to reduce the API surface area will need to maintain
    • so this makes it more API like - we would not be AS free to change this one you start relying on it
  • Function<Object, Object> preCoercionFunction is anaemic
    • if this got accepted I think it should be a specific class with a FooEnvironment parameter object so it could be extended
  • So far this is a static call to public static CoercedVariables coerceVariableValues()
    • so really the graphql engine will never call this code in its coercing path
    • I think you will double co-erce with this pattern
    • once on the outside with this static call
    • and again on the inside during engine coercing
    • I suspect a static holder of this special hook (one per JVM say) would be better performance value

@rciummo-linkedin
Copy link
Author

rciummo-linkedin commented Mar 29, 2023

So just some thoughts as I think about this change - I just want to list them but I havent yet drawn conclusions from them per se

  • I understand your need for this static call back hook

    • but its it generally applicable?

Well I imagine that if starting from scratch, someone who was dealing with these kind of exceptions to standard coercion would just make their own custom scalars from the start. We are in a bit of a unique circumstance where we can't make this backwards incompatible. However, I can imagine that keeping coercion more strict makes all of the native scalars less useable and adding some flexibility makes them easier to use.

  • ValuesResolver et al is @Internal

    • we do this to reduce the API surface area will need to maintain
    • so this makes it more API like - we would not be AS free to change this one you start relying on it
  • Function<Object, Object> preCoercionFunction is anaemic

    • if this got accepted I think it should be a specific class with a FooEnvironment parameter object so it could be extended
  • So far this is a static call to public static CoercedVariables coerceVariableValues()

    • so really the graphql engine will never call this code in its coercing path
    • I think you will double co-erce with this pattern
    • once on the outside with this static call
    • and again on the inside during engine coercing
    • I suspect a static holder of this special hook (one per JVM say) would be better performance value
  • You are right for graphql-java. In our code we have a custom engine that makes the call to ValuesResolver directly. I agree that it should be in a static holder. Will work on that update.

@dondonz
Copy link
Member

dondonz commented Apr 17, 2023

Hello, FYI @bbakerman is adding a way to modify coercion in #3188

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants