mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-11-14 14:56:54 +00:00
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.