Wir stellen unsere Erfahrung vor, die wir in 15 Monaten Einsatz von Elixir und GraphQL in Produktion nach Relaunch eines großen
Jobanzeigenportals gesammelt haben.
Elixir bietet uns die Möglichkeit, ein hoch verfügbares Backend mit extrem geringen Antwortzeiten zu entwickeln. Dieses wird über eine GraphQL Schnittstelle von mehreren Frontends genutzt.
Elixir ist eine junge, funktionale Programmiersprache, die 2011 vorgestellt wurde. Jedoch setzt sie auf dem Erlang Ökosystem auf, welches in über 32 Jahren eine extrem stabile Basis zur Entwicklung von Anwendungen geworden ist.
Ein häufiger Anwendungsfall von Elixir sind Echtzeitapplikationen, zum Beispiel Chatanwendungen, Bots und IoT-Anwendungen. In Verbindung mit GraphQL Subscriptions ist es einfach möglich, Clients über Statusaktualisierungen vom Server zu Informieren. Wir zeigen, wofür man Elixir einsetzen kann, wie GraphQL einen leichten Einstieg in Datenexploration anbietet und wieso beide zusammen eine Überlegung wert sind.
5. „GraphQL is a query language designed to build
client applications by providing an intuitive and
flexible syntax and system for describing their data
requirements and interactions.“
GraphQL Spec — https://facebook.github.io/graphql/
15. Elixir
current_process = self()
# Spawn an Elixir process (not an operating system one!)
spawn_link(fn ->
send current_process, {:msg, "hello world"}
end)
# Block until the message is received
receive do
{:msg, contents} -> IO.puts contents
end
17. Absinthe Schema schreiben
$ vi lib/disruption_web/schema.ex
defmodule DisruptionWeb.Schema do
use Absinthe.Schema
query do
field :post, type: :post do
arg :id, non_null(:integer)
end
end
end
query {
post(id: 42) {
title
comments {
text
author {
name
}
}
}
}
18. defmodule DisruptionWeb.Schema do
use Absinthe.Schema
query do
field :post, type: :post do
arg :id, non_null(:integer)
end
end
object :post do
field :title, :string
field :author, :author
field :published_date, :datetime
field :comments, list_of(:comment)
end
object :author do
field :name, :string
field :email, :string
end
object :comment do
field :text, :string
field :author, :author
end
19.
20. defmodule DisruptionWeb.Schema do
use Absinthe.Schema
query do
field :post, type: :post do
arg :id, non_null(:id)
resolve fn args, _context ->
Api.post_by_id(args[:id])
end
end
end
object :post do
field :title, :string
field :author, :author
field :published_date, :datetime
field :comments, list_of(:comment) do
resolve fn post, _args, _context ->
post
|> Map.get(:id)
|> Api.comments_for_post()
end
end
end
21. defmodule DisruptionWeb.Schema do
use Absinthe.Schema
query do
field :post, type: :post do
arg :id, non_null(:id)
resolve fn args, _context ->
Api.post_by_id(args[:id])
end
end
end
object :post do
field :title, :string
field :author, :author
field :published_date, :datetime
field :comments, list_of(:comment) do
resolve fn %{id: id}, _, _ ->
Api.comments_for_post(id)
end
end
end
22.
23. defmodule DisruptionWeb.Schema do
use Absinthe.Schema
object :message do
field :name, :string
field :text, :string
field :room, :string
end
mutation do
field :send_message, :message do
arg :room, non_null(:string)
arg :name, non_null(:string)
arg :text, non_null(:string)
resolve fn args, _ ->
{:ok, args}
end
end
end
subscription do
field :messages, list_of(:message) do
arg :room, non_null(:string)
trigger :send_message,
topic: fn msg -> msg.room end
config fn args, _ ->
{:ok, topic: args.room}
end
end
end
24.
25. defmodule DisruptionWeb.Schema do
use Absinthe.Schema
object :message do
field :name, :string
field :text, :string
field :room, :string
end
input_object :msg_params do
field :room, non_null(:string)
field :name, non_null(:string)
field :text, non_null(:string)
end
mutation do
field :send_message, :message do
arg :message, non_null(:msg_params)
resolve fn args, _ -> {:ok, args} end
end
end
26. mutation do
field :send_message, :message do
arg :message, non_null(:msg_params)
resolve fn msg, _ ->
Absinthe.Subscription.publish(Endpoint, msg, messages: msg.room)
{:ok, args}
end
end
end
30. Learning: Mapping von Schema zu Business Logic
Resolver so dumm wie möglich, so schlau wie nö@g
Schema als Konsolidierung und Validierung
Use-Case-oriented / Product-centric
31. Learning: Scaling & Performance
Zwei GraphQL Pods für drei Portale
Subresolver für teure Opera@onen
Asynchrones Resolving nutzen
32. Learning: GraphQL Sprach Features & Tooling
Keine Union Types für Input Objects
GraphQL Tracing und Caching (z.B. Apollo Engine)
Öffentliches Schema ist öffentlich