vector_api_client/
client.rs

1use anyhow::Context;
2use graphql_client::GraphQLQuery;
3use url::Url;
4
5use crate::gql::HealthQueryExt;
6
7/// Wrapped `Result` type, that returns deserialized GraphQL response data.
8pub type QueryResult<T> =
9    anyhow::Result<graphql_client::Response<<T as GraphQLQuery>::ResponseData>>;
10
11/// GraphQL query client over HTTP.
12#[derive(Debug)]
13pub struct Client {
14    url: Url,
15}
16
17impl Client {
18    /// Returns a new GraphQL query client, bound to the provided URL.
19    pub fn new(url: Url) -> Self {
20        Self { url }
21    }
22
23    /// Send a health query
24    pub async fn healthcheck(&self) -> Result<(), ()> {
25        self.health_query().await.map(|_| ()).map_err(|_| ())
26    }
27
28    /// Issue a GraphQL query using Reqwest, serializing the response to the associated
29    /// GraphQL type for the given `request_body`.
30    pub async fn query<T: GraphQLQuery>(
31        &self,
32        request_body: &graphql_client::QueryBody<T::Variables>,
33    ) -> QueryResult<T> {
34        let client = reqwest::Client::new();
35
36        client
37            .post(self.url.clone())
38            .json(request_body)
39            .send()
40            .await
41            .with_context(|| {
42                format!(
43                    "Couldn't send '{}' query to {}",
44                    request_body.operation_name,
45                    &self.url.as_str()
46                )
47            })?
48            .json()
49            .await
50            .with_context(|| {
51                format!(
52                    "Couldn't serialize the response for '{}' query: {:?}",
53                    request_body.operation_name, request_body.query
54                )
55            })
56    }
57}