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
No fields configured for issues without a type.

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions