Giter VIP home page Giter VIP logo

dgraph-rs's Introduction

Hi there 👋

My name is Swoorup Joshi. I'm a passionate about distributed & concurrent systems, and making high traffic application scale.

While I look at the platform/runtime as a tool to achieve the goal, my personal weapons of choice include: Rust or F#.

println!("${firstName}[email protected]")

dgraph-rs's People

Contributors

enmand avatar martinmr avatar ondrowan avatar swoorup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

dgraph-rs's Issues

Update mutation not erroring or actually saving

I'm having some trouble, most likely due to incorrect use (again). I'm neither receiving an error or seeing the effect take place. I have a struct that looks like so:

// Model for updating a user
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct UserUpdate {
    pub uid: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub email: Option<String>,
    pub updated_at: Option<DateTime<Utc>>
}

I then have an endpoint that receives a request an updates the user conditional on if values exist in the payload:

let req = request.into_inner();
let mut user = UserUpdate {
    uid: usr.unwrap().uid.to_string(),
    username: None,
    password: None,
    email: None,
    updated_at: Some(Utc::now())
};
// Update values if supplied to the endpoint
if req.username.to_string() != "" {
    user.username = Some(req.username.to_string());
}
if req.email.to_string() != "" {
    user.email = Some(req.email.to_string());
}
if req.password.to_string() != "" {
    user.password = Some(req.password.to_string());
}
// Submit the record to upgrade
let mut txn = self.graph.new_txn();
let mut mututation = dgraph::Mutation::new();
mututation.set_set_json(serde_json::to_vec(&user).expect("Invalid JSON"));
// Finalize the commit
let res = txn.commit();
if res.is_err() {
    return Err(Status::internal("INTERNAL_ERROR"));
}

There might be a better way to structure this but it's the only way I could think of structuring it. When I run a request there's no error, the result comes back successful but my record isn't modified at all. I'm passing in the correct uid and everything.

Wondering where I went wrong :-/ if this doesn't work I was going to just run an Operation with the syntax for the mutation written out.

Support for Dgraph 1.1

Dgraph 1.1.0 landed 5 days ago and it contains some breaking changes we need to address. I checked Go and JS clients and they both released new major version that supports it. I'm not 100% sure but I think we can mitigate this with feature flag. I'll try to look into it soon and see if it's gonna be as easy and elegant as I think.

Suggestion: default to dgraph 1.1

I almost just walked away from dgraph-rs because I wasn't using it properly. I installed a fresh copy of Dgraph and attempted writing some Rust queries against it to validate this library and got the error:

thread 'main' panicked at 'failed to create data: GrpcError(RpcFailure(RpcStatus { status: Unimplemented, details: Some("unknown method Mutate for service api.Dgraph") }))', src/server.rs:1:1

This lead me to believe the library was not maintained for the latest version of Dgraph. However luckily I ended up reading the instructions on the README properly and determined you have to activate the latest with a feature flag.

There's are three easy solutions:

  1. Use 1.1 as the default
  2. Force the feature definition to pull in which feature to use
  3. When the mutation error comes above comes back warn the user that they are likely using incompatible versions.

This makes them more attentive to the version being used. Honestly I think a combination of 1 and 3 are the safest bet moving forward,

Thanks for your work on this library. It's saving me a lot of time/effort.

Is production ready?

Greetings, I'm looking for a graph database rust driver for a new project. Dgraph and this project are great to include them, but the last commit is from more than 1 year ago, so I was wondering if it's abandoned or just not maintained.

Functional tests

I've written functional tests for this library, but I have no idea how to include them into Rust's testing pipeline. The problem is that I need two separate instances of Dgraph for testing (secure and insecure; on non-standard ports, so it doesn't interfere with user's data on local instance). Docker is an obvious choice for this, but I have no idea how to write a (multi-platform) script that can also run setup and teardown of these instances. Basically I need something that runs:

  • docker-compose up
  • cargo test
  • docker-compose down

Is there any way to do this easily via Cargo scripts? Right now the most obvious way that comes into my mind is to run these commands via std::process::Command, but I don't know what pitfalls does this approach have.

Is failure crate necessary?

I found out it's currently not easily possible to match errors produced by gRPC. Let's say there's a wrong alter and I want to catch particular error and present it to user. It's currently very awkward to do so.

// Errorneous alter
let op = dgraph::Operation {
    schema: "name: string @error .",
    ..Default::default()
};

let result = dgraph.alter(&op);

if let Err(err) = result {
    if let Ok(grpc_err) = err.downcast::<grpcio::Error>() {
        if let grpcio::Error::RpcFailure(status) = grpc_err {
            eprintln!("{}", status.details.unwrap())
        }
    }
}

First of all, grpcio::Error should be probably re-exported so users don't need to include grpcio just for error matching.

This also led me to check how failure is used in this library and it seems it could be swapped out for std Error since the more advanced features aren't used anyway. I think it would make error handling a bit easier for users.

Let me know if I've missed something obvious that makes this easier.

Can't install the crate

Protobufs are compiled during build step, but protoc-grpcio requires protoc CLI utility to be installed to actually compile anything. Therefore if users of this library don't have this utility installed, this crate won't build. Wouldn't it be better idea to precompile protobufs and keep generated files in repo, like official (Go and JS) clients do?

gRPC errors on client connect and query

Hi!

I'm trying out this client and I'm getting a couple errors. First, I get this error when I create a client:

E1203 14:06:23.973404816    6831 uri_parser.cc:46]           bad uri.scheme: ''
E1203 14:06:23.973503065    6831 uri_parser.cc:52]                            ^ here
E1203 14:06:23.973512562    6831 http_proxy.cc:58]           cannot parse value of 'http_proxy' env var

And this error when I make a query:

Err(
    GrpcError(
        RpcFailure(
            RpcStatus {
                status: Internal,
                details: Some(
                    "grpc: error unmarshalling request: proto: wrong wireType = 2 for field StartTs",
                ),
            },
        ),
    ),
)

The server I'm connecting to is at localhost:9080; has anyone seen this issue before?

Trouble serializing DateTime for record

I'm having trouble using the DateTime trait with a record. Here's my struct:

// Models the user in the graph
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct User {
    pub id: String,
    pub username: String,
    pub password: String,
    pub email: String,
    pub coordinates: Vec<f64>,
    pub location: f64,
    pub created_at: Option<DateTime<Utc>>,
    pub updated_at: Option<DateTime<Utc>>
}

Here's how I'm using it:

let current_date: DateTime<Utc> = Utc.timestamp(0, 0);
let u = User {
    id: id.to_string(),
    email: "".to_string(),
    username: username.to_string(),
    coordinates: vec![], //vec![1.1f64, 2f64]
    location: 04.0,
    password: "".to_string(),
    created_at: Some(current_date),
    updated_at: Some(current_date)
};

Here's the error I'm receiving:

error[E0277]: the trait bound `chrono::DateTime<chrono::Utc>: _IMPL_DESERIALIZE_FOR_User::_serde::Serialize` is not satisfied
  --> src/server.rs:52:5
   |
52 |     pub created_at: Option<DateTime<Utc>>,
   |     ^^^ the trait `_IMPL_DESERIALIZE_FOR_User::_serde::Serialize` is not implemented for `chrono::DateTime<chrono::Utc>`
   |
   = note: required because of the requirements on the impl of `_IMPL_DESERIALIZE_FOR_User::_serde::Serialize` for `std::option::Option<chrono::DateTime<chrono::Utc>>`
   = note: required by `_IMPL_DESERIALIZE_FOR_User::_serde::ser::SerializeStruct::serialize_field`

Pretty close to the simple example, so not sure what I've done wrong here or if it's a bug related to serde/dgraph-rs.

Consecutive queries on a transaction causes StartTs mismatch

When using a Txn to perform two queries in a row, dgraph errors out with a message stating StartTs mismatch.

You should be able to get that behavior if you do the following:

let mut txn = client.txn();

// Should work okay!
match txn.query("q(func: uid(0x01)) { uid }".to_string()) {
    Ok(result) => {},
    Err(e) => println!(e)
}

// StartTs mismatch (Err!)
match txn.query("q(func: uid(0x01)) { uid }".to_string()) {
    Ok(result) => {},
    Err(e) => println!(e)
}

Thanks for making this library!

Geo types being handled strangely

I'm having trouble with a geo predicate not being recorded correctly. I attempted two different implementations. The first was to pass a vec of float: coordinates: vec![ lat, lon ].

Then noted that it required a vec u8 and attempted coercing the values vec![ ( lat / 100000.0) as u8, ( lon / 100000.0) as u8 ].

The other was to use WKB:

let lat: f64 = location.lat.into();
let lon: f64 = location.lon.into();
if lat > 90.0 || lat < -90.0 || lon > 180.0 || lon < -180.0 {
    return Err(Status::invalid_argument("LAT_LNG_INVALID"));
}
let p: Geometry<f64> = Geometry::Point(Point::new(lat, lon));
let wkb = geom_to_wkb(&p);

I attempted WKB because the source seems to indicate that's what it's expecting

geo_val(::std::vec::Vec<u8>),

When I do that I get a panic. I'm using 1.1 btw:

thread 'main' panicked at 'failed to create data: GrpcError(RpcFailure(RpcStatus { status: Unknown, details: Some("Cannot convert int to type geo") }))', src/server.rs:1:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Upsert

Hi, thanks for the library!

Is there a way to run an Upsert type of query?

Referencing existing UIDs when mutating

I'm having issues when trying to mutate things in the database

let c = MutComment {
    content: comment.content.clone(),
    poster,
    thread,
    attachment: attachment,
    post_time: "2019-04-11T01:45:00Z".to_string(), // ignore this, it's placeholder
  };

both poster and thread are supposed to be references to another node's UID, which I have stored as strings but when trying to mutate it this way the function creates the request as them being actual strings, instead of scalar values ie. <0x14c2>.

Is there a way to force it to handle these strings as scalar values?
And if not, how are the RDF mutation requests formatted?
I tried doing that because this wasn't working out, where I would just replace parts of the string with the correct values but the DB really didn't like me formatting the RDF the same way I would when using the Ratel Web UI. I tried removing a few levels of {} from the string but that didn't make a difference.

Interest in switching from grpcio to tonic

Hi, would you accept a PR switching to tonic (based on tokio) if the PR retained the existing functionality (perhaps with some changes where unavoidable)?

The motivation for this PR is that trying to use dgraph on the new Apple OS requires one to build LLVM from source, because of bindgen relying on it.
Switching to tonic should in theory not cause any significant performance regression (if there's even any regression) as the transport layer is still the same.

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.