JanusGraph / JanusGraph/janusgraph

Unique index failed when vertex creation running in parallel

Open
#121 21 comments 0 reactions 0 assignees View on GitHub
kind/bug/possible storage/berkeleydb
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.