Skip to content

GraphQL default schema issues and potential for customisation #5777

Closed
@omairvaiyani

Description

@omairvaiyani

I'd first like to congratulate the core contributors for an excellent job at introducing GraphQL into Parse. It really is a big step forward at keeping the Parse project modern and exciting for new developers.

I can see that the approach has been one of plug-n-play; all types, queries and mutations are automatically generated which means that for many teams, they can swap out many of their existing queries with GraphQL. This is pretty amazing stuff - but it does have inherent tradeoffs. I'll list these concerns out in hopes of some productive discussion to guide future development before the community's usage of the ParseGraphQLServer becomes too reliant on the status quo.

Schema overload

Autogenerating the graph using the entire database schema, and adding all default mutations for each class is like bending GraphQL into an exact map of what Parse already offers. The real power of GraphQL is the ability to generate representations of your database that you would like to make available to your clients, incrementally and evolutionarily. Its an opportunity for enterprises and scaling teams to re-think their schema, and decide what really should be accessed and mutated.

I think an ability to configure the Parse GraphQL server should be introduced that does one or two of the following:

  • Turn the default schema generation off, and instead pass in ones own schema
  • Override specific types/queries/mutations for selected classes
  • Add completely custom types, queries and mutations that do not necessarily tie into the default schema

Now, we don't want to throw the baby out with the bathwater here. There is some impressive coding done here by the contributors around the use of resolvers and mapping of GraphQL query constraints with that of Parse. Careful consideration is needed to maintain these helpful modules whilst allowing developers to extend the ParseGraphQLServer to their specific needs.

Nested mutations lose atomicity

Mutations differ from queries in that they run in series, rather than in parallel. This is to allow atomic mutations. Unfortunately, nesting mutations as is the case with the Parse implementation, loses this synchronous execution and results in tradeoff of atomic mutations.

mutation StockMarketAction {
  // executes first
   incrementStockPrice(ticker: "GOOGL", incrementBy: 1) {
     price
   }
  // waits for the above to complete, then executes
   sellStock(ticker: "GOOGL", numShares: 50) {
     numShares
   }
}

As it currently stands, Parse's GraphQL Schema nests all mutations under objects (and users) like so:

mutation StockMarketAction {
   objects {
      // runs immediately
      updateStock(objectId: "googl", fields: { stockPrice: 50 }) {
        updatedAt
      }
      // runs immediately, above stock price update may not be updated before this order is executed
      createStockOrder(fields: { type: "sell", numShares: "50", stockId: "googl"  }) {
        objectId
      }
   }

}

No obvious location for Cloud Functions

CloudFunctions don't really have a home in mutations as it stands. This means that clients will have to maintain two separate network requests layers should they require full-usage of a parse server API. Whilst we are striving to reduce our reliance of RPC's, there are many instances where an RPC approach is required, and so we'd very much like CloudFunctions to be first-class citizens in ParseGraphQLServer.

--

I was tempted to begin forking and adding PRs to establish some of the above suggestions, but I think it's absolutely critical that some discussion is done before further code is cooked.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:featureNew feature or improvement of existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions