orientdb icon indicating copy to clipboard operation
orientdb copied to clipboard

Using gremlin, calling Vertex.addEdge(String,Vertex) causes occasional OCommandExecutionException with message "Class `xxx` already exists"

Open matthewadams opened this issue 1 year ago • 3 comments

OrientDB Version: 3.2.32, 3.2.33, 3.2.34 (using official OrientDB containers)

Java Version: openjdk version "21.0.4" 2024-07-16 LTS, OpenJDK Runtime Environment Corretto-21.0.4.7.1 (build 21.0.4+7-LTS), OpenJDK 64-Bit Server VM Corretto-21.0.4.7.1 (build 21.0.4+7-LTS, mixed mode, sharing)

OS: macOS Sequoia 15.0.1 (24A348)

Expected behavior

Vertex.addEdge(String,Vertex) should succeed even if the class already exists.

Actual behavior

Vertex.addEdge(String,Vertex) throws

com.orientechnologies.orient.core.exception.OCommandExecutionException: Class `RESULTED_IN` already exists	DB name="ANALYTICS"	DB name="ANALYTICS"

Relevant stack trace:

          org.apache.tinkerpop.gremlin.orientdb.OrientGraph.createClass(OrientGraph.java:646)
          org.apache.tinkerpop.gremlin.orientdb.OrientGraph.createClass(OrientGraph.java:621)
          org.apache.tinkerpop.gremlin.orientdb.OrientGraph.createEdgeClass(OrientGraph.java:609)
          org.apache.tinkerpop.gremlin.orientdb.OrientVertex.addEdge(OrientVertex.java:135)

It appears that in OSchemaRemote.java, method createClass, should change line 104 from

cmd.append('`');

to

cmd.append('` IF NOT EXISTS ');

Further, perhaps line 96 of the same file should simply return silently, too, short-circuiting to just returning the OClass instead, going from

      if (classes.containsKey(key))
        throw new OSchemaException("Class '" + className + "' already exists in current database");

to

      if (classes.containsKey(key))
        return classes.get(key);

Steps to reproduce

This issue is intermittent, but happens frequently enough that it's causing our tests to fail and our CI pipelines to fail. We're using the OrientDB java driver in a Spring Boot 3.3.3 + Kotlin 2.0.20 environment, and the OrientDB driver doesn't appear to offer asynchronous APIs, which is problematic. There could be simultaneous activities (not necessarily multiple threads, but multiple coroutines on a single thread) that are causing this to fail. Hard to tell, but making OSchemaRemote.createClass(ODatabaseDocumentInternal database, final String className, int[] clusterIds, OClass... superClasses) more lenient would prolly work around the issue.

matthewadams avatar Oct 04 '24 21:10 matthewadams