Skip to content

Vertex.new_edge: resolve both ends by record id on the JVM build - #216

Open
tae898 wants to merge 1 commit into
mainfrom
fix/stale-vertex-new-edge
Open

tae898 wants to merge 1 commit into
mainfrom
fix/stale-vertex-new-edge

Conversation

@tae898

@tae898 tae898 commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #215

The JVM Vertex.new_edge called newEdge on the cached ImmutableVertex and passed the target as a Java vertex object. A vertex's first edge rewrites its record, so any object read before that commit is out of date and the update raised ConcurrentModificationException. The native wrapper already goes by record id.

Decision: make the JVM match native. Neither the docs nor the docstrings say that records are snapshots that must be re-read before new_edge; the docs say the native build sends record ids, and the new_edge docstring promises an edge between two vertices without any condition. So the source is looked up by its record id inside the active transaction (one lookupByRID), and the target goes in as its record id, which the engine loads itself. The wrapper object you hold is not refreshed.

Behaviour change: new_edge from a stale vertex object now succeeds on the JVM build instead of raising. No documented behaviour changes; I added a paragraph to the record-id section of databases-and-queries.adoc and a docstring note.

Not changed: modify().set().save() on a stale object. The JVM build uses the engine's version check (an out-of-date object conflicts at commit) and the native build writes the properties by record id. That is a separate difference and I did not alter it here.

Tests: tests/test_stale_vertex_new_edge.py runs on both builds (objects read once, one edge per transaction; stale target only; stale after an SQL-made edge; several edges in one transaction) and checks the edge count and in and out degrees. I did not run it locally; CI runs both workflows on this branch.

🤖 Generated with Claude Code

A vertex object read before the first edge of that vertex was committed held the old record version, so newEdge from it raised ConcurrentModificationException on the JVM build; the native build goes by record id and succeeded. Look the source up by id inside the active transaction and pass the target as its id. Regression test runs on both builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tae898
tae898 marked this pull request as ready for review November 3, 2026 16:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vertex.new_edge on a vertex object read earlier raises ConcurrentModificationException on the JVM build only

1 participant