Giter Site home page Giter Site logo

federation's People

Contributors

benjie avatar codef0rmerz avatar dependabot[bot] avatar phryneas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

federation's Issues

Federating two postgraphile endpoints with Apollo Federation results in "Query.query can only be defined once" error with Relay support or "Union type _Entity" error without Relay support

Hello guys,

I'm trying to federate two postgraphile endpoints with the Apollo Federation gateway but can't seem to find a working combination.

Postgraphile with both Federation and Relay support

Given I started the postgraphile endpoints with Federation support (using FederationPlugin) and Relay support (default NodePlugin activated), when I start the Apollo Federation gateway, it complains with the following error:

(node:19865) UnhandledPromiseRejectionWarning: GraphQLSchemaValidationError: Field "Query.query" can only be defined once.

Field "Query.nodeId" can only be defined once.

Field "Query.node" can only be defined once.
    at ApolloGateway.createSchema (/home/cvidal/Documents/Sources/pocs/postgraphile/federation/node_modules/@apollo/gateway/dist/index.js:210:19)
    at ApolloGateway.<anonymous> (/home/cvidal/Documents/Sources/pocs/postgraphile/federation/node_modules/@apollo/gateway/dist/index.js:181:32)
    at Generator.next (<anonymous>)
    at fulfilled (/home/cvidal/Documents/Sources/pocs/postgraphile/federation/node_modules/@apollo/gateway/dist/index.js:5:58)
    at Object.dynatraceRegularInvoke [as doInvoke] (/opt/dynatrace/oneagent/agent/res/nodeagent/nodejsagent.js:1732:20)
    at Object.a.safeInvoke (/opt/dynatrace/oneagent/agent/res/nodeagent/nodejsagent.js:1802:29)
    at /opt/dynatrace/oneagent/agent/res/nodeagent/nodejsagent.js:6952:25
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

I investigated a bit and looking at the Apollo Federation demo here https://github.com/apollographql/federation-demo, the federated services don't expose node and nodeId fields in the Query type.

Postgraphile with Federation support but without Relay support

I therefore tested starting the two postgraphile endpoints without Relay support (skipping the NodePlugin plugin) but the FederationPlugin plugin fails with :

Error: Union type _Entity must define one or more member types.
    at assertValidSchema (/home/cvidal/Documents/Sources/pocs/postgraphile/custom-postgraphile/node_modules/graphql/type/validate.js:71:11)
    at Object.validate (/home/cvidal/Documents/Sources/pocs/postgraphile/custom-postgraphile/node_modules/graphql/validation/validate.js:54:35)
    at parseQuery (/home/cvidal/Documents/Sources/pocs/postgraphile/custom-postgraphile/node_modules/postgraphile/src/postgraphile/http/createPostGraphileHttpRequestHandler.ts:352:32)
    at /home/cvidal/Documents/Sources/pocs/postgraphile/custom-postgraphile/node_modules/postgraphile/src/postgraphile/http/createPostGraphileHttpRequestHandler.ts:690:55
    at Array.map (<anonymous>)
    at requestHandler (/home/cvidal/Documents/Sources/pocs/postgraphile/custom-postgraphile/node_modules/postgraphile/src/postgraphile/http/createPostGraphileHttpRequestHandler.ts:650:20)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

Apparently, this is a known problem in Apollo Federation that Relay is not supported:
https://spectrum.chat/apollo/apollo-federation/federation-with-relays-node-interface~c0ae3cb1-d243-491a-ac58-17307629e31e

Conclusion

So, this problem may be spread between Postgraphile and Apollo Federation Gateway.

That being said, I can't find a working combination so far, with or without Relay support.

Contribution/Maintenance of @graphile/federation

Summary

We are looking at using postgraphile for a new project with part of the decision based on its compatibility with Apollo Federation or the latest GraphQL Tools Schema Stitching. I set up a boiler plate project with postgraphile and a local Apollo server and found that this plugin did not work as expected with the latest versions of federation. I then stumbled on a fork of this repo from last year https://github.com/jarvisuser90/postgraphile-apollo-federation-plugin which got me further but also needed a few changes. I opened a PR to that repo at brooklyn-labs/postgraphile-plugin-apollo-federation#11.

Unfortunately, I don't think the maintainer of the fork as an active user anymore which puts me in an odd place. I would prefer to get those changes, and possibly the diff in the fork, into this repository instead, but I have feeling the fork was created due to changes not being merged here in a timely manner.

Does anyone know the current status of this plugin? Would it be better to fork again and keep things moving or would pull requests to this repo be looked at versus left to go stale?

I would much prefer to keep things here as this feels like this most official place for the plugin to thrive, but I am unsure how the activeness.

Thanks for the information!

[Question] How can I apply federation to resolve sub-objects from another service

Summary

I have two example PostGraphile services: a media service having a movie entity and a video service having a video entity. The movie entity stores the ID of the video. The federation service should allow to query movie->video->title.

Additional context

Using latest PostGraphile in library version and latest version of the graphile/federation library.
I am using the express way to include PostGraphile in the minimal version for each service.
I am following the guide on https://www.apollographql.com/docs/federation/quickstart/ to add both services to the federation service. This works all fine - I can get in one query both the details from the media and video service (but cannot resolve movie --> video --> fields).

Media service

CREATE TABLE public.movies (
  id INT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
  title text NOT NULL,
  description text,
  video_id INT
);

INSERT INTO public.movies (title, description, video_id) VALUES
  ('Avatar', 'Jake, who is paraplegic, replaces his twin on the Na''vi inhabited Pandora for a corporate mission. After the natives accept him as one of their own, he must decide where his loyalties lie.', 1),
  ('Black Widow', 'Natasha Romanoff, aka Black Widow, confronts the darker parts of her ledger when a dangerous conspiracy with ties to her past arises. Pursued by a force that will stop at nothing to bring her down, Natasha must deal with her history as a spy, and the broken relationships left in her wake long before she became an Avenger.', 2),
  ('The Lord of the Rings: The Two Towers', 'Frodo and Sam arrive in Mordor with the help of Gollum. A number of new allies join their former companions to defend Isengard as Saruman launches an assault from his domain.', 3);

Video service

CREATE TABLE public.videos (
  id INT NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
  title text NOT NULL,
  video_url text
);

INSERT INTO public.videos (id, title, video_url) VALUES
  (1, 'Avatar Trailer', 'https://www.youtube.com/watch?v=6ziBFh3V1aM'),
  (2, 'Black Widow Trailer', 'https://www.youtube.com/watch?v=ybji16u608U'),
  (3, 'The Lord of the Rings: The Two Towers Trailer', 'https://www.youtube.com/watch?v=Y4neBR0h39c');

The _entities query is working nicely when I run it directly against the video service.

query videos {
  _entities(representations: [
      {
        __typename: "Video",
        nodeId: "WyJ2aWRlb3MiLDFd"
      }]) {
    ... on Video {
      id
      nodeId
      title
      videoUrl
    }
  }
}

Question

I tried multiple different approaches with makeExtendSchemaPlugin and others - how can I correctly update the Movie entity to have a Video reference?

In the end I (think I) need the following in the generated schema:

type Movie implements Node @key(fields: "nodeId") {
  id: Int!
  title: String!
  description: String

  nodeId: ID!
  videoId: Int

  # this video here - should be resolved via nodeId (or directly the ID if that is possible)
  video: Video
}

extend type Video @key(fields: "nodeId") {
  nodeId: ID! @external
}

My failed attempt with a plugin on the media side:

const { makeExtendSchemaPlugin, gql } = require("graphile-utils");

const ExtendPlugin = makeExtendSchemaPlugin(() => {
  return {
    typeDefs: gql`
      # hack - must be later removed
      type Video {
        DoNotUseThisProperty: String
      }
      # This is how it should really look like - or use the nodeId:
      extend type Video @key(fields: "id") {
        id: Int! @external
      }
      extend type Movie {
        video: Video
      }
    `,
    resolvers: {
      Movie: {
        video: async (movie) => {
          console.log(movie);
          return {
            id: movie.videoId,
          };
        },
      },
    },
  };
});

module.exports = ExtendPlugin;

With the above plugin the video service does not correctly receive any request to resolve the video entity within the video service.

The following query against the federation service would be my goal - the allVideos is working fine and allMovies is working fine if I remove the video sub-object query:

query ExampleQuery {
  allMovies {
    nodes {
      id
      videoId
      title

      video {
        id
        title
        nodeId
      }
    }
  }
  allVideos {
    nodes {
      id
      title
      videoUrl
    }
  }
}

Thanks for any suggestions or ideas.

Couldn't add schema extension plugin extend type of another service

I would like to add a schema extension plugin in this nodejs Postgraphile server to pointing to another type in another GraghQL service. The other service is running with Apollo Server. Then would like to register both GrqphQL with Apollo Gateway.
However, in my plugin:

const { makeExtendSchemaPlugin, gql } = require("graphile-utils");

const SchemaExtensionPlugin = makeExtendSchemaPlugin(build => {
  // Get any helpers we need from `build`
  const { pgSql: sql, inflection } = build;
  return {
      typeDefs: gql`
        extend type Query {
            ThingLinked: [ThingLinkedProduct]
        }

        type ThingLinkedProduct @key(fields: "id") {
            id: Int!
            name: String
            product: Product
        }

        extend type Product @key(fields: "upc") {
            upc: String!    @external
        }
    `,
      resolvers: {...}
  };
});
  
export default SchemaExtensionPlugin;

Error:

Error: Could not find type named 'Product'.
    at getType (C:\Workspace\EMCP\node_modules\graphile-utils\src\makeExtendSchemaPlugin.ts:516:15)
    at C:\Workspace\EMCP\node_modules\graphile-utils\src\makeExtendSchemaPlugin.ts:755:24

I even tried to add Apollo's buildFederatedSchema API in this extension, got different error.

Is this feature supported?

I'm able to add 'extend type' the other way around. Added 'extend type' from here to the other Apollo Server GraphQL, and Apollo gateway can query this one using nodeId

Federation not working

Using types from other service just does not work. I can't define external derectives properly, and get errors about must being used with @requires, @provides, or as a key type. I cannot get it to work. Let me link you to the thread of discussion

https://spectrum.chat/apollo/apollo-federation/federation-query-inside-mutation~3c9cca0e-9a82-4738-8f9f-5d9de0c3876d

and the discussion on graphile discord which resulted in no solution:

I have a question about how federation is supposed to work. I have postgraphile setup and working and can see my schema. Now in another service i want to have a mutation that returns one of the types made from the postgraphile service. Let's call this type 'User' and the user has some nested fields one of which is 'UUID'. When i try to reference this type apollo complains about unknown type. The only way i can fix this is if i extend the type and basically redefine every field and add @key and @external directives. This seems pointless to use federation if i have to redefine the types i want to share in every new service?? What am i misunderstanding?

extend type User @key(fields: "nodeId") { 
    id: UUID! @external 
    name: String! @external 
    position: String! @external} 

this is the type i want to share. I extend it like that in the service i want to use it from, but it's made by postgraphile itself
i'm trying to use it like this 

 
type Mutation { doaThing(blah: String) : User @external } 

Add @key as primary key fields instead of nodeId

When using Graphile federated with another service, it seems to make more sense for the key to be on the primary keys of the resource instead of the nodeId. This is because any other resource would be likely to have access to the resource by its primary keys.

This can be worked around by adding @requires(fields: {primary keys}) to each other field and fetching by the keys in __resolveReference but this seemed like a bad solution.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.