graphql

2021-07-28T06:21:00.058600Z

We use lacinia with the component library and reloaded workflow. We have a component for pedestal and one for the schema-provider. It has been great so far but the component has a lot of dependencies (> 150) which makes reloading slow when one of the resolvers is changed. Any tips on how to improve this?

2021-07-28T06:22:34.061100Z

I am aware that lacinia can resolve vars when they’re passed (to skip compiling the schema on each reset), but in my testing this shaved 2 seconds off, the biggest factor seems to be reloading the files

vemv 2021-07-30T14:32:20.005900Z

if the bottleneck is code reloading itself (as opposed to starting/stopping) you might benefit from parallelisation I've used a WIP parallel impl of refresh for the whole year, it works nice enough that I can forget about it But I should fix/test a couple things before sharing it

vemv 2021-07-30T14:34:54.006100Z

Other than that, another line of research is inspecting the "dependency paths" (from ns1 to ns2) and verifying if they make sense If it doesn't make sense to refresh/reset ns2 ns/component whenever ns1 changes, you might have an architectural problem at the same time, the whole Reloaded workflow is very pessimistic when it comes to consider x a dependency of y. So it's not rare at all to end up "reloading the world" whenever something changes

2021-07-30T15:45:21.006300Z

Yeah it's strictly reloading; the reset takes 1-2 seconds longer than a similar refresh. The dependencies all "make sense", or at least, i think they do 😬. Currently all types that need resolvers have their own namespaces. They are not inter-connected at all. Except that the graphql-component which provides the schema needs a reference to all those resolvers. Which means that if a resolver changes, the change propegates to graphql-component -> all other resolvers. I made a POC which requires all resolvers lazily in the graphql-component, which 'fixes' the reload-behaviour; but requires a lookup/reload of the resolver before resolving the schema in development (which has it's own downsides)

👀 1
vemv 2021-07-30T16:50:59.007400Z

I might be a little dense today but the problem might be less obvious than we think

vemv 2021-07-30T16:51:10.007600Z

vemv 2021-07-30T16:51:39.008Z

under this scenario if resolver1 changes, the component ns should be resolved, and the user ns too

vemv 2021-07-30T16:52:20.008200Z

but that should be it, right? i.e. resolver2 has no reason to be reloaded unless there's something like a reference in the other direction, such that resolver2 depends (directly or not) on the graphql component

vemv 2021-07-30T16:54:03.008500Z

it can be good to try determining this sort of unnecessary dependencies. Sometimes they happen due to bad modularization

vemv 2021-07-30T17:01:15.008800Z

I checked just now, and when I change resolver1 at my work codebase, none of the other resolvers get refreshed. That's good 👍 -test namespaces from disparate resolvers get refreshed though. That's because they all depend on a central system ns which depends on graphql and then on resolver1 . That also makes sense, it's a good use case for parallelization (because normally nothing depends on -test namespaces)

2021-07-30T17:35:47.010800Z

Hmmm, i thought that resolver2 would be refreshed because it's a dependency of the graphql.component; but maybe there's another reason why it's reloaded. I'll have to do some more experimenting. Thanks for thinking along!

👍 1
2021-07-30T18:10:07.011100Z

❤️ Thanks for that direction. It was indeed our text-fixture's depenency on the system, that made it circular and load every resolver as a result. Now I'll take a look if I can fix that hammock

🍻 1
2021-07-30T19:05:59.011500Z

Success , we had a fixture which'd built the system, which is now defered until runtime of the test instead of compile time, which speeds up loading the test, and also fixes the need of the compile-time dependency. Thanks again!

vemv 2021-07-30T19:06:30.011800Z

🙌 very happy to hear!

vemv 2021-07-30T19:07:12.012Z

it would be interesting to lint for cycles 👀 circular dependencies are already forbidden by t.n itself, but as we saw here, there are non-critical cycles that can get big without one noticing

➕ 1
2021-07-30T19:27:45.013400Z

It has been a bother for a while, obviously growing over time. Pinpointing was a bit of a headscratcher tho. Maybe a linter could've helped here

2021-07-30T19:27:59.014Z

But the namespace with 150 requires should've been a sign

😅 1
eraserhd 2021-07-28T18:40:27.062200Z

Does Lacinia have a way of generating GraphQL schema? My org wants it for registering with backstage.

eraserhd 2021-07-30T13:21:50.003600Z

why forbid those?

hlship 2021-08-01T16:32:52.014300Z

They’re kind of ambiguous, you end up having to fold them into the Query object (etc.); of course, if you work off the compiled schema, that’s already handled.

eraserhd 2021-07-28T18:45:53.062300Z

Specifically, I mean GraphQL SDL.

gklijs 2021-07-28T18:57:40.062500Z

No, but since it's just Clojure/EDN I think it's easy to create one based on something. Guess introspec PostgreSQL and create the schema and resolvers based on that should be doable. I know with Kotlin it can be done with annotations on functions, but in that case they are fully typed. Maybe something with spec could also work.

eraserhd 2021-07-28T19:03:33.062700Z

Yeah, it's easy, and it definitely looks like it isn't present yet. I'll make a PR.

eraserhd 2021-07-28T19:08:34.062900Z

Proposal: com.walmartlabs.lacinia.schema/graphql-sdl or com.walmartlabs.lacinia.schema/graphql-sdl-text.

orestis 2021-07-29T06:19:22.063100Z

We have used a 3rd-party tool, pointing it to our /graphql http endpoint, and it generated the schema for us. I don't recall the name, we ended up not needing it.

2021-07-29T08:47:16.063300Z

We have also worked around this with a tool that gets the schema from the API endpoint (via the IntrospectionQuery, the same way that GraphiQL loads the schema). Its “good enough” for us and not too much overhead because the development server is always running a we have simple shell script to dump the schema. I can provide details/pointers if anybody want to implement the same workaround.

eraserhd 2021-07-29T13:30:25.063500Z

I was pointed to an npm package that does this, and am considering it. It's possible to boot the system in CI and fail the build if the user did not commit any required updates to the schema file, and wrap this node package. But this makes development more awkward.

eraserhd 2021-07-29T13:31:07.063700Z

Our schema is largely auto-generated from a data dictionary in the first place.

hlship 2021-07-29T21:06:07.066300Z

I started to work on this at one point, but determined that for Walmart’s needs, starting with an SDL document (rather than generating one from EDN) worked better in the overall picture. It would still be a valuable addition to be able to easily convert back from EDN to SDL.

hlship 2021-07-29T21:06:34.066500Z

It would probably be OK to forbid the use of :queries, :mutations, or :subscriptions keys in the EDN schema.