How to resolve the error when next() step is used in gremlin?

Viewed 820

Previously I have used janusgraph-0.2.0-hadoop2 server and gremlin@2.6.0 library for querying.My queries worked fine. But, now I have updated to latest versions(janusgraph: latest, Cassandra: 3, elastic search: 6.6.0) and janusgraph-0.5.0-hadoop2 server. For janusgraph-0.5.0-hadoop2 server and gremlin@2.6.0 library, the following query

g.addV('Location') .property('locationId', 'afdvbd-w6POkbQTq') .property('active', false) .as('place') .V().hasLabel('user').has('userId', 'hhdfjgygkgkdgfyukdgd') .as('person') .addE('createdBy').from('place') .property('on', 1589278312249).next()

results an error

Exception while adding place to graph Error: java.util.NoSuchElementException (Error 597) at GremlinClient.handleProtocolMessage (/srv/node_modules/gremlin/lib/GremlinClient.js:182:37) at WebSocketGremlinConnection.connection.on.message (/srv/node_modules/gremlin/lib/GremlinClient.js:108:46) at emitOne (events.js:116:13) at WebSocketGremlinConnection.emit (events.js:211:7) at WebSocketGremlinConnection.handleMessage (/srv/node_modules/gremlin/lib/WebSocketGremlinConnection.js:45:10) at WebSocketGremlinConnection.ws.onmessage.message (/srv/node_modules/gremlin/lib/WebSocketGremlinConnection.js:30:41) at WebSocket.onMessage (/srv/node_modules/ws/lib/EventTarget.js:103:16) at emitTwo (events.js:126:13) at WebSocket.emit (events.js:214:7) at Receiver._receiver.onmessage (/srv/node_modules/ws/lib/WebSocket.js:146:54)

The same query when I am running by updating the gremlin library to 3.4.6, then the result is as follows

Logs in google cloud platform:

RangeError: Invalid status code: undefined at ServerResponse.writeHead (_http_server.js:200:11) at ServerResponse._implicitHeader (_http_server.js:191:8) at write_ (_http_outgoing.js:632:9) at ServerResponse.end (_http_outgoing.js:751:5) at ServerResponse.send (/srv/node_modules/express/lib/response.js:221:10) at ServerResponse.json (/srv/node_modules/express/lib/response.js:267:15) at ServerResponse.send (/srv/node_modules/express/lib/response.js:158:21) at place.postPlace.then.catch.err (/srv/routes/place.js:41:35) at <anonymous> at process._tickDomainCallback (internal/process/next_tick.js:229:7)

Logs in gremlin console:

java.util.NoSuchElementException
Type ':help' or ':h' for help.
Display stack trace? [yN]y
java.util.NoSuchElementException
        at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.next(DefaultTraversal.java:213)
        at java_util_Iterator$next.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
        at Script17.run(Script17.groovy:1)
        at org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.eval(GremlinGroovyScriptEngine.java:674)
        at org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine.eval(GremlinGroovyScriptEngine.java:376)
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
        at org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor.lambda$eval$0(GremlinExecutor.java:267)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

And my javascript snippet is

/**
 * @param {Object} options
 * @param {} options.userId 
 * @param options.client // this is the gremlin client to run queries onto graph database.
 * @throws {Error}
 * @return {Promise}
 */
module.exports.addLocation = (options) => {
  const location = options.location;
  const admin = options.admin;
  const createdOn = new Date().valueOf(); // TODO: timestamp entered into Firestore. Same value should be given here

  console.log('addLocation invoked', location);
  console.log('Options obtained', options);
  return new Promise((resolve, reject) => {
    if (options.userId !== options.reqUserId) {
      console.log(`UserId: ${options.userId}, reqUserId: ${options.reqUserId}`, options);
      return reject({
        status: 401,
        body: 'Unauthorized. You can\'t impersonate other users!'
      });
    }
    console.log('validating the location');
    const errors = validate(location, 'Model');
    if (errors) {
      console.log('Error while validating the locations:', errors);
      return reject({
        status: 405,
        body: errors
      });
    }
    const locationId = `${location.name.replace(/\s+/g, '-').replace(/[^a-zA-Z0-9-_]/g, '').toLowerCase()  }-${  shortid.generate()}`; //TODO: id obtained from firestore
    console.log(`Created dynamic location id: ${  locationId}`);

    location['locationId'] = locationId;
    location['createdDate'] = new Date();
    location['lastUpdatedDate'] = new Date();
    if (location.publishedDate) story['publishedDate'] = new Date(location.publishedDate);
    if (location.unpublishedDate) story['unpublishedDate'] = new Date(location.unpublishedDate);
    console.log(`updated location: ${ JSON.stringify(location)}`);
    //TODO: get the ID of the story and use it to make entry into Graph
    const name = location.name;
    const active = false;
    const inputParams = {
      userId:options.userId,
      locationId,
      name,
      active,
      createdOn
    };
    console.log('adding location to graph');
    const query = `g.addV('Location') .property('locationId', locationId) .property('active', false) .as('place') .V().hasLabel('user').has('userId',userId ) .as('person') .addE('createdBy').from('place') .property('on', 1589278312249).next()`;
    console.log(`query: ${query}  inputParams:`, inputParams);
    options.client.executeGraph(query, inputParams).then(res => {
      if (res.length > 0) {
        console.log('Successfully added the location to graph');
        console.log('adding location to firestore');
        
        
        const createdlocation = location; // TODO: replace with actual object.
        admin.firestore().doc(`cms/ugc/locations/${  locationId}`).set(location).then(() => {
          console.log('succesfully added location to firestore ');

          return resolve({
            status: 200,
            data: createdlocation
          });
        }).catch((err) => {
          console.log('Error while adding location to firestore:', err);
          return reject({status:500, error: err});
        });
      } 
    }).catch(err => {
      console.log('Exception while adding location to graph', err);
      return reject({
        status: 500,
        error: err
      });
    });
  });
};

But, while running the same query in gremlin console with static data and also by removing the next() step, then it is working perfectly fine.

Don't know the exact issue, but I thought of next() step in latest versions maynot work correctly.It is a wild guess but I am not getting how to resolve it. Any help would be greatly appreciated. Thanks in advance!

1 Answers

I'm really not sure what could be wrong. Taken on it's own NoSuchElementException usually means that you've called next() on an empty Traversal. The question then becomes, why is my traversal not returning data? In this case, I'd be suspicious of V().hasLabel('user').has('userId','x') because it's the only portion of the query that isn't additive. It requires a vertex to be produced for addE() to return anything.

Running your query above on an empty graph you can see what happens:

gremlin> g.addV('Location').property('locationId', 123).property('active', false) .as('place').
......1>   V().hasLabel('user').has('userId','x').as('person').
......2>   addE('createdBy').from('place').property('on', 1589278312249).next()
java.util.NoSuchElementException
Type ':help' or ':h' for help.
Display stack trace? [yN]

so it's easy to recreate. The problem of course is that you say your traversal works correctly in the Gremlin Console. Is it possible that you've connected to the same graph in both of your tests? Did you use the exact same parameters (i.e. the same "userId")? I'd verify from the failing javascript that you can properly query the vertex you are trying to add an edge to.

Related