diff --git a/pageserver/src/http/openapi_spec.yml b/pageserver/src/http/openapi_spec.yml index 38e07f172d..b8e44e59c3 100644 --- a/pageserver/src/http/openapi_spec.yml +++ b/pageserver/src/http/openapi_spec.yml @@ -52,6 +52,21 @@ paths: schema: type: object + /v1/deletion_queue/flush_execute: + put: + description: Execute any deletions currently enqueued + security: [] + responses: + "200": + description: | + Flush completed: deletion has been attempted for enqueued objects. This does not guarantee + that deletion executed successfully. + content: + application/json: + schema: + type: object + + /v1/tenant/{tenant_id}: parameters: - name: tenant_id diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs index c65cc84a8e..5435535d02 100644 --- a/pageserver/src/http/routes.rs +++ b/pageserver/src/http/routes.rs @@ -1132,6 +1132,28 @@ async fn always_panic_handler( json_response(StatusCode::NO_CONTENT, ()) } +async fn deletion_queue_flush_execute( + r: Request, + cancel: CancellationToken, +) -> Result, ApiError> { + let state = get_state(&r); + + if let None = state.remote_storage { + // Nothing to do if remote storage is disabled. + return json_response(StatusCode::OK, ()); + } + + let queue_client = state.deletion_queue.new_client(); + tokio::select! { + _ = queue_client.flush_execute()=> { + json_response(StatusCode::OK, ()) + }, + _ = cancel.cancelled() => { + Err(ApiError::ShuttingDown) + } + } +} + async fn disk_usage_eviction_run( mut r: Request, _cancel: CancellationToken, @@ -1456,6 +1478,9 @@ pub fn make_router( .put("/v1/disk_usage_eviction/run", |r| { api_handler(r, disk_usage_eviction_run) }) + .put("/v1/deletion_queue/flush_execute", |r| { + api_handler(r, deletion_queue_flush_execute) + }) .put("/v1/tenant/:tenant_id/break", |r| { testing_api_handler("set tenant state to broken", r, handle_tenant_break) })