Conversation
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.
This PR fixes mixed-index DISCARD_INDEX cleanup by ensuring the Elasticsearch index-store name is derived in one place (via getIndexStoreName) and passed through to clearStore unchanged, avoiding case-related mismatches.
Changes:
- Refactors
ElasticSearchClient.clearStoreto accept a pre-derivedindexStoreName(signature change) and updates the REST implementation accordingly. - Updates
ElasticSearchIndex.clearStoreto derive the index-store name viagetIndexStoreNameand improve the thrown error context. - Adds a unit test covering the REST client
clearStorecontract (verbatim name usage + no delete when absent).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| janusgraph-es/src/test/java/org/janusgraph/diskstorage/es/rest/RestClientClearStoreTest.java | Adds unit tests asserting clearStore uses the provided index-store name verbatim and guards deletion by existence. |
| janusgraph-es/src/main/java/org/janusgraph/diskstorage/es/rest/RestElasticSearchClient.java | Updates clearStore to operate on a single indexStoreName argument and removes duplicated name composition. |
| janusgraph-es/src/main/java/org/janusgraph/diskstorage/es/ElasticSearchIndex.java | Derives the index-store name once via getIndexStoreName and passes it to the client; updates exception message accordingly. |
| janusgraph-es/src/main/java/org/janusgraph/diskstorage/es/ElasticSearchClient.java | Changes the interface signature for clearStore and documents the “pre-derived name” contract. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ph#4929) Every read and write path mapped a JanusGraph store name to an Elasticsearch index name through generateIndexStoreName, which lowercases the store. RestElasticSearchClient.clearStore composed the same name by hand and did not lowercase it. A mixed index stores its JanusGraph index name as the store name verbatim, and JanusGraph index names are case sensitive. So for an index named vertexByName, documents were written to and queried from <indexName>_vertexbyname, while DISCARD_INDEX asked Elasticsearch to delete <indexName>_vertexByName. An Elasticsearch index name is always lowercase, so that name cannot exist. Either the existence check returned false and the call did nothing, or Elasticsearch rejected the name and ManagementSystem reported that the backend does not support index removal. The documents stayed, and the schema was marked DISCARDED, so JanusGraph believed the data was gone. Remove the second derivation instead of correcting it. ElasticSearchIndex now passes the name it already derived, so ElasticSearchClient.clearStore takes the Elasticsearch index name rather than the pair it used to rebuild. Cover the client contract with RestClientClearStoreTest, which pins that the name it is given is used verbatim for both the existence check and the deletion, and cover the derivation itself against a real Elasticsearch with testClearStoreOfAMixedCaseStoreName, which fails on the previous behavior with the index still present after the store was cleared. 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>
e419026 to
9c49d8d
Compare
|
Reviewed, rebased on current The bug is real, and I have it on filmDocker was the gap in your own verification, so I closed it. I added I then put the old derivation back, in So it is the silent branch of the two you described: That test matters beyond confirming the bug: On the approachI agree with taking the second option from the issue rather than the one-line I also confirmed the premise: Verification
Follow-upsBoth of the things you set aside are worth their own issues, and I agree with leaving them here:
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The public client interface change lacks a compatibility path for downstream implementations and compiled consumers.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Resolved since last review (4)
UsingMockito.resetis generally discouraged because it clears both stubbing and interaction… The comment claims an Elasticsearch index could “genuinely differ in case”, but Elasticsearch index… Since this is a public interface method, prefer a Javadoc comment (/** ... */) over line comments… This test asserts only the HTTP method for the existence check. To better lock down the contract…
| * JanusGraph store name, so that the mapping between the two exists in exactly one place. | ||
| * It is used verbatim; in particular it is not lowercased here. | ||
| */ | ||
| void clearStore(String indexStoreName) throws IOException; |



Fixes #4929.
Every read and write path maps a JanusGraph store name to an Elasticsearch index name through
generateIndexStoreName, which lowercases the store.RestElasticSearchClient.clearStorecomposed the same name by hand and did not lowercase it.A mixed index stores its JanusGraph index name as the store name verbatim, and JanusGraph index names are case-sensitive. So for an index named
vertexByName:<indexName>_vertexbynameclearStoretargeted<indexName>_vertexByNameAn Elasticsearch index name is always lowercase, so the second cannot exist. Either the existence check returned false and the call silently did nothing, or Elasticsearch rejected the name and
ManagementSystemreported the misleading "Index removal is not supported for this Backend". Either way the documents remained while the schema was markedDISCARDED, so JanusGraph believed the data was gone.Approach
I took the second option from the issue — removing the duplicated derivation rather than correcting it.
ElasticSearchIndex.clearStorenow derives the name throughgetIndexStoreName, the same call every other path uses, and passes it down. So the mapping exists in exactly one place and cannot drift again.This changes an interface signature:
ElasticSearchClient.clearStore(String indexName, String storeName)becomesclearStore(String indexStoreName).RestElasticSearchClientis the only implementation andElasticSearchIndexthe only caller, both in this module, so nothing else in the tree is affected.IndexProvider.clearStore(String storeName)is a different interface and is untouched.If you would rather not change the signature, the one-line alternative from the issue — lowercasing inside
clearStore— also fixes the reported bug, and I am happy to switch to it. I preferred this version because the duplication is the root cause.Testing
Docker was not available to me, so I could not run the container-backed
ElasticsearchIndexTestlocally and did not want to add an integration test I could not verify.RestClientClearStoreTestunit-tests the client contract with a mockedRestClient: the existence check and the delete both address the exact name given, no delete is issued when the index is absent, and the method does not lowercase what it receives — which is what makes passing the pre-derived name correct.The lowercasing itself stays covered by the existing paths, since
getIndexStoreNameis now the only derivation and every read and write already depends on it.Also worth a look, not fixed here
Two things I noticed next to this code, both from your issue and both left alone deliberately:
generateIndexStoreNamelowercases, two mixed indexes differing only in case (byNameandbyname) map to the same Elasticsearch index and silently share documents.ManagementSystem.checkIndexNameonly enforces uniqueness on the JanusGraph side. That is a validation change, not a rename, so it belongs in its own PR.RestElasticSearchClient.deleteIndexdoes nothing at all when the name is not an alias, which looks unintended but is a separate concern.For all changes:
master)?For code changes: