Skip to content

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

Merged
tae898 merged 1 commit into
mainfrom
fix/stale-vertex-new-edge
Nov 5, 2026
Merged

tae898 merged 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
@tae898 tae898 added this to the 26.11.1 milestone Nov 5, 2026
@tae898 tae898 added bug Something isn't working jvm The arcadedb-jvm package (JPype build) labels Nov 5, 2026
@tae898
tae898 merged commit d04a85e into main Nov 5, 2026
99 checks passed
@tae898
tae898 deleted the fix/stale-vertex-new-edge branch November 5, 2026 01:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working jvm The arcadedb-jvm package (JPype build)

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