https://serverless-stack.com/ logo
#random
Title
# random
t

thdxr

10/30/2021, 4:10 PM
Is anyone in here super experienced with gql?
a

Adrián Mouly

10/30/2021, 7:26 PM
I was until figured it was hard to use with ORM.
o

Omi Chowdhury

10/30/2021, 7:50 PM
Like GraphQL in general? Or the
graphql-tag
lib?
t

thdxr

10/30/2021, 8:11 PM
in general
o

Omi Chowdhury

10/30/2021, 8:13 PM
Fragment’s public API is graphql, learnt a bunch of stuff implementing it and running it at scale
t

thdxr

10/30/2021, 8:14 PM
Been trying to get an answer to this: https://github.com/FormidableLabs/urql/discussions/2055
o

Omi Chowdhury

10/30/2021, 8:16 PM
So in my API I expose the equivalent of authorId and author - which then lets me handle those two cases differently
t

thdxr

10/30/2021, 8:17 PM
for my usecase I'm heavily using a normalized cache on the frontend, it'll see those as 2 different things right
o

Omi Chowdhury

10/30/2021, 8:17 PM
yeah
Also there’s logic that means if you only query author.id it doesn’t actually go fetch the author
t

thdxr

10/30/2021, 8:18 PM
yeah I don't want to allow clients to query all the authors details when listing posts
o

Omi Chowdhury

10/30/2021, 8:18 PM
because of perf or security?
t

thdxr

10/30/2021, 8:18 PM
Performance
this is a contrived example
maybe I just want to limit it to
id
and
name
. And the only way I can find to do that is by creating a different type for it. But then it confuses my clientside cache because it doesn't know TinyAuthor and Author are the same thing unless I setup a bunch of mapping
And then to go further, maybe I don't want clients listing all 100 fields in post when listing posts and restrict them to just 10 of them. Now I have TinyPost and Post too. Feels really inelegant
o

Omi Chowdhury

10/30/2021, 8:20 PM
yeah I err of the side of giving my clients as much flexibility as I can give them - if they want that data, and I don
t

thdxr

10/30/2021, 8:21 PM
in my case Post and Author are in 2 different data sources so I can't easily join them
o

Omi Chowdhury

10/30/2021, 8:21 PM
don’t let them get it, they’ll just make more API calls anyway - so best to get the full query they want, and optimise things to make that work
t

thdxr

10/30/2021, 8:22 PM
I guess I can leave it as the full data type and appsync will just error if they ask for fields I haven't implemented a way to resolve
o

Omi Chowdhury

10/30/2021, 8:23 PM
yeah I have a few different data sources (search index, dynamo, qldb). But doing it as one big query is more efficient than many smaller ones as things like authorisation checks can be cached
On your thing - I don’t think there’s a way around having two different types. You could implement the server to check the parent type and return things differently, but that would poison your cache. I don’t think introducing a union type of TinyPost | Post helps either
t

thdxr

10/30/2021, 8:25 PM
Yeah I guess I have to lean towards what's simplest for the client to understand
cool thanks
o

Omi Chowdhury

10/30/2021, 8:27 PM
You could just reject queries with too much complexity - so instead of returning nulls for properties you don’t want to fetch, you explicitly error out and return null for author
t

thdxr

10/30/2021, 8:28 PM
Yeah that's what I'm doing currently
makes sense
I know people love gql and I'm trying to be open minded but it feels really inelegant in a lot of places coming from jsonapi
o

Omi Chowdhury

10/30/2021, 8:31 PM
I think there’s a big philosophical shift between those styles from server is king to client is king
t

thdxr

10/30/2021, 8:33 PM
jsonapi operates client first as well. It just felt like a more elegant implementation of all the same concepts and you can see it in the client libraries (eg orbit) since they tend to be way more simple all while supporting the same advanced features
o

Omi Chowdhury

10/30/2021, 8:39 PM
I built an API like that before (I remember it being called HATEOS back then, not sure what relation that has with jsonapi) - but we had to invent stuff on top of it to get some of the same features as graphql (e.g. fetching multiple levels deeper into the graph in one network request, serving schemas alongside the data to autogenerate UI)
It became a big pain to implement things authorisation and send get requests like
/users/34?expansions=department.name,department,manager.name,manager.id,manager.department.id,manager.department.id
was a bad DX
t

thdxr

10/30/2021, 8:44 PM
Well raw gql over the wire looks just as ugly - it's not as much a problem if you have good clients typed to build it + receive it
o

Omi Chowdhury

10/30/2021, 8:46 PM
Yeah those didn’t exist at the time, we can ran into issues where get requests got too long, had to implement our own normalised cache - and web server frameworks weren’t designed for those use cases
t

thdxr

10/30/2021, 8:47 PM
Yeah ultimately what we're trying to do is complex so can't get rid of that
btw I noticed fragment's public api is in gql. Your customers are probably more savvy but have you had any pushback on that from people looking for a normal rest api?
o

Omi Chowdhury

10/30/2021, 8:47 PM
One thing that is fundamentally different is mutations vs state changes for updates
I go back and forth on it, where CRUD works much better on jsonapi, but if you need to invent new nouns to represent more complex updates. Like we had a use case where the API to terminate an employee needed extra info sent in. The basic update would be
{status: 'terminated'}
but we also needed to send
{moveDirectReportsTo: 'some other user'}
t

thdxr

10/30/2021, 8:53 PM
Yeah you usually end up having to create another resource for that which you're "creating"
o

Omi Chowdhury

10/30/2021, 8:54 PM
Right - UserTerminationFlow - which ends up being practically being same as gql with terminateUser(), and the fact that the users status changed is implicit in both
t

thdxr

10/30/2021, 8:55 PM
yeah
I guess I was hoping given how much gql ripped up, all the tooling required, and the fact they were starting ground up that all this would feel better to use. Maybe I need to get more practiced with it
o

Omi Chowdhury

10/30/2021, 8:59 PM
More than anything having standardised tooling, nomenclature and APIs across different APIs, and having all these problems solved - with batteries built-in - is the biggest benefit. That there is one approach to solving this class of problems, that historically REST and the tooling around it never took a strong opinion on
My API would be far harder to understand and use if it was a REST API - because the tooling isn’t as good. Would be interesting to see what the REST version of this API call would look like:
Copy code
query GetBalanceSheet ($ledgerId: ID!, $filter: LedgerAccountFilter) {
  ledger(id: $ledgerId) {
    ledgerAccounts(filter: $filter) {
      nodes {
        id
        name
        type
        end_of_year: balance(at: "2021")
        end_of_month: balance(at: "2021-06")
        end_of_day: balance(at: "2021-06-15")
        end_of_hour: balance(at: "2021-06-15T06")
      }
    }
  }
}
Copy code
{
  "ledgerId": "some-ledger-id",
  "filter": {
    "type": {
      "in": [
        "asset",
        "liability"
      ]
    }
  }
}
Your customers are probably more savvy but have you had any pushback on that from people looking for a normal rest api?
Not really, initially most people are indifferent or “cool!” - and then they become converts once they setup code-generated SDKs and start creating API calls like the above
d

Damjan

11/01/2021, 12:39 PM
What you are trying to do is completely incompatible with GraphQL :) But there’s nothing preventing you from having caching for the entire graphql api and in the server as well, so not sure it’s really a problem. Assuming data only changes via mutations, it’s also easy to know when and what to cache bust