Skip to content

feat: Implement write-only index state that is not considered for read queries#4919

Open
porunov wants to merge 1 commit into
JanusGraph:masterfrom
porunov:feature/index-states-redesign
Open

feat: Implement write-only index state that is not considered for read queries#4919
porunov wants to merge 1 commit into
JanusGraph:masterfrom
porunov:feature/index-states-redesign

Conversation

@porunov

@porunov porunov commented Jul 13, 2026

Copy link
Copy Markdown
Member

Add SchemaStatus.WRITE_ONLY_ENABLED and SchemaAction.ENABLE_WRITE_ONLY. An index in this state receives updates for all graph mutations but is not used to answer queries, and SchemaAction.REINDEX preserves this state instead of automatically enabling the index. This enables the workflow "create index -> reindex it without enabling -> enable it later when necessary", as well as demoting an ENABLED index to write-only and re-enabling it later without a reindex.

Additional lifecycle extensions (no changes to existing workflows):

  • DISABLE_INDEX can be applied to an INSTALLED index, allowing an index to be created and disabled in the same management transaction so that it never receives writes until explicitly activated.
  • REGISTER_INDEX can be applied to a DISABLED index to re-activate it for writes with the registration barrier required for a lossless reindex.
  • ENABLE_INDEX, DISCARD_INDEX and MARK_DISCARDED accept WRITE_ONLY_ENABLED.
  • A pending index registration no longer overwrites a status change that superseded it (e.g. disabling an index while its registration acknowledgement is still pending).

WRITE_ONLY_ENABLED is appended at the end of SchemaStatus because the status is persisted by its ordinal.

The documentation of the index lifecycle is rewritten to reflect the actual write behavior of the existing states (INSTALLED and REGISTERED indexes have always received graph updates; queries only ever use ENABLED indexes) and now includes the write-only workflows and an updated state transition diagram.

Fixes #4894 follow-up; supersedes the docs-only draft of that PR.


Thank you for contributing to JanusGraph!

In order to streamline the review of the contribution we ask you
to ensure the following steps have been taken:

For all changes:

  • Is there an issue associated with this PR? Is it referenced in the commit message?
  • Does your PR body contain #xyz where xyz is the issue number you are trying to resolve?
  • Has your PR been rebased against the latest commit within the target branch (typically master)?
  • Is your initial contribution a single, squashed commit?

For code changes:

  • Have you written and/or updated unit tests to verify your changes?
  • If adding new dependencies to the code, are these dependencies licensed in a way that is compatible for inclusion under ASF 2.0?
  • If applicable, have you updated the LICENSE.txt file, including the main LICENSE.txt file in the root of this repository?
  • If applicable, have you updated the NOTICE.txt file, including the main NOTICE.txt file found in the root of this repository?

For documentation related changes:

  • Have you ensured that format looks appropriate for the output in which it is rendered?

@porunov porunov added this to the 1.2.0 milestone Jul 13, 2026
@porunov porunov requested a review from Copilot July 13, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends JanusGraph’s index lifecycle with an explicit write-only state so indexes can receive mutation updates while being excluded from query planning, and reindexing can be performed without forcing query enablement. It updates core management logic, adds comprehensive lifecycle tests, and rewrites the index lifecycle documentation to match actual behavior.

Changes:

  • Add SchemaStatus.WRITE_ONLY_ENABLED and SchemaAction.ENABLE_WRITE_ONLY, and preserve write-only status across REINDEX.
  • Extend lifecycle transitions (DISABLE_INDEX, REGISTER_INDEX, ENABLE_INDEX, DISCARD_INDEX, MARK_DISCARDED) to include WRITE_ONLY_ENABLED and support create-then-disable / re-register workflows.
  • Add backend tests and update docs (lifecycle diagram, lifecycle narrative, reindexing docs, changelog) to document and validate the new workflows.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
janusgraph-core/src/main/java/org/janusgraph/graphdb/olap/job/IndexRemoveJob.java Allows index removal precondition to accept WRITE_ONLY_ENABLED.
janusgraph-core/src/main/java/org/janusgraph/graphdb/database/management/ManagementSystem.java Implements ENABLE_WRITE_ONLY, preserves write-only state after REINDEX, and hardens pending registration handshake behavior.
janusgraph-core/src/main/java/org/janusgraph/core/schema/SchemaStatus.java Adds WRITE_ONLY_ENABLED (appended to preserve ordinal persistence) and clarifies status semantics.
janusgraph-core/src/main/java/org/janusgraph/core/schema/SchemaAction.java Adds ENABLE_WRITE_ONLY and broadens action applicability sets for the new lifecycle transitions.
janusgraph-backend-testutils/src/main/java/org/janusgraph/graphdb/JanusGraphTest.java Adds lifecycle tests for deferred enablement, demotion/promotion, and create-disabled-then-activate workflows.
janusgraph-backend-testutils/src/main/java/org/janusgraph/graphdb/JanusGraphIndexTest.java Adds mixed-index tests covering write-only behavior and create-disabled behavior.
docs/schema/index-management/index-reindexing.md Documents reindex auto-enable exception for write-only indexes and updates example errors.
docs/schema/index-management/index-lifecycle.svg Updates lifecycle diagram to include write-only state and new transitions.
docs/schema/index-management/index-lifecycle.md Rewrites lifecycle docs to reflect actual write behavior and adds write-only workflows.
docs/changelog.md Adds changelog entry documenting the new status/action, workflow implications, and downgrade warning.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread janusgraph-core/src/main/java/org/janusgraph/graphdb/olap/job/IndexRemoveJob.java Outdated
porunov added a commit to porunov/janusgraph that referenced this pull request Jul 14, 2026
The message claimed the index "must be disabled" although REGISTERED,
DISCARDED and (since the write-only feature) WRITE_ONLY_ENABLED are also
accepted. Derive the accepted statuses from
SchemaAction.DISCARD_INDEX.getApplicableStatus() - mirroring how
IndexRepairJob derives its accepted statuses from SchemaAction.REINDEX -
so the job validation and the action applicability can no longer drift
apart, and report that set in the error message.

Addresses Copilot review feedback on JanusGraph#4919.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6JuYe7uEs3dbr7MSPUtr2
Signed-off-by: Oleksandr Porunov <alexandr.porunov@gmail.com>
@porunov porunov requested a review from Copilot July 14, 2026 16:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 1 comment.

…d queries

Add SchemaStatus.WRITE_ONLY_ENABLED and SchemaAction.ENABLE_WRITE_ONLY.
An index in this state receives updates for all graph mutations but is not
used to answer queries, and SchemaAction.REINDEX preserves this state
instead of automatically enabling the index. This enables the workflow
"create index -> reindex it without enabling -> enable it later when
necessary", as well as demoting an ENABLED index to write-only and
re-enabling it later without a reindex. WRITE_ONLY_ENABLED is appended at
the end of SchemaStatus because the status is persisted by its ordinal.

Additional lifecycle extensions (no changes to existing workflows):
- DISABLE_INDEX can be applied to an INSTALLED index, allowing an index to
  be created and disabled in the same management transaction so that it
  never receives writes until explicitly activated.
- REGISTER_INDEX can be applied to a DISABLED index to re-activate it for
  writes with the registration barrier required for a lossless reindex.
- ENABLE_INDEX, DISCARD_INDEX and MARK_DISCARDED accept WRITE_ONLY_ENABLED.
- A pending index registration no longer overwrites a status change that
  superseded it (e.g. disabling an index while its registration
  acknowledgement is still pending).

Add SchemaAction.REMOVE_STALE_ENTRIES which removes index entries that
reference graph elements that no longer exist, for example because the
element was deleted while an index status change was still propagating
through the cluster or while the index was disabled. The action complements
REINDEX: a reindex restores missing entries for existing elements but never
removes entries, while REMOVE_STALE_ENTRIES removes entries of deleted
elements but never adds entries. Composite graph indexes are cleaned by the
new StaleIndexEntryRemoveJob which scans the internal index store; mixed
graph indexes are cleaned by the new MixedIndexStaleEntryRemover which
enumerates the documents through exists-queries against the index backend
and deletes stale documents in batches, running on a background thread
behind the new (cancellable) CompletableScanJobFuture. Removed and examined
entries are reported through the ScanMetrics custom metrics
"stale-entries-removed" and "scanned-entries". Vertex-centric indexes are
not supported by this action.

The index lifecycle documentation is rewritten to reflect the actual write
behavior of the existing states (INSTALLED and REGISTERED indexes have
always received graph updates; queries only ever use ENABLED indexes), now
includes the write-only workflows, an updated state transition diagram and
a new section about consistency during status transitions, and the
IndexRemoveJob validation error message reports the accepted statuses
derived from SchemaAction.DISCARD_INDEX instead of a stale hardcoded text.

Fixes JanusGraph#4894 follow-up; supersedes the docs-only draft of that PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6JuYe7uEs3dbr7MSPUtr2
Signed-off-by: Oleksandr Porunov <alexandr.porunov@gmail.com>
@porunov porunov force-pushed the feature/index-states-redesign branch from 69ad23a to a6af806 Compare July 14, 2026 16:24
@porunov porunov requested a review from Copilot July 14, 2026 16:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Comment on lines +47 to +58
@Override
public ScanMetrics getIntermediateResult() throws ExecutionException {
if (future.isCompletedExceptionally()) {
try {
future.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ExecutionException(e);
}
}
return intermediateMetrics;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants