router icon indicating copy to clipboard operation
router copied to clipboard

Implement spec-compliant @cost directive

Open willgittoes opened this issue 7 months ago • 1 comments

Is your feature request related to a problem? Please describe.

I am unable to use the Demand Control feature, because it does not accept the IBM @cost specification.

The page for demand control states that it is "based on" the IBM spec: https://www.apollographql.com/docs/graphos/routing/security/demand-control

But unfortunately the weight parameter is implemented differently. The Apollo version requires an integer, but in the spec it is defined as weight: String!. The spec states that:

All implementations must accept a literal serialized Float.

While I agree it's a bit silly that it's a string in the spec (for some nebulous "it might be a formula one day!" reason), I don't think it would be difficult to implement the spec as it is currently written to only require deserializing a Float. This would happen not during router serving requests, but during schema loading. Linting during schema composition would be when parse errors are surfaced.

Describe the solution you'd like

Implement the IBM spec for the @cost directive.

Ideally we would import the directive from the IBM spec, but even if we had to change the @link directive to import from Apollo, if the types matched it would make things much easier for us. The different GraphQL server libraries we use will automatically insert @cost directives for us at various parts in the schema, so it's not as a simple as us "just importing and using the apollo cost directive" because our explicit uses are dwarfed by the implicit ones. If the types were at least conformant, then we could import the Apollo spec and the auto-generated @cost directives would match up, and could then be successfully composed.

Describe alternatives you've considered

Going to every graphql server implementation we use in each programming language and adding a special "Apollo mode" for cost. Each of those changes would complex since there are often automatic methods of adding cost directives that would need to be intercepted. Each of these changes would reduce our ability to use other tooling that expects spec-compliant cost calculations.

Additional context

Parsing a float from a string in rust takes "tens of nanoseconds" (unless it's a special case, like numbers with 300 digits or more or where the mantissa uses the entire 64 bits), so even in a schema with a million fields and every field has a cost directive with a string that needs to be parsed, it would take ~1/20 of a second to do that (during schema load time, not during request serving). So I think there would be no performance problems from this.

willgittoes avatar Apr 08 '25 00:04 willgittoes

âž•

richmo avatar Apr 08 '25 00:04 richmo