Package: graphene-federation
graphene-federationFederation support forGraphenefollowing theApollo Federation specifications.This repository is heavily based on the repo it was forked from... Huge thanks toPreply for setting up the foundations.WARNING: This version is not compatible withgrapheneversion below v3.
If you need to use a version compatible withgraphenev2 I recommend using the version 1.0.0 ofgraphene_federation.Supported FeaturesAt the moment it supports:sdl(_serviceon field): enable to add schema in federation (as is)@keydecorator (entity support): enable to perform queries across service boundaries (you can have more than one key per type)@extend: extend remote typesexternal(): mark a field as externalrequires(): mark that field resolver requires other fields to be pre-fetchedprovides()/@provides: annotate the expected returned fieldset from a field on a base type that is guaranteed to be selectable by the gateway.Each type which is decorated with@keyor@extendis added to the_Entityunion.
The__resolve_referencemethodcan be defined for each type that is an entity.
Note that since the notation with double underscores can be problematic in Python for model inheritance this resolver method can also be named_resolve_reference(the__resolve_referencemethod will take precedence if both are declared).This method is called whenever an entity is requested as part of the fulfilling a query plan.
If not explicitly defined, the default resolver is used.
The default resolver just creates instance of type with passed fieldset as kwargs, seeentity.get_entity_queryfor more detailsYou should define__resolve_reference, if you need to extract object before passing it to fields resolvers (example:FileNode)You should not define__resolve_reference, if fields resolvers need only data passed in fieldset (example:FunnyText)
Read more inofficial documentation.ExampleHere is an example of implementation based on theApollo Federation introduction example.
It implements a federation schema for a basic e-commerce application over three services: accounts, products, reviews.AccountsFirst add an account service that expose aUsertype that can then be referenced in other services by itsidfield:fromgrapheneimportField,ID,ObjectType,Stringfromgraphene_federationimportbuild_schema,key@key("id")classUser(ObjectType):id=Int(required=True)username=String(required=True)def__resolve_reference(self,info,**kwargs):"""Here we resolve the reference of the user entity referenced by its `id` field."""returnUser(id=self.id,email=f"user_{self.id}@mail.com")classQuery(ObjectType):me=Field(User)schema=build_schema(query=Query)ProductThe product service exposes aProducttype that can be used by other services via theupcfield:fromgrapheneimportArgument,ID,Int,List,ObjectType,Stringfromgraphene_federationimportbuild_schema,key@key("upc")classProduct(ObjectType):upc=String(required=True)name=String(required=True)price=Int()def__resolve_reference(self,info,**kwargs):"""Here we resolve the reference of the product entity referenced by its `upc` field."""returnProduct(upc=self.upc,name=f"product{self.upc}")classQuery(ObjectType):topProducts=List(Product,first=Argument(Int,default_value=5))schema=build_schema(query=Query)ReviewsThe reviews service exposes aReviewtype which has a link to both theUserandProducttypes.
It also has the ability to provide the username of theUser.
On top of that it adds to theUser/Producttypes (that are both defined in other services) the ability to get their reviews.fromgrapheneimportField,ID,Int,List,ObjectType,Stringfromgraphene_federationimportbuild_schema,extend,external,provides@extend("id")classUser(ObjectType):id=external(Int(required=True))reviews=List(lambda:Review)defresolve_reviews(self,info,*args,**kwargs):"""Get all the reviews of a given user. (not implemented here)"""return[]@extend("upc")classProduct(ObjectType):upc=external(String(required=True))reviews=List(lambda:Review)# Note that both the base type and the field need to be decorated with `provides` (on the field itself you need to specify which fields get provided).@providesclassReview(ObjectType):body=String()author=provides(Field(User),fields="username")product=Field(Product)classQuery(ObjectType):review=Field(Review)schema=build_schema(query=Query)FederationNote that each schema declaration for the services is a valid graphql schema (it only adds the_Entityand_Servicetypes).
The best way to check that the decorator are set correctly is to request the service sdl:fromgraphqlimportgraphqlquery="""query {_service {sdl}}"""result=graphql(schema,query)print(result.data["_service"]["sdl"])Those can then be used in a federated schema.You can find more examples in the unit / integration tests andexamples folder.There is also a coolexampleof integration with Mongoengine.Known issuesdecorators will not work properly on fields with custom names for examplesome_field = String(name='another_name')ContributingYou can run the unit tests by doing:make tests.You can run the integration tests by doingmake integration-build && make integration-test.You can get a development environment (on a Docker container) withmake dev-setup.You should useblackto format your code.The tests are automatically run on Travis CI on push to GitHub.