APIs in Scala with
Volodymyr Tsukur
API,
Volodymyr Tsukur
not DB!
Volodymyr Tsukur
R&D Manager,
Lead Engineer @
Partner @
EASYHUNT
Program Committee @
JEEConf, XP Days
flushdia vtsukur
Lithuania
Ukraine
Kyiv
Dnipro
Vilnius
Wix Engineering Locations
Israel
Tel Aviv
Be’er Sheva
120M+ users*
700+ engineers
2100+ employees
600+ microservices
title
price
images
description
info
...
{
}
GET /products/:id
imagesimages(1)
priceprice
titletitle
[
]
description
GET /products
...
info
{
}
10%!
OVER-fetching
01
GET /carts/:id
items [
{
product
quantity
total
}
{
}
]
subTotal
GET /carts/1
GET /products/59eb838e3f
GET /products/59eb88c400
GET /products/59eb838e40
- UNDER-fetching
- extra requests
02
GET /carts/1?projection=with-products
...
GET /carts/1?projection=summary
GET /carts/1?projection=
GET /carts/1?projection=
GET /carts/1?projection=with-products
- no unified & widely adopted
standard :( *
- harder to collaborate :(
03
How to @deprecate and
phase out outdated stuff?
04
2012
2015
“... is a query language for APIs and a runtime for
fulfilling those queries with your existing data”
type User {
name: String
friends: [User]
city: City
}
type City {
name: String
population: Int
citizens: [User]
}
1. Define schema
{
user(name: String): User
...
}
2. Ask for data
user(name: String): User
2. Ask for data
{
user(name: “Vova Unicorn”) {
friends {
name
}
city {
name
population
}
}
}
3. Get it!
{
user(name: “Vova Unicorn”) {
friends {
name
}
city {
name
population
}
}
}
{
“data”: {
“user”: {
“friends”: [
{ “name”: “Lena” },
{ “name”: “Stas” }
]
“city”: {
“name”: “Kyiv”,
“population”: 2928087
}
}
}
}
only necessary data
{
“data”: {
“user”: {
“friends”: [
{ “name”: “Lena” },
{ “name”: “Stas” }
]
“city”: {
“name”: “Kyiv”,
“population”: 2928087
}
}
}
}
{
user(name: “Vova Unicorn”) {
friends {
name
}
city {
name
population
}
}
}
in one request *
{
“data”: {
“user”: {
“friends”: [
{ “name”: “Lena” },
{ “name”: “Stas” }
]
“city”: {
“name”: “Kyiv”,
“population”: 2928087
}
}
}
}
{
user(name: “Vova Unicorn”) {
friends {
name
}
city {
name
population
}
}
}
HTTP POST
let us see how it works!
WYSIWYG
efficient fetching
easier to develop
analytics
any data source and transport
Cart Service
circe
HTTP
Product Service
circe
let us rock and roll!
running query
{
cart(id: 1) {
items {
product {
title
price
images(limit: 1)
sku
}
quantity
total
}
subTotal
}
}
1)
{
cart(id: 1) {
items {
product {
title
price
images(limit: 1)
sku
}
quantity
total
}
subTotal
}
}
2) 1 service call
{
cart(id: 1) {
items {
product {
title
price
images(limit: 1)
sku
}
quantity
total
}
subTotal
}
}
3)
+ n x
product {
title
price
images(limit: 1)
sku
}
product {
title
price
images(limit: 1)
sku
}
GET /products/1
GET /products/2
GET /products/3
e x p e c t a t i o n s
R
e
a
l
i
t
y
{
cart(id: 1) {
items {
product {
title
price
images(limit: 1)
sku
}
quantity
total
}
subTotal
}
}
+
GET /products?ids=1,2,3
let’s fix it!
Security
{
user(name: “Vova Unicorn”) {
friends {
name
friends {
name
friends {
name
friends {
name
...
}
}
}
}
}
}
limit query depth
limit query complexity
let us defend!
throttling / rate limiting
set timeouts
pagination
schema {
query: Query
}
schema {
query: Query,
mutation: Mutation
}
type Mutation {
addProductToCart(cart: ID!,
product: ID!,
count: Int = 1): Cart
}
let us mutate!
+
+
I want it !!!
but let us see the BAD parts
caching
security
error handling
arbitrary resources / file uploads
operation idempotency?
operation naming
hypermedia
Alternatives
https://philsturgeon.uk/api/2017/01/24/graphql-vs-rest-overview/
https://blog.runscope.com/posts/you-might-not-need-graphql
NO !!!
but it shines
as an
integrated
solution
schema {
query: Query,
mutation: Mutation,
subscription: Subscription
}
subscription {
productAdded(cart: 123) {
items {
product ...
}
subTotal
}
}
{
“data”: {
“productAdded”: {
“items”: [
{ “product”: ... },
{ “product”: ... },
{ “product”: ... },
{ “product”: ... }
]
“subTotal”: 289.33
}
}
}
://
{
“data”: {
“productAdded”: {
“items”: [
{ “product”: ... },
{ “product”: ... },
{ “product”: ... },
{ “product”: ... }
]
“subTotal”: 289.33
}
}
}
subscription {
productAdded(cart: 123) {
items {
product ...
}
subTotal
}
}
://
https://github.com/vtsukur/graphql-sangria-online-store
sample, not
production
ready code!
Questions?
volodymyrt@wix.com
flushdia vtsukur

GraphQL APIs in Scala with Sangria