JanusGraph / JanusGraph/janusgraph
Unique index failed when vertex creation running in parallel
- Dominant language
- Java
- Stars
- 5.8k
- Forks
- 1.2k
- Avg merge
- 13h 53m
- Merged PRs (30d)
- 6
Description
Hi all.
Unique index not working when run vertex creation in parallel.
```scala
import java.io.File
import java.util.concurrent.Executors
import org.apache.commons.configuration.BaseConfiguration
import org.apache.commons.io.{FileUtils, IOUtils}
import org.apache.tinkerpop.gremlin.structure.{Graph, Vertex}
import org.janusgraph.core.{JanusGraph, JanusGraphFactory}
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.util.Random
object Launcher {
val DB_DIR = "/tmp/titan-index-test"
def openGraph(): Graph = {
val conf = new BaseConfiguration()
conf.setProperty("schema.default", "none")
conf.setProperty("storage.backend", "berkeleyje")
conf.setProperty("storage.directory", DB_DIR)
createSchema(JanusGraphFactory.open(conf))
}
def createSchema(graph: JanusGraph): JanusGraph = {
val mgmt = graph.openManagement()
val label = mgmt.makeVertexLabel("user").make()
val key = mgmt.makePropertyKey("username").dataType(classOf[String]).make()
val pass = mgmt.makePropertyKey("pass").dataType(classOf[String]).make()
mgmt.buildIndex("usernameUnique", classOf[Vertex]).addKey(key).indexOnly(label).unique().buildCompositeIndex()
mgmt.commit()
graph
}
def main(args: Array[String]): Unit = {
System.out.println("Start application")
FileUtils.deleteQuietly(new File(DB_DIR))
val graph = openGraph()
//Create vertex with unique data.
val v = graph.addVertex("user")
v.property("pass", "test")
v.property("username", "Test")
graph.tx().commit()
(1 to 1000).foreach { i =>
println("test: " + i)
val fSeq = Future.sequence(test(graph))
println("Awaiting")
Await.result(fSeq, 1.minute)
val count = graph.traversal().V().has("username", "Den").count().next()
println("Count of vertices: " + count)
assert(count == 1, "Users > 1")
}
println("Closing application")
graph.close()
System.exit(0)
}
def test(graph: Graph)(implicit ec: ExecutionContext): List[Future[Boolean]] = {
(1 to 10).toList.map { _ =>
Future {
try {
println("Add vertex!!!")
val v = graph.addVertex("user")
v.property("pass", "test")
v.property("username", "Den")
graph.tx().commit()
true
} catch {
case ex: Exception =>
println(ex.getMessage)
false
}
}
}
}
}
```
Result:
```
Adding this property for key [username] and value [Den] violates a uniqueness constraint [usernameUnique]
Adding this property for key [username] and value [Den] violates a uniqueness constraint [usernameUnique]
Adding this property for key [username] and value [Den] violates a uniqueness constraint [usernameUnique]
Adding this property for key [username] and value [Den] violates a uniqueness constraint [usernameUnique]
Exception in thread "main" java.lang.AssertionError: assertion failed: Users > 1
at scala.Predef$.assert(Predef.scala:170)
at com.xdev.titan.Launcher$$anonfun$main$1.apply$mcVI$sp(Launcher.scala:62)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
at com.xdev.titan.Launcher$.main(Launcher.scala:52)
at com.xdev.titan.Launcher.main(Launcher.scala)
Count of vertices: 2
```
This additional vertex cannot be removed, operation failed with status NOT_FOUND.
Contributor guide
Research direction
Start with the Scala reproducer in the issue and the failing locations in Launcher.scala:52 and Launcher.scala:62. Run the parallel vertex-creation case and inspect the uniqueness-constraint and NOT_FOUND results. Done means concurrent creation of the same username leaves exactly one matching vertex without an unrecoverable extra vertex.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, scala
- Domain
- databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100