Skip to content

Tracker Checker: handle HTTP Tracker timeouts #679

@josecelano

Description

@josecelano

Parent issue: #677

You can run a Tracker Checker with:

TORRUST_CHECKER_CONFIG='{
    "udp_trackers": [],
    "http_trackers": ["http://127.0.0.1:7070"],
    "health_checks": []
}' cargo run --bin tracker_checker

The HTTP Tracker client does not have any timeout so it will wait forever.

We have to add a timeout to the HTTP client requests:

/// HTTP Tracker Client
pub struct Client {
    base_url: Url,
    reqwest: ReqwestClient,
    key: Option<Key>,
}

impl Client {
    // ...

    pub async fn announce(&self, query: &announce::Query) -> Response {
        self.get(&self.build_announce_path_and_query(query)).await
    }

    pub async fn scrape(&self, query: &scrape::Query) -> Response {
        self.get(&self.build_scrape_path_and_query(query)).await
    }

    pub async fn announce_with_header(&self, query: &Query, key: &str, value: &str) -> Response {
        self.get_with_header(&self.build_announce_path_and_query(query), key, value)
            .await
    }

    pub async fn health_check(&self) -> Response {
        self.get(&self.build_path("health_check")).await
    }

    /// # Panics
    ///
    /// This method fails if there was an error while sending request.
    pub async fn get(&self, path: &str) -> Response {
        self.reqwest.get(self.build_url(path)).send().await.unwrap()
    }

    /// # Panics
    ///
    /// This method fails if there was an error while sending request.
    pub async fn get_with_header(&self, path: &str, key: &str, value: &str) -> Response {
        self.reqwest
            .get(self.build_url(path))
            .header(key, value)
            .send()
            .await
            .unwrap()
    }

    // ...
}

You can add a timeout to all reqwest.get like this in the Health Check:

HttpClient::builder().timeout(Duration::from_secs(5)).build().unwrap();

You can force the error by adding a sleep in the handler:

async fn handle(
    tracker: &Arc<Tracker>,
    announce_request: &Announce,
    client_ip_sources: &ClientIpSources,
    maybe_key: Option<Key>,
) -> Response {
    thread::sleep(time::Duration::from_secs(7));

    let announce_data = match handle_announce(tracker, announce_request, client_ip_sources, maybe_key).await {
        Ok(announce_data) => announce_data,
        Err(error) => return error.into_response(),
    };
    build_response(announce_request, announce_data)
}

This issue should be implemented after refactoring the HTTP Tracker client to return errors instead of panicking.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions