Skip to content

Instantly share code, notes, and snippets.

@adamhjk
Last active January 15, 2020 04:50
Show Gist options
  • Save adamhjk/12923a45633cd548924d5cf8a02e8df0 to your computer and use it in GitHub Desktop.
Save adamhjk/12923a45633cd548924d5cf8a02e8df0 to your computer and use it in GitHub Desktop.
What I mean about graphql
protoPackageName = "si.account"
service.Account.CreateAccount.skipauth = true
service.Account.CreateAccount.mutation = true
service.Account.GetBillingAccount.query = true
service.Account.CreateUser.mutation = true
service.Account.GetUser.query = true
service.Account.ListUsers.query = true
service.Account.ListWorkspaces.query = true
service.Account.ListOrganizations.query = true
message.LoginRequest.skip = true
message.LoginReply.skip = true
message.User.passwordHash.skip = true
[message.User.billingAccountId.has_one]
to = "billingAccount"
grpcServiceName = "Account"
method = "GetBillingAccount"
type = "BillingAccount"
[[message.BillingAccount.id.has_many]]
to = "users"
grpcServiceName = "Account"
method = "ListUsers"
type = "ListUsersReply"
inputType = "ListUsersRequest"
[[message.BillingAccount.id.has_many]]
to = "organizations"
grpcServiceName = "Account"
method = "ListOrganizations"
type = "ListOrganizationsReply"
inputType = "ListOrganizationsRequest"
[message.Organization.billingAccountId.has_one]
to = "billingAccount"
grpcServiceName = "Account"
method = "GetBillingAccount"
type = "BillingAccount"
[[message.Organization.id.has_many]]
to = "workspaces"
grpcServiceName = "Account"
method = "ListWorkspaces"
type = "ListWorkspacesReply"
inputType = "ListWorkspacesRequest"
query getProfile($userId: String!) {
getUser(input: { userId: $userId }) {
user {
id
email
domain
displayName
givenName
familyName
picture
billingAccount {
id
displayName
shortName
organizations {
items {
id
name
workspaces {
items {
id
name
}
nextPageToken
totalCount
}
}
nextPageToken
totalCount
}
}
}
}
}
{
"data": {
"getUser": {
"user": {
"id": "user:afaae8c7-2ade-411a-aa08-ec551cacab95",
"email": "adam@systeminit.com",
"domain": "systeminit.com",
"displayName": "Adam Jacob",
"givenName": "Adam",
"familyName": "Jacob",
"picture": "",
"billingAccount": {
"id": "billing_account:3ca74d69-f23e-4a2e-9668-3e2a8e6acec2",
"displayName": "adam",
"shortName": "adam",
"organizations": {
"items": [
{
"id": "organization:b8f5bac0-dc4b-4ff4-8fb9-bde9aaec0bb8",
"name": "default",
"workspaces": {
"items": [
{
"id": "workspace:2abf3d98-e818-4378-a91a-3d7e1325d6c8",
"name": "default"
}
],
"nextPageToken": "",
"totalCount": 1
}
}
],
"nextPageToken": "",
"totalCount": 1
}
}
}
}
}
}
@adamhjk
Copy link
Author

adamhjk commented Jan 14, 2020

This generates four backend gRPC calls. One to get the user, one to get the billing account, one to list organizations, and one to list workspaces. If there were more organizations and workspaces added, we would fetch those too (and send consequently more backend API calls).

This is glorious, because you would have had to make these calls regardless - if I was doing REST, I would make N calls from the frontend, maybe fuck around with some stateful store a-la redux or vuex. Here, you don't even bother - you just make the call once, cache the data on the client side, and move on. All the "expensive" calls are inside my span of control (in particular with regards to latency), and the graphql server layer is where I can do all kinds of tricks to speed things up if I need to.

It's the same architecture I would have wound up with if I used REST, but standardized (ish), and with guide-rails that neatly drop you into the kind of design that scales well. I'm stoked about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment