fix: refactor region leader state validation (#5626)

* enhance: refactor region leader state validation

* chore: apply suggestions from CR

* chore: add logs
This commit is contained in:
Weny Xu
2025-03-03 18:07:25 +08:00
committed by GitHub
parent e714f7df6c
commit ca81fc6a70
2 changed files with 43 additions and 9 deletions

View File

@@ -490,6 +490,18 @@ pub enum Error {
location: Location,
},
#[snafu(display(
"Region {} is in {:?} state, which does not permit manifest updates.",
region_id,
state
))]
UpdateManifest {
region_id: RegionId,
state: RegionRoleState,
#[snafu(implicit)]
location: Location,
},
#[snafu(display("Region {} is in {:?} state, expect: {:?}", region_id, state, expect))]
RegionLeaderState {
region_id: RegionId,
@@ -1055,7 +1067,7 @@ impl ErrorExt for Error {
CompactRegion { source, .. } => source.status_code(),
CompatReader { .. } => StatusCode::Unexpected,
InvalidRegionRequest { source, .. } => source.status_code(),
RegionLeaderState { .. } => StatusCode::RegionNotReady,
RegionLeaderState { .. } | UpdateManifest { .. } => StatusCode::RegionNotReady,
&FlushableRegionState { .. } => StatusCode::RegionNotReady,
JsonOptions { .. } => StatusCode::InvalidArguments,
EmptyRegionDir { .. } | EmptyManifestDir { .. } => StatusCode::RegionNotFound,

View File

@@ -36,7 +36,7 @@ use store_api::storage::RegionId;
use crate::access_layer::AccessLayerRef;
use crate::error::{
FlushableRegionStateSnafu, RegionLeaderStateSnafu, RegionNotFoundSnafu, RegionTruncatedSnafu,
Result,
Result, UpdateManifestSnafu,
};
use crate::manifest::action::{RegionMetaAction, RegionMetaActionList};
use crate::manifest::manager::RegionManifestManager;
@@ -371,14 +371,36 @@ impl ManifestContext {
// Checks state inside the lock. This is to ensure that we won't update the manifest
// after `set_readonly_gracefully()` is called.
let current_state = self.state.load();
ensure!(
current_state == RegionRoleState::Leader(expect_state),
RegionLeaderStateSnafu {
region_id: manifest.metadata.region_id,
state: current_state,
expect: expect_state,
// If expect_state is not downgrading, the current state must be either `expect_state` or downgrading.
//
// A downgrading leader rejects user writes but still allows
// flushing the memtable and updating the manifest.
if expect_state != RegionLeaderState::Downgrading {
if current_state == RegionRoleState::Leader(RegionLeaderState::Downgrading) {
info!(
"Region {} is in downgrading leader state, updating manifest. state is {:?}",
manifest.metadata.region_id, expect_state
);
}
);
ensure!(
current_state == RegionRoleState::Leader(expect_state)
|| current_state == RegionRoleState::Leader(RegionLeaderState::Downgrading),
UpdateManifestSnafu {
region_id: manifest.metadata.region_id,
state: current_state,
}
);
} else {
ensure!(
current_state == RegionRoleState::Leader(expect_state),
RegionLeaderStateSnafu {
region_id: manifest.metadata.region_id,
state: current_state,
expect: expect_state,
}
);
}
for action in &action_list.actions {
// Checks whether the edit is still applicable.