You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: api.rs
    path of file: ./repos/neon/compute_tools/src/http
    
    the code of the file until where you have to start completion: use std::convert::Infallible;
use std::net::IpAddr;
use std::net::Ipv6Addr;
use std::net::SocketAddr;
use std::sync::Arc;
use std::thread;

use crate::compute::forward_termination_signal;
use crate::compute::{ComputeNode, ComputeState, ParsedSpec};
use compute_api::requests::ConfigurationRequest;
use compute_api::responses::{ComputeStatus, ComputeStatusResponse, GenericAPIError};

use anyhow::Result;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use tokio::task;
use tracing::{error, info, warn};
use tracing_utils::http::OtelName;

fn status_response_from_state(state: &ComputeState) -> ComputeStatusResponse {
    ComputeStatusResponse {
        start_time: state.start_time,
        tenant: state
            .pspec
            .as_ref()
            .map(|pspec| pspec.tenant_id.to_string()),
        timeline: state
            .pspec
            .as_ref()
            .map(|pspec| pspec.timeline_id.to_string()),
        status: state.status,
        last_active: state
    
async fn handle_terminate_request(compute: &Arc<ComputeNode>) -> Result<(), (String, StatusCode)> {
    {
        let mut state = compute.state.lock().unwrap();
        if state.status == ComputeStatus::Terminated {
            return Ok(());
        }
        if state.status != ComputeStatus::Empty && state.status != ComputeStatus::Running {
            let msg = format!(
                "invalid compute status for termination request: {:?}",
                state.status.clone()
            );
            return Err((msg, StatusCode::PRECONDITION_FAILED));
        }
        state.status = ComputeStatus::TerminationPending;
        compute.state_changed.notify_all();
        drop(state);
    }
    forward_termination_signal();
    info!("sent signal and notified waiters");

    // Spawn a blocking thread to wait for compute to become Terminated.
    // This is needed to do not block the main pool of workers and
    // be able to serve other requests while some particular request
    // is waiting for compute to finish configuration.
    let c = compute.clone();
    task::spawn_blocking(move || {
        let mut state = c.state.lock().unwrap();
        while state.status != ComputeStatus::Terminated {
            state = c.state_changed.wait(state).unwrap();
            info!(
                "waiting for compute to become Terminated, current status: {:?}",
                state.status
            );
        }

        Ok(())
    })
    .await
    .unwrap()?;
    info!("terminated Postgres");
    Ok(())
}