This repo is a work in progress plug for the graphql-erlang project.
As the name implies graphql-erlang is a GraphQL engine written for
the Beam (the Erlang VM). While the Erlang project has not reached
one-point-oh yet it would be interesting to see how this project would
integrate with the Elixir and its ecosystem.
graphql-erlang is and open source project, mainly developed at
ShopGun ApS who runs it in production and sponsors its development.
The graphql-erlang project is freely available and is released under an open source license:
While there are other GraphQL engines in the making for the Elixir ecosystem the graphql-erlang has its place. It takes an alternative approach to defining a GraphQL server that most of the other implementations I have seen, notably it parses a schema file and the programmer is responsible for mapping the objects, «enums», unions, and interfaces to modules defining their behaviour. Essentially the GraphQL engine takes care of the requests, enforcing and validates the data types going in and out of it, the user defines the logic that fulfills the inquiry.
The approach taken by graphql-erlang makes it explicit how many processes are spawned when a query is resolved in parallel because it is the programmer who explicitly spawn processes and reply back to the graphql-engine with a result and a reply token.
Besides the explicitness of process, implementing a resolver relies heavily on pattern-matching. The whole experience is designed to compliment how Erlang works internally. A programmer with a good grasp of the Erlang process model should feel very much at home with graphql-erlang thus preventing the dreaded context switch.
The GraphQL Erlang Tutorial is a small book about the system, and reading it is highly recommended:
As of now I have a plug that initialize a GraphQL schema with bindings. It sets up the build and validation pipelines for both the initialization of the server and the individual requests.
The configuration happens by passing arguments to the plug. Usage can be seen in the project test.
While it is pretty straight forward to setup the compilation steps I have stumbled upon the following challenges.
Feel free to open issues responding to particular challenges by including the headline in the title.
While I think I have a fairly good grasp of Elixir I would like to hear peoples opinion on what a good Elixir integration would look like.
I currently have a Plug, and I would like to be able to add it to a Phoenix route which could handle the GraphQL requests. I guess some macros that setup some good defaults for resolvers could be cool and aid building GraphQL servers in general.
This needs some R&D.
We need to work on better error reporting from the GraphQL engine itself, but the wrapper could perhaps report errors in a format that is better suited for Elixir.
This needs some R&D.
Graphql-erlang uses the atom null to communicate no data. This is
native to both JSON, the GraphQL spec, and quite common in the Erlang
ecosystem. This means the final data-structure returned by GraphQL will
contain :null atoms. This presents us with a problem: the atom :null
is cast to the string "null" in all the Elixir JSON encoders I have
looked at. This is because nil is special in Elixir, and thus is the
one being translated into null—other special atoms are true and false
who will be translated into their corresponding Boolean values.
We could traverse the returned data-structures and replace nils with
:nulls before passing them to one of the JSON encoders, but this
would result in an unnecessary overhead—switching to using the atom
nil in the GraphQL engine instead would present the same problem, only
on the Erlang side. In other words: One must convert.
A more reasonable solution could be to handle :null as a special
case in Poison. This would require one line of code but one would not
be able to encode and decode to the same data structure—I don't know
if this is a requirement for Poison, I would assume converting a
MapSet to JSON and converting it back would result in a different data
structure anyways.
My argument for handling :null -> null as a special case in Poison
is interopability with other Erlang modules. I know of people who have
had to deal with this building CouchDB adaptors and other JSON adaptors
built on top of the Erlang libraries. In short this is not a unique problem.
I have solved the problem by using the jsx JSON encoder, the same
encoder we use at ShopGun, because it convert :null to null in the
resulting JSON. That is why exjsx has been listed as a dependency.
N.b: it would be nice to be able to change the JSON encoder.
This needs a bit of thinking and R&D. I would not like people to create modules called «:Person» for mapping with a «Person»-type in the GraphQL schema.
One thing that could happen as well is to create the mapping table from a naming structure (kinda like a Phoenix router) but I don't like this because it makes the system a bit less transparent.
The project is called GraphqlDeux at the moment. This is because this is my second attempt of creating this.
A better name would be cool; preferably one that makes for a nice logo that would go well on mugs and tshirts. :D