warpforge / warpgrapher

Rust framework for graph-based API services.
Apache License 2.0
33 stars 1 forks source link

Add AnzoGraph and SparQL capability #85

Open 007vasy opened 3 years ago

007vasy commented 3 years ago

I am going to develop and auto resolver generator for SparQL, I want to use it for AnzoGraph for a project. (It is painful to write all the resolvers for it)

Are you willing to advise me on this journey? Any pointer, lessons learned creating it for the other languages?

maldrake commented 3 years ago

@007vasy, I'd be happy to help. We did a lot of work to modularize the database-specific parts of Warpgrapher when we added Gremlin support, so it should be much easier than it would've been a few versions ago. I think the following places are where changes will be needed:

Ok, so with the test and CI/CD environment in place, to implement the database and query language support itself:

If you do decide to work on adding SparQL support, I'd be happy to help.

007vasy commented 3 years ago

thanks for the pointers :) this is great, I think the pattern of neo4j and gremlin will really help me!

maldrake commented 3 years ago

If you run into any questions or problems along the way, let me know, and I'll do what I can to help.

007vasy commented 3 years ago

created a fork, will do a PR if there is some functionality ready for review

007vasy commented 3 years ago

@maldrake I am almost ready with the test setup, any examples how I could utilise macros for this?

maldrake commented 3 years ago

If all goes well, I should have something to make life easier early next week. I hope that timeline works.

007vasy commented 3 years ago

no rush, I am working on this on my free time, and I am also learning the more complex features of rust, so I appreciate any help on this journey :+1: :)

maldrake commented 3 years ago

Later than I'd hoped, but I have some things to look at...

I think you'll want to pull a couple branches from our upstream repo into your fork, specifically both the "event-framework" and "test-macro" branches. (Or, if we get the two open pull requests for them merged soon, then they won't be separate branches at that point.) For an overview of what they do and why they help...

First, the event-framework branch is preparation for an upcoming change, but I cleaned it up into a releasable form because it's going to make life easier for the SparQL implementation. Previously, we'd been rolling up everything in a mutation query into a single database query. If your mutation edited five nodes with relationships between them, added a few more, or deleted some... that would all get compounded into one database query. The upside was efficiency in terms of few round trips to the database, though the Gremlin traversals and nested Cypher subqueries could become quite complex, and thus hard for a query planner to optimize. The PR in the event-framework branch breaks things out so that complex GraphQL queries are sent as a series of multiple queries to the database, one for each operation on a node or relationship. This should make it a lot easier to add SparQL support, as each individual query operation is much simpler. At the risk of getting ahead of my peer reviewers, I'd say definitely write new code to the interfaces in the event-framework branch. Hopefully it'll be merged soon.

Ok, the second change is to make life easier for testing. Up above, I'd said that you'd need to copy/paste a bunch of repetitive code to add new test cases for SparQL. The real work of the test case is done in a single function but each database-specific integration test needs to be set up individually, with the right type of client (Neo4J vs. Cosmos vs. Gremlin), and so on. Have a look at tests/node_mnmt_resolver.rs for an example. The code in the test-macros branch makes this much easier now. If you look at node_mnmt_resolver.rs in the test-macros branch, you can see that the three database-specific test case setup functions for each real test function are gone, replace by a single macro annotation of "wg_test".

I added a warpgrapher_macros package. If you open warpgrapher_macros/src/lib.rs, you can see the definition of the wg_test macro. It parses the token stream, yielding the input variable of type ItemFn. It stores the name of that base testing function in name, and then creates identifiers for the name variants for each database: name_cosmos, name_gremlin, and name_neo4j. It then uses the quote! macro to generate code for the three database-specific test cases, which each get the appropriate database client and pass it to the base testing function. The end result is that now you don't have to do any of that repetitive copy/pasting/editing of test code. You still need to add SparQL-specific database client setup code in the tests/setup/mod.rs module, as well as code to clear the database between tests. However, then you can add a fourth database test case function to the macro code, and you're done. It'll be applied to all the base test functions automatically.

007vasy commented 3 years ago

woow, @maldrake you are amazing :+1: it is really making my life easier, I am having issues with having a proper sparQL client in Rust, Issue so that has to solve even before I can do the test setup

007vasy commented 3 years ago

@maldrake if you have time and patience could you spent 5 min max of what should a sparql client do to able me to create the sparql graphl translator? here is the code of a bare-bones sparql client in rust which can communicate with anzograph

maldrake commented 3 years ago

@007vasy, sure, happy to help. In good news, we don't ask for a lot from the client. The modules crate::engine::database::gremlin and crate::engine::database::neo4j are the right ones to look at for examples of how we use the database clients. I think the only required thing is to be able to send a query and get a response back from the database.

There are some other nice to have features, such as:

Oh, yes... one other thing. As a practical matter, the SparQL client will have to be packaged as a crate on crates.io that we can import to Warpgrapher through the Cargo.toml file.