strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations πŸ“
https://strawberry.rocks
MIT License
3.92k stars 516 forks source link

Support explicit setting of federation version #3503

Open bradleyoesch opened 3 months ago

bradleyoesch commented 3 months ago

Feature Request Type

Description

The latest version of strawberry supports federation v2.7 and hardcodes the directive urls as such: https://github.com/strawberry-graphql/strawberry/pull/3420

The apollo federation version at my company is v2.5 so I've updated our schema generator to manually replace v2.7 with v2.5

It would be nice to be able to set this at the schema level, e.g. federation.Schema(query=Query, federation_version="v2.5")

At first glance it seems relatively straightforward:

  1. Add federation_version argument to the schema, default to "v2.7" if enable_federation_2=True
  2. Set enable_federation_2=True if federation_version >= 2
  3. Update schema urls with the version so the schema generator writes that version

But I imagine that the versioning actually changes underlying support, so then there are outstanding questions:

Not sure what the approach should be, but I don't think this library should dictate the federation version, and more explicitly, I think that users of this library should be able to get library updates unrelated to federation version, rather than having to pin to the version before some federation version was explicitly supported / mandated.

Upvote & Fund

Fund with Polar

erikwrede commented 3 months ago

Hey @bradleyoesch! Thank you for bringing this up. It's a valid concern and something we should indeed think about carefully to ensure Strawberry remains flexible and user-friendly, especially when it comes to dealing with different federation versions. Your input is greatly appreciated! 😊

Regarding your suggestions and questions, let's dive a bit deeper:

Would it be preferable to overwrite the print_schema function with version instead?

I would lean against this. Having this functionality as a core feature is essential. Overriding such functions could lead to unnecessary complexity and potentially unexpected behaviors. It's better to handle versioning more intrinsically within the framework.

Would we support old federation versions and new ones?

This is a tricky one. Ideally, we aim to provide forward compatibility with newer versions of federation while also offering a degree of backward compatibility. However, supporting every version past and future indefinitely isn't feasible due mainly to the maintenance overhead and potential limitations it imposes on evolving Strawberry's schema handling.

Would we have to validate the version number against what features are supported?

Implementing some form of version validation sounds like a prudent approach. This could help prevent confusion and errors by ensuring that the features being used are compatible with the specified federation version. Of course, the challenge here is to determine the most effective and user-friendly way to implement such checks.

Would we just trust the user that they know which features are available if they're setting the version explicitly?

Rover or other composition tools should fail composition if some versions are incompatible.

Given these considerations, here's what I believe could be a balanced approach:

There is one catch with the last variant though: we still don't support every version of federation for new releases. From time to time, a strawberry upgrade will require upgrading to the very newest federation version because the federation library had to be updated to accompany the newest strawberry breaking changes. This is an acceptable trade off in my opinion and is in line with common deprecation practices.

If anyone has further thoughts or suggestions, please don't hesitate to share. I'm all ears! πŸ“

patrick91 commented 3 months ago

The apollo federation version at my company is v2.5 so I've updated our schema generator to manually replace v2.7 with v2.5

@bradleyoesch I'm assuming you were getting errors because you're on older version of the router?

I think we can allow to specify the version (maybe using a Literal, so we only allow versions we know we support[1]), but it would be nice to also add validation if you're using newer features in older versions (as @erikwrede suggested)

Consider a separate federation library

@erikwrede not sure I understood this point 😊

[1] at least at a "type checking" level

erikwrede commented 3 months ago

@patrick91 I meant publishing a separate package called strawberry-federation, with each package version corresponding to an apollo federation version.

bradleyoesch commented 1 month ago

@erikwrede

  • Default to supporting the latest federation version, while also allowing specific version targeting This could be achieved by introducing a federation_version argument, as you suggested. It would just change the version numbers in the schema but not have any further effect for now. This way, we address immediate compatibility concerns without overcommitting to extensive multi-version support.

If it's just to change the version numbers in the schema then imo just let users override it themselves, since it's not real functionality.

  • Version Validation Implementing a simple check against known features and directives for each federation version could help users steer clear of using unsupported features. This would add a layer of complexity but could improve usability and error handling. However, I am concerned about the maintainability of this approach in the long run

Yeah I'm concerned with that too. There'd probably have to be a running list of supported versions and a threshold where old ones get dropped off. I'm not too familiar with the differences in federation versions and how frequently they release, so I'm not sure how much of a lift that would be.

  • Consider a separate federation library Federation support mostly builds on somewhat stable Strawberry internals. They are unlikely to change fundamentally very frequently. One federation lib version could be compatible with multiple strawberry versions. We should however consider using a monorepo so we never forget to immediately release new federation versions in case we do make breaking changes.

Sounds interesting, and could address the "running list of supported versions" and at least document it well.

Wish I had a stronger opinion at the moment to help direct ideas!