Skip to content

feat: Add new TaskLockType KILL for embedded kill tasks - #19921

Merged
kfaraz merged 20 commits into
apache:masterfrom
kfaraz:no_lock_for_kill
Aug 12, 2026
Merged

feat: Add new TaskLockType KILL for embedded kill tasks#19921
kfaraz merged 20 commits into
apache:masterfrom
kfaraz:no_lock_for_kill

Conversation

@kfaraz

@kfaraz kfaraz commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

This has been split from #19772 .

Instead of acquiring a lock for markAsUsed and markAsUnused APIs (as it may potentially hamper ingestion),
this patch tries to relax the locking requirements of a kill task and adds restrictions on the window for markAsUsed.

Changes

  • Add new TaskLockType.KILL
  • This lock can coexist with any other lock type but not with another KILL lock to ensure that only a single kill task is working on a single datasource-interval
  • This lock type can currently be used only by embedded kill tasks so that the UnusedSegmentsKiller does not skip intervals with active ingestion.
  • Inject the SegmentsMetadataManagerConfig into SqlSegmentsMetadataQuery.
  • Do not allow a segment to be marked as used if it was last updated earlier than the buffer period. This ensures that an unused segment that is now eligible for kill is not accidentally marked as used while a kill task for that segment is in progress.
  • Add methods in SegmentMetadataTransactionFactory to provide read-write transactions which do not use the segment metadata cache. This moves away the transaction creation logic from IndexerSQLMetadataStorageCoordinator to the transaction factory and reduces the number of call sites that create a SqlSegmentsMetadataQuery.
  • Add tests

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

kfaraz and others added 2 commits August 7, 2026 13:20
Introduces a new KILL lock type that can coexist with all other lock
types (EXCLUSIVE, SHARED, REPLACE, APPEND) but not with another KILL
lock on an overlapping interval. Only tasks of type "kill" are permitted
to acquire a KILL lock. UnusedSegmentsKiller's embedded kill task now
uses KILL locking by default, allowing concurrent ingest tasks to
proceed while unused segments are being deleted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kfaraz and others added 3 commits August 7, 2026 22:51
Tests verify that a KILL lock can be acquired, released, and revoked
for tasks that are never inserted into TaskStorage (the embedded kill
task pattern used by UnusedSegmentsKiller). Specifically:
- Acquire + release without task in storage unblocks the next acquirer
- Lock is not restored after syncFromStorage (task not persisted)
- Higher-priority kill task not in storage can revoke a lower-priority one
- KILL lock coexists with other lock types held by persisted tasks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kfaraz and others added 3 commits August 9, 2026 14:52
Add tests to SqlSegmentsMetadataQueryTest covering the
validateSegmentsForMarkingAsUsed guard:
- throws CONFLICT when kill is enabled and segment was updated before buffer period
- succeeds when kill is enabled but segment was updated within buffer period
- succeeds when kill is disabled regardless of how old the update time is
- covers markSegmentAsUsed, markNonOvershadowedSegmentsAsUsed, and
  markAllNonOvershadowedSegmentsAsUsed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@kfaraz
kfaraz marked this pull request as ready for review August 9, 2026 14:51
@kfaraz
kfaraz requested a review from gianm August 9, 2026 14:51

@FrankChen021 FrankChen021 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Severity Findings
P0 0
P1 0
P2 1
P3 0
Total 1

Reviewed 35 of 35 changed files.


This is an automated review by Codex GPT-5.6-Luna(max)

Map.of(Tasks.PRIORITY_KEY, Tasks.DEFAULT_EMBEDDED_KILL_TASK_PRIORITY),
Map.of(
Tasks.PRIORITY_KEY, Tasks.DEFAULT_EMBEDDED_KILL_TASK_PRIORITY,
Tasks.TASK_LOCK_TYPE, TaskLockType.KILL.name()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] KILL locks incorrectly suppress compaction

The compaction duty reports active locks through getLockedIntervals, which includes this priority-25 KILL lock even though KILL is designed to coexist with compaction locks. Compatible intervals are consequently deferred while a kill task is active. Make lock reporting honor lock compatibility and add a regression test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Addressed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Confirmed fixed at this head: getLockedIntervals now ignores KILL locks for non-KILL requests, with regression coverage. I reviewed all 37 changed files and found no additional issues.

Comment on lines +1042 to +1049
throw DruidException.forPersona(DruidException.Persona.OPERATOR)
.ofCategory(DruidException.Category.CONFLICT)
.build(
"Segment IDs[%s] cannot be marked as used since"
+ " they were last updated more than [%s] ago and"
+ " are now eligible for permanent deletion.",
expiredSegmentIds, bufferPeriod
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

does this new restriction need to be in docs? perhaps in the properties table that describes what the buffer period is and what happens after the segment ages out of the buffer?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

documenting depends a lot on the outcome of my comment above related to only enforcing this when using embedded kill

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I think we should document it either way (at least for embedded kill tasks).

Comment on lines +1026 to +1029
if (!managerConfig.getKillUnused().isEnabled()) {
// Do not verify the buffer period if embedded kill tasks are not enabled
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmmm. do we really need to introduce this exception to the rule? Having the whole system opted into the new restriction about how long a segment can be unused before not being eligible to mark used seems less sconfusing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I started with that. But then I realized that the bufferPeriod config makes sense only when embedded kill is enabled, since the UnusedSegmentKillerConfig.bufferPeriod does not apply to regular kill tasks.

throw new ISE("Unable to grant LockPosse to inactive Task [%s]", task.getId());
}

if (request.getType() == TaskLockType.KILL && !KillUnusedSegmentsTask.TYPE.equals(task.getType())) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

so manually submitted kill tasks can use the kill lock type, as far as I can tell at least. is that acceptable?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this is on purpose but I see the problem. If we wanted to use the KILL lock type for manual kill tasks, we would also need to do the validation on mark-as-used even if embedded kill was disabled.

I don't see a clear way to do that, except maybe always honoring the bufferPeriod.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated this to allow KILL locks only for embedded kill tasks.

@kfaraz

kfaraz commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @capistrant !
I decided to use the new KILL lock type only for embedded kill tasks and also do the markAsUsed validation only when embedded kill is enabled.
This would be an additional incentive for users to try out the embedded kill tasks.

@capistrant capistrant left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for responses to my questions and comments. looks good to me.

@FrankChen021 FrankChen021 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have reviewed the code for correctness, edge cases, concurrency, and integration risks; no issues found.

Reviewed 38 of 38 changed files.


This is an automated review by Codex GPT-5.6-Luna(max)

@kfaraz
kfaraz merged commit 978de63 into apache:master Aug 12, 2026
45 of 46 checks passed
@kfaraz
kfaraz deleted the no_lock_for_kill branch August 12, 2026 16:21
@github-actions github-actions Bot added this to the 39.0.0 milestone Aug 12, 2026
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.

4 participants