Search code examples
javagremlintinkerpop3amazon-neptune

Conditionally interrupt java-gremlin update traversal, with error message


I have a scenario where I in the midst of an update traversal want to check a condition, and if that condition is false I want to interrupt the traversal and leave the graph unchanged. Also I want to know that the traversal was skipped so I can throw an exception to the invoking code.

Constraints:

  • I need to do this in one traversal, because the graph database service I use can not hold a transaction over multiple traversals.
  • I do need a way to identify why the traversal was interrupted.
  • Also it seems I can not use the sideEffect() step (?), because that seems to not play with serializing of the gremlin query.

Principal traversal that works locally using TinkerGraph but not deployed as a lambda invocing AWS Neptune.

GraphTraversalSource g = graph.traversal();

g.V().hasLabel("ops").fold()
  .coalesce(
      unfold(),
      sideEffect(t -> { throw new RuntimeException("First vertice not found"); }))
  .as("a")
  // do much more stuff
  .hasNext();

sideEffect(org.someone.graph.ClassImpl$$Lambda$155/352598575@1b7f1140)]], aliases={g=g}}}] could not be serialized by org.apache.tinkerpop.gremlin.driver.ser.AbstractGryoMessageSerializerV3d0.


Solution

  • Lambdas can't be serialized which is why you're getting that exception. Furthermore, lambdas are not supported in Neptune so your approach wouldn't work anyway. Your experiments with TinkerGraph worked because it has neither of these limitations.

    I'm not sure what you can do to work around this problem because you mentioned that:

    I do need a way to identify why the traversal was interrupted.

    Maybe you could use constant() somehow?

    gremlin> g = TinkerFactory.createModern().traversal()
    ==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
    gremlin> g.V().has('person','name','marko').fold().coalesce(unfold(), constant('Not Found'))
    ==>v[1]
    gremlin> g.V().has('person','name','x').fold().coalesce(unfold(), constant('Not Found'))
    ==>Not Found
    

    I'm not sure that this will work perfectly though because you want to

    leave the graph unchanged

    Depending on how you write your Gremlin, this wouldn't have even worked in TinkerGraph. constant() isn't an "error condition" that is going to be recognized as a method for rolling back a transaction. Perhaps that's just something to be aware of. Depending on how complex your logic is, you might end up with some really hard to read Gremlin. You might need reconsider your approach.