fix(storcon): correctly handle 404 error in lsn lease (#12537)

## Problem

close LKB-253

## Summary of changes

404 for timeline requests could happen when the tenant is intended to be
on a pageserver but not attached yet. This patch adds handling for the
lease request. In the future, we should extend this handling to more
operations.

---------

Signed-off-by: Alex Chi Z <chi@neon.tech>
This commit is contained in:
Alex Chi Z.
2025-07-10 10:28:58 -04:00
committed by GitHub
parent d33b3c7457
commit be5bbaecad

View File

@@ -4761,6 +4761,7 @@ impl Service {
) )
.await; .await;
let mut retry_if_not_attached = false;
let targets = { let targets = {
let locked = self.inner.read().unwrap(); let locked = self.inner.read().unwrap();
let mut targets = Vec::new(); let mut targets = Vec::new();
@@ -4777,6 +4778,24 @@ impl Service {
.expect("Pageservers may not be deleted while referenced"); .expect("Pageservers may not be deleted while referenced");
targets.push((*tenant_shard_id, node.clone())); targets.push((*tenant_shard_id, node.clone()));
if let Some(location) = shard.observed.locations.get(node_id) {
if let Some(ref conf) = location.conf {
if conf.mode != LocationConfigMode::AttachedSingle
&& conf.mode != LocationConfigMode::AttachedMulti
{
// If the shard is attached as secondary, we need to retry if 404.
retry_if_not_attached = true;
}
// If the shard is attached as primary, we should succeed.
} else {
// Location conf is not available yet, retry if 404.
retry_if_not_attached = true;
}
} else {
// The shard is not attached to the intended pageserver yet, retry if 404.
retry_if_not_attached = true;
}
} }
} }
targets targets
@@ -4807,6 +4826,18 @@ impl Service {
valid_until = Some(lease.valid_until); valid_until = Some(lease.valid_until);
} }
} }
Err(mgmt_api::Error::ApiError(StatusCode::NOT_FOUND, _))
if retry_if_not_attached =>
{
// This is expected if the attach is not finished yet. Return 503 so that the client can retry.
return Err(ApiError::ResourceUnavailable(
format!(
"Timeline is not attached to the pageserver {} yet, please retry",
node.get_id()
)
.into(),
));
}
Err(e) => { Err(e) => {
return Err(passthrough_api_error(&node, e)); return Err(passthrough_api_error(&node, e));
} }