Conversation
e8f1099 to
7525f26
Compare
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Fixes a failure mode when applying updateIndex actions to mixed indexes where no field matches the action’s applicable statuses, by rejecting early with a descriptive error (and adding regression tests).
Changes:
- Add a precondition guard for mixed indexes to reject update actions that match no fields, including reporting per-field statuses.
- Remove a now-redundant/late guard in the mixed
REMOVE_STALE_ENTRIESpath. - Add
MixedIndexUpdateStatusTestcovering the rejected case and two success paths (registering INSTALLED, disabling ENABLED).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| janusgraph-test/src/test/java/org/janusgraph/graphdb/database/management/MixedIndexUpdateStatusTest.java | Adds regression tests ensuring a descriptive exception is thrown when an update action matches no mixed-index fields. |
| janusgraph-core/src/main/java/org/janusgraph/graphdb/database/management/ManagementSystem.java | Adds an early guard for mixed-index updates when no fields match, and includes per-field status in the rejection message. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
7525f26 to
89e3261
Compare
|
Reviewed, rebased on current On "no-op or clear error"The issue asked for "either no-ops or reports a clear error, as it does for composite indexes", and I wanted to be sure which of those composite actually does before signing off on throwing. It throws: On the two behaviour changesBoth are improvements and I am happy to take them, but I checked each one rather than taking the reasoning on trust.
On the third action this silently affectsWorth stating explicitly, since neither the issue nor the PR body mentions it: the guard also makes Verification
|
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 1
Open (2)
Resolved since last review (1)
89e3261 to
9a4883d
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 1
Open (3)
This new helper introduces references to Arrays and Collectors. If they are not already imported in… · New The error message printsapplicableStatusvia the collection’s defaulttoString(), which can be… · New Comment formatting is inconsistent with typical Java style (missing a space after//). Please… · New
9a4883d to
00e2d4e
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 2
Open (2)
Resolved since last review (3)
00e2d4e to
6c8829e
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 3
Open (3)
6c8829e to
ca73124
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
Review effort: Lite
Findings: 3
Open (4)
This uses a static counter shared across all tests/JVM state. If the build enables parallel test… · New This uses a static counter shared across all tests/JVM state. If the build enables parallel test… · New OverridingclearStorewithout delegating tosuper.clearStore(storeName)can break test… · New The comment says the output is in enum declaration order, but the implementation relies on… · New
Resolved since last review (3)
…ph#4930) A mixed index keeps a SchemaStatus per field instead of one status on the index, so updateIndex collects the fields whose status the action applies to. When no field matched, the empty set was passed on to setStatus, which routed to setStatusVertex, whose precondition can never hold for a mixed index. That precondition carries no message, so the caller received a bare IllegalArgumentException with nothing to act on. Re-running an idempotent schema script is enough to reach this. REGISTER_INDEX applies to INSTALLED and DISABLED, so it matches no field once the index is enabled. An index built on a property key created in the same management transaction is enabled immediately, so a script which creates an index and then registers it fails the second time it runs. The composite branch guards against this a few lines earlier with isApplicableStatus, which throws a message naming the action and the status. Give the mixed branch the equivalent check, and report the status of every field so it is clear which one blocked the action. Render the applicable statuses in the declaration order of the enum rather than through the iteration order of the HashSet which holds them, so the message does not vary between runs. Cover both of those with tests which fail without the guard: a discard of an enabled index is rejected without the index backend having been cleared, and a drop of an index which is not discarded is rejected with the index still present. The sequence which must keep working, disable then discard then drop, is covered too. This makes a mixed index behave as a composite index already does for an action which does not apply to it. It also means DISCARD_INDEX no longer clears the index backend before failing, and DROP_INDEX on a mixed index which is not DISCARDED is now rejected rather than dropping the schema vertex and orphaning the documents. The equivalent check that REMOVE_STALE_ENTRIES made for itself is now unreachable, so remove it. Signed-off-by: Balmukund Trivedi <btrivedipublic@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-Authored-By: Oleksandr Porunov <alexandr.porunov@gmail.com> Signed-off-by: Oleksandr Porunov <alexandr.porunov@gmail.com>
ca73124 to
ea29f96
Compare



Fixes #4930.
A mixed index keeps a
SchemaStatusper field instead of one status on the index, soupdateIndexcollects the fields whose status the action applies to. When no field matched, that empty set was passed tosetStatus, which routed tosetStatusVertex, whose precondition can never hold for a mixed index.One correction to the issue: that precondition is
Preconditions.checkArgument(condition)with no message argument, so the exception's message isnull. The caller does not get a confusing message aboutRelationTypeVertex— it gets a bareIllegalArgumentExceptionwith no message at all. I found this while writing the test, which failed with aNullPointerExceptionone.getMessage()before the fix.Re-running an idempotent schema script is enough to reach it, exactly as the issue describes:
REGISTER_INDEXapplies toINSTALLEDandDISABLED, so it matches no field once the index is enabled. An index built on a property key created in the same management transaction is enabled immediately, so a script that creates an index and then registers it fails the second time it runs.Change
The composite branch guards this a few lines earlier via
isApplicableStatus. Worth noting that method never returnsfalse— it throws — so thereturn nullafter it in the composite branch is unreachable, and the composite behaviour is "throw a descriptive error". This gives the mixed branch the equivalent check, and additionally reports the status of every field so it is clear which one blocked the action:Two consequences worth your attention
The guard applies to every action, which is what makes a mixed index behave the way a composite index already does. Two of those are behaviour changes beyond the reported symptom, both of which I believe are improvements — but they are yours to judge:
DISCARD_INDEXno longer clears the index backend before failing. Previously it calledIndexSerializer.clearStoreand then threw fromsetStatusVertex, so the documents were already gone while the status change had not happened.DROP_INDEXon a mixed index which is notDISCARDEDis now rejected. This is the second problem you flagged in the issue as possibly deserving its own issue —schemaVertex.remove()used to run regardless, dropping the schema vertex and orphaning every document in the index backend. A composite index is already gated this way.I also removed the
!keySubset.isEmpty()check thatREMOVE_STALE_ENTRIESmade for itself, since the new guard runs earlier and makes it unreachable. If you would rather narrow the guard to only the status-changing actions, that check needs to come back.Testing
MixedIndexUpdateStatusTestruns against the in-memory backend with the existingRecordingIndexProvideras the index backend. It covers the rejected case and asserts the message names the action, the index, the blocking status and the applicable statuses; plus two paths that must keep working, registering anINSTALLEDindex and disabling anENABLEDone.I checked every existing caller of
DISCARD_INDEXandDROP_INDEXin the test tree. The mixed-index sequences inJanusGraphIndexTestandElasticsearchJanusGraphIndexTestall discard or mark-discarded before dropping, so they stay compatible; the sequences inJanusGraphTestare composite and relation indexes, which this does not touch.IndexSerializerTeststill passes. Docker was unavailable to me, so I could not run the container-backed suites locally.For all changes:
master)?For code changes: