test: force GC API skips precondition checks

Signed-off-by: Alex Chi Z <chi@neon.tech>
This commit is contained in:
Alex Chi Z
2025-07-09 16:12:02 -04:00
parent 0b639ba608
commit 79f5139f0a
4 changed files with 36 additions and 4 deletions

View File

@@ -2221,6 +2221,9 @@ async fn timeline_gc_handler(
) -> Result<Response<Body>, ApiError> {
let tenant_shard_id: TenantShardId = parse_request_param(&request, "tenant_shard_id")?;
let timeline_id: TimelineId = parse_request_param(&request, "timeline_id")?;
let skip_precond_checks =
parse_query_param::<_, bool>(&request, "skip_precond_checks")?.unwrap_or(false);
check_permission(&request, Some(tenant_shard_id.tenant_id))?;
let gc_req: TimelineGcRequest = json_request(&mut request).await?;
@@ -2230,7 +2233,14 @@ async fn timeline_gc_handler(
let ctx = RequestContext::new(TaskKind::MgmtRequest, DownloadBehavior::Download);
let gc_result = state
.tenant_manager
.immediate_gc(tenant_shard_id, timeline_id, gc_req, cancel, &ctx)
.immediate_gc(
tenant_shard_id,
timeline_id,
gc_req,
cancel,
&ctx,
skip_precond_checks,
)
.await?;
json_response(StatusCode::OK, gc_result)

View File

@@ -3075,7 +3075,6 @@ impl TenantShard {
/// `pitr` specifies the same as a time difference from the current time. The effective
/// GC cutoff point is determined conservatively by either `horizon` and `pitr`, whichever
/// requires more history to be retained.
//
pub(crate) async fn gc_iteration(
&self,
target_timeline_id: Option<TimelineId>,
@@ -3083,6 +3082,19 @@ impl TenantShard {
pitr: Duration,
cancel: &CancellationToken,
ctx: &RequestContext,
) -> Result<GcResult, GcError> {
self.gc_iteration_inner(target_timeline_id, horizon, pitr, cancel, ctx, false)
.await
}
pub(crate) async fn gc_iteration_inner(
&self,
target_timeline_id: Option<TimelineId>,
horizon: u64,
pitr: Duration,
cancel: &CancellationToken,
ctx: &RequestContext,
skip_precond_checks: bool,
) -> Result<GcResult, GcError> {
// Don't start doing work during shutdown
if let TenantState::Stopping { .. } = self.current_state() {
@@ -3094,7 +3106,7 @@ impl TenantShard {
return Err(GcError::NotActive);
}
{
if !skip_precond_checks {
let conf = self.tenant_conf.load();
// If we may not delete layers, then simply skip GC. Even though a tenant

View File

@@ -2357,6 +2357,7 @@ impl TenantManager {
gc_req: TimelineGcRequest,
cancel: CancellationToken,
ctx: &RequestContext,
skip_precond_checks: bool,
) -> Result<GcResult, ApiError> {
let tenant = {
let guard = self.tenants.read().unwrap();
@@ -2383,7 +2384,14 @@ impl TenantManager {
#[allow(unused_mut)]
let mut result = tenant
.gc_iteration(Some(timeline_id), gc_horizon, pitr, &cancel, &ctx)
.gc_iteration_inner(
Some(timeline_id),
gc_horizon,
pitr,
&cancel,
&ctx,
skip_precond_checks,
)
.await;
// FIXME: `gc_iteration` can return an error for multiple reasons; we should handle it
// better once the types support it.

View File

@@ -695,6 +695,7 @@ class PageserverHttpClient(requests.Session, MetricsGetter):
tenant_id: TenantId | TenantShardId,
timeline_id: TimelineId,
gc_horizon: int | None,
skip_precond_checks: bool = True,
) -> dict[str, Any]:
"""
Unlike most handlers, this will wait for the layers to be actually
@@ -708,6 +709,7 @@ class PageserverHttpClient(requests.Session, MetricsGetter):
res = self.put(
f"http://localhost:{self.port}/v1/tenant/{tenant_id}/timeline/{timeline_id}/do_gc",
json={"gc_horizon": gc_horizon},
params={"skip_precond_checks": skip_precond_checks},
)
log.info(f"Got GC request response code: {res.status_code}")
self.verbose_error(res)