'Gremlin Concurrent Modification Exception on Neptune
I have seen many concurrent modification exceptions emerging since I changed a small Gremlin operation in a .Net setting, with Neptune as a the back-end. I'm struggling to understand what could be causing it.
This is my new query
await Graph.V(itemId)
.ActiveLinkedVertex(DbLabels.ComponentEdge)
.OutE(DbLabels.ComponentEdge).HasNot(DbLabels.EdgeToProperty)
.MarkToDate(_operationTime)
.Promise(t => t.Iterate());
and this is my ActiveLinkedVertex extension
public static GraphTraversal<Vertex, Vertex> ActiveLinkedVertex(this GraphTraversal<Vertex, Vertex> traversal, string edgeLabel)
{
traversal = traversal.OutE(edgeLabel)
.HasNot(DbLabels.EdgeToProperty)
.InV();
return traversal;
}
And here's my 'MarkToDate'
public static GraphTraversal<S, E> MarkToDate<S, E>(this GraphTraversal<S, E> traversal, DateTime utcUpdateTime)
{
traversal = traversal.Property(DbLabels.EdgeToProperty, utcUpdateTime).Property(DbLabels.EdgeToTicksProperty, utcUpdateTime.Ticks);
return traversal;
}
The query is getting hit in a multithreaded setting, but never on the same itemId or even itemId's parent. Each thread is working on an isolated subgraph.
Is there anything in the internal implementation of Neptune/Gremlin that I'm missing that could cause a broad lock to be taken, for example, or is my query open to concurrent mods in some way?
Additional Information (edit)
The new query replaced a buggy version, that was
await Graph.V(itemId)
.Out(DbLabels.ComponentEdge)
.OutE(DbLabels.ComponentEdge)
.MarkToDate(_operationTime)
.Promise(t => t.Iterate());
This is is simplified view of what the graph is. Everything below a group is being done on a separate thread and in-order. There can be x-links between Vertices labelled as 'Part' in different groups, but the edges we're mutating are the Component edges between the green and purple verts at the bottom (MarkToDate on the edges)
I've read on the Neptune docs that range locks taken on neighbouring nodes can cause CMEs, but I am finding it hard to understand whether a CME is possible when mutating the edges at the bottom below, under separate Groups. If I put back the original (bugged) update, then there are no CMEs.
Solution 1:[1]
It's hard to tell from the code what exactly might be going on. Concurrent Modification Exceptions (CME) are generally re-triable and can happen if two (or more) threads hit more or less the same part of the graph at the same time. Due to the way locking works, it is hard to give you a single rule about when CMEs may occur and how to avoid them, but the most common reason is when two or more threads try to mutate the same area of the database.
In general, application code should plan to catch, and handle CMEs during concurrent mutation of the graph, and in most cases a backoff/retry strategy is sufficient.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kelvin Lawrence |

