Files
greptimedb/src
Lei, HUANG 024714b1b5 fix(mito2): remove stale compaction status when next compaction is throttled (#8618)
I hereby agree to the terms of the [GreptimeDB
CLA](https://github.com/GreptimeTeam/.github/blob/main/CLA.md).

## Refer to a related PR or issue link (optional)

Fixes #8617

## What's changed and what's your intention?

**Summary:** Fixes a mito2 compaction scheduler bug where a region
permanently stops compacting after a finished compaction when
`min_compaction_interval` is configured to a non-zero value.

**Root cause:**

1. `CompactionScheduler::on_compaction_finished` falls through without
removing the region's `CompactionStatus` when there is no pending manual
request and no pending DDL, leaving a status with `active_compaction =
None` in `region_status`.
2. Back in `RegionWorkerLoop::handle_compaction_finished`,
`is_compacting()` is now `false`, but the follow-up
`schedule_next_compaction` (whose `Ok(None)` branch is the only normal
path that removes the status) is gated by `min_compaction_interval`.
Since the scheduling timestamp was already updated when the task was
scheduled, a compaction that finishes within the interval skips this
cleanup, and the stale status remains forever.
3. From then on, every compaction trigger hits the "status exists"
branch of `CompactionScheduler::schedule_compaction`, which does not
check whether a compaction is actually active: regular requests are
merged into `status.waiters` (never woken until close/drop/failure) and
manual `StrictWindow` requests are parked in `status.pending_request`
(never executed). The region never compacts again until restart and SSTs
keep accumulating.

Note this only manifests with `min_compaction_interval > 0`; with the
default `0` the gate always passes and `schedule_next_compaction` cleans
up the status.

**How this PR works:**

- Adds `CompactionScheduler::remove_inactive_status(region_id)`, which
removes the status only when it has no active compaction. A
`debug_assert!` guards the invariant that such a status has no
waiters/pending requests/pending DDLs (they can only be enqueued while a
compaction is active, and the worker loop is strictly sequential).
- Calls it from `handle_compaction_finished` when the
`min_compaction_interval` gate skips `schedule_next_compaction`,
restoring the invariant that a status in the map always has an active
compaction. The throttling semantics are unchanged: the next trigger
still has to wait for the interval to pass.

**Tests:**

- `test_remove_inactive_status_keeps_running_compaction`: status with an
active compaction (or no status) is never removed.
- `test_compaction_reschedulable_when_next_compaction_throttled`:
reproduces the reported flow — schedule, finish (stale status remains),
remove it as the throttled worker path does, and verify the region can
be scheduled for compaction again.

**Compatibility:** no API, persisted-format, or wire-format changes;
internal scheduler behavior only.

## PR Checklist
Please convert it to a draft if some of the following conditions are not
met.

- [x] I have written the necessary rustdoc comments.
- [x] I have added the necessary unit tests and integration tests.
- [ ] This PR requires documentation updates.
- [x] API changes are backward compatible.
- [x] Schema or data changes are backward compatible.
2026-07-23 12:03:11 +00:00
..
2026-05-25 08:51:40 +00:00