diff --git a/shared/comm-lib/src/blob/client.rs b/shared/comm-lib/src/blob/client.rs --- a/shared/comm-lib/src/blob/client.rs +++ b/shared/comm-lib/src/blob/client.rs @@ -16,12 +16,12 @@ use crate::{ auth::{AuthorizationCredential, UserIdentity}, blob::types::http::{ - AssignHolderRequest, AssignHolderResponse, RemoveHolderRequest, - RemoveHoldersRequest, + AssignHolderRequest, AssignHolderResponse, HoldersQueryResponse, + RemoveHolderRequest, RemoveHoldersRequest, }, }; -use super::types::http::RemoveHoldersResponse; +use super::types::http::{BlobInfo, RemoveHoldersResponse}; #[derive(From, Error, Debug, Display)] pub enum BlobServiceError { @@ -260,7 +260,7 @@ } } - let url = self.get_holders_url()?; + let url = self.get_holders_url(None)?; trace!("Request payload: {:?}", request); let response = self .request(Method::DELETE, url)? @@ -280,6 +280,39 @@ Ok(result) } + /// Returns a list of (blob hash; holder) pairs for holders that + /// are in format of `prefix:rest` or their first `tag` + /// is equal to the queried value (NOTE: tags are not yet implemented). + /// Equality check is done server side. Full prefix value must be specified. + /// + /// #### Example _(blob hashes omitted for brevity)_: + /// Given holders in DDB: `["foo:abc", "bar:abc", "foo:123", "foobar:456"]`, + /// querying for `foo` will return: `["foo:abc", "foo:123"]`. + pub async fn query_holders_by_prefix( + &self, + prefix: impl AsRef, + ) -> BlobResult> { + debug!("Query holders by prefix request."); + + let url = self.get_holders_url(Some(prefix.as_ref()))?; + let response = self + .request(Method::GET, url)? + .send() + .await + .map_err(BlobServiceError::ClientError)?; + + if !response.status().is_success() { + return error_response_result(response).await; + } + + let HoldersQueryResponse { items } = response.json().await?; + debug!( + "Request successful. Found {} holders matching prefix.", + items.len() + ); + Ok(items) + } + /// Uploads a blob. Returns `BlobServiceError::AlreadyExists` if blob with given hash /// already exists. /// @@ -402,10 +435,17 @@ Ok(url) } - fn get_holders_url(&self) -> Result { + fn get_holders_url( + &self, + prefix: Option<&str>, + ) -> Result { + let path = match prefix { + Some(prefix) => format!("/holders?prefix={}", prefix), + None => "/holders".to_string(), + }; let url = self .blob_service_url - .join("/holders") + .join(&path) .map_err(|err| BlobServiceError::URLError(err.to_string()))?; trace!("Constructed request URL: {}", url); Ok(url)