Coder Social home page Coder Social logo

Dynamic schema about async-graphql HOT 36 CLOSED

async-graphql avatar async-graphql commented on April 29, 2024 4
Dynamic schema

from async-graphql.

Comments (36)

sunli829 avatar sunli829 commented on April 29, 2024 4

I'm working on this, it's going well, and a preview will be released this week. πŸ™‚

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024 4

I opened a PR to track progress.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024 2

I think we should probably add an execution phase validator called Guard.

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024 1

Yep, dynamic schema would definitely be something of interest.
I'm currently building a "hacky" way to do this as it's not properly supported anywhere, for example in my project I need to have

RecordType {
...
schema: JSONMap
}

and Record {
recordTypeId: ..
data: JSONMap (this data is being validated using a json schema from RecordType)
}

And I'd like to support some sort of querying by these dynamic fields. At the moment I'm looking at custom implementation for this as this is tricky and not really supported by the graphql spec, considering that in the example above each RecordType might have a different schema.

But, getting back to reality - it would be nice to support dynamic schema!

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024 1

I think we should probably add an execution phase validator called Guard.

Yeah, that would be awesome.

If you need a context, the Validator can't do that right now, because it's in the query validation phase, and it hasn't created a context yet.😁

Yeah, I have figured as much.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024 1

Thank you, that gave me some inspiration, and I'm working on that right now.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024 1

One important feature I overlooked is that guard can be applied to the SimpleObject.

from async-graphql.

chipsenkbeil avatar chipsenkbeil commented on April 29, 2024 1

@sunli829, what became of this issue? I wasn't able to follow along properly to understand if this was implemented. There was mention of passing new schemas to validators and not having a context available. Then there was discussion about a guard and it looks like that was implemented, although I don't recall seeing guards mentioned in the book.

A use case I have in mind is enabling users of vimwiki-server to define custom logic that can leverage the data models I've built for the vimwiki language and respond to some custom query using an embedded language like Lua that connects to the Rust server.

My only thought right now without some way to define a custom schema alongside my static schema is through some general-purpose query:

{
    lua_query(key: "some identifier", input: "some input") {
        key
        output
    }
}

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024 1

Am I right in thinking that dynamic schemas would also be needed to implement an Apollo Gateway replacement in rust?

Yes, you are absolutely correct. 😁

from async-graphql.

Visic avatar Visic commented on April 29, 2024 1

Dynamic schemas would be a big win for my production work. I have/am developing a system for the company I work for which allows us to add/remove/change our systems behavior at runtime using a series of configuration files, part of which is being able to manipulate our webserver/graphql interface. Right now I have to use a super generic interface that works for all situations but isn't ideal due to how vague it is.

from async-graphql.

aschaeffer avatar aschaeffer commented on April 29, 2024 1

@Bjohnson131 Please take a look at https://github.com/apollographql/apollo-rs

Currently, if you want to implement a dynamic schema, you have to implement it by yourself. Use apollo-encoder to generate a schema SDL and apollo-parser to parse GraphQL requests.

from async-graphql.

nicolaiunrein avatar nicolaiunrein commented on April 29, 2024

I’m relatively new to GraphQL and haven’t encountered dynamic schemas. Could you provide a link? Or an example use-case?

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

https://github.com/graphql-go/graphql

Like this, allows change schema at run time.
Not code generation, no type safety, and poor performance.

from async-graphql.

nicolaiunrein avatar nicolaiunrein commented on April 29, 2024

Alright so here is a somewhat incomplete and unordered list of thoughts:

Cons

  • The effort of implementing it.
  • People might choose a not ideal implementation for their problem because they are unaware of the cost.

Pros

  • The task of handling dynamic schemas is expensive in every language and I would always prefer to implement an inefficient task in a fast language than in a slow one.

  • dynamic schemas in rust would still outperform implementations in most other languages + give you still a decent amount of typesafety which is important because you might have no control over the schemas you are serving.

  • Can be handy for rapid prototyping.

  • Not every project needs top performance.

  • Sometimes usability is key. Eg. a service implementing a graphql endpoint for maintenance or admins etc.

  • If implementing dynamic schemas means decoupling the logic from the codegen then you get even more benefits. It becomes easier to

    • add new features like flatten fields for example.

    • add new crates like an async-graphql-client which depends on the same core types.

  • I would:

    • prepare the codebase by extracting the core functionality.

    • implement it on top of the core.

    • make it a feature which is disabled by default.

    • clearly state in the docs that static schemas. are to be preferred over dynamic schemas where ever possible.

    • Show benchmarks of dynamic vs static.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

I tried it out yesterday, but it didn't workπŸ˜‚, and I'm still thinking about a better way to do it. The main reason is that rust does not support generic specialization, solving the problem with newtype makes the library particularly verbose to use.

from async-graphql.

nicolaiunrein avatar nicolaiunrein commented on April 29, 2024

I will definitely πŸŽ‰ when specialization lands on stable rust.

from async-graphql.

nicolaiunrein avatar nicolaiunrein commented on April 29, 2024

Have you looked at the Syllogism crate for specialization?

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

Thank you for telling me about Syllogism crate. I'll see if it works for me. 😁

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

Validation the JSONMap you could try async_graphql::InputValueValidator.

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

@sunli829 I'll give it a shot, I can probably integrate that with http://rustless.org/valico/doc/valico/

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

This should solve the problem perfectly.😁

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

@sunli829 yeah, except I need to pass said schema to the validator.
That would be possible if the context got passed to the validator as well, so that I could go to the database and check, otherwise I can't see how to implement this. But it's alright if I just have to check within the mutation body.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

If you need a context, the Validator can't do that right now, because it's in the query validation phase, and it hasn't created a context yet.😁

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

@sunli829 should I add a ticket for Guard?
I'd contribute it myself, but so far a bit swamped with other coding duties :/

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

This should be finished by tomorrow. I have been trying other improvements for the last two days.

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

Curious to see what you came up with for other issues we had!

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

In fact, I'm still thinking about how to use Guard, because even without this feature, a single line of code can solve the problem.

#[field(guard="require_auth")
async fn value(&self) -> i32 {...}
async fn value(&self, ctx: &Context<'_>) -> FieldResult<i32> {
   require_auth(ctx)?;
}

The guard attribute doesn't offer any convenience, and I'm still wondering if this feature is necessary.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

Curious to see what you came up with for other issues we had!

I tried to optimize the way the interface is defined, but I was not satisfied with either approach.

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

In fact, I'm still thinking about how to use Guard, because even without this feature, a single line of code can solve the problem.

#[field(guard="require_auth")
async fn value(&self) -> i32 {...}
async fn value(&self, ctx: &Context<'_>) -> FieldResult<i32> {
   require_auth(ctx)?;
}

The guard attribute doesn't offer any convenience, and I'm still wondering if this feature is necessary.

That actually seems very nice to me, because then we could apply several guards as well, and that's several method calls.
If we could also specify params for the guards - even better. For example, field(guard="require_auth(role=ADMIN)") or similar.

Take a look at some of the features of https://docs.nestjs.com/graphql/tooling for inspiration, they have some powerful annotations in place that make working with graphql a blast!

from async-graphql.

ruseinov avatar ruseinov commented on April 29, 2024

One important feature I overlooked is that guard can be applied to the SimpleObject.

Yeah, I mean there are plenty of nice looking features there, but not all of them can be implemented in rust the same way, as it's not the same.

For example, there is an ability to annotate methods and types so that they end up being parts of the query/mutation/subscription without actually being one object AFAIK. That allows for splitting the schema by functionality, we could kind of mimic that by having a composite struct I suppose.

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

I created a new issue #43, adding this feature was more difficult than I expected, I needed to modify some code generation, and it probably took a little longer to complete.

from async-graphql.

D1plo1d avatar D1plo1d commented on April 29, 2024

Am I right in thinking that dynamic schemas would also be needed to implement an Apollo Gateway replacement in rust?

from async-graphql.

Bjohnson131 avatar Bjohnson131 commented on April 29, 2024

Hey @sunli829 you closed this as completed. was there a PR for this feature that I can look at?

from async-graphql.

sunli829 avatar sunli829 commented on April 29, 2024

I underestimated the amount of work, but it should be done this week.

from async-graphql.

Bjohnson131 avatar Bjohnson131 commented on April 29, 2024

This is so big! If you get a preview, let me know! I'll be following!

from async-graphql.

xoac avatar xoac commented on April 29, 2024

This issue can be probably closed

from async-graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.