orientdb
orientdb copied to clipboard
Using gremlin, calling Vertex.addEdge(String,Vertex) causes occasional OCommandExecutionException with message "Class `xxx` already exists"
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.