use super::builder::StreamingPull;
use super::client_builder::ClientBuilder;
use super::transport::Transport;
use crate::ClientBuilderResult as BuilderResult;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct Subscriber {
inner: Arc<Transport>,
client_id: String,
grpc_subchannel_count: usize,
}
impl Subscriber {
pub fn builder() -> ClientBuilder {
ClientBuilder::new()
}
pub fn streaming_pull<T>(&self, subscription: T) -> StreamingPull
where
T: Into<String>,
{
StreamingPull::new(
self.inner.clone(),
subscription.into(),
self.client_id.clone(),
self.grpc_subchannel_count,
)
}
pub(super) async fn new(builder: ClientBuilder) -> BuilderResult<Self> {
let grpc_subchannel_count =
std::cmp::max(1, builder.config.grpc_subchannel_count.unwrap_or(1));
let transport = Transport::new(builder.config).await?;
Ok(Self {
inner: Arc::new(transport),
client_id: uuid::Uuid::new_v4().to_string(),
grpc_subchannel_count,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use gaxi::grpc::tonic::Status as TonicStatus;
use google_cloud_auth::credentials::anonymous::Builder as Anonymous;
use pubsub_grpc_mock::{MockSubscriber, start};
#[tokio::test]
async fn basic() -> anyhow::Result<()> {
let _ = Subscriber::builder().build().await?;
Ok(())
}
#[tokio::test]
async fn streaming_pull() -> anyhow::Result<()> {
let mut mock = MockSubscriber::new();
mock.expect_streaming_pull()
.return_once(|_| Err(TonicStatus::failed_precondition("fail")));
let (endpoint, _server) = start("0.0.0.0:0", mock).await?;
let client = Subscriber::builder()
.with_endpoint(endpoint)
.with_credentials(Anonymous::new().build())
.build()
.await?;
let err = client
.streaming_pull("projects/p/subscriptions/s")
.start()
.next()
.await
.expect("stream should not be empty")
.expect_err("the first streamed item should be an error");
assert!(err.status().is_some(), "{err:?}");
let status = err.status().unwrap();
assert_eq!(
status.code,
google_cloud_gax::error::rpc::Code::FailedPrecondition
);
assert_eq!(status.message, "fail");
Ok(())
}
#[tokio::test]
async fn grpc_subchannel_count() -> anyhow::Result<()> {
let client = Subscriber::builder()
.with_credentials(Anonymous::new().build())
.build()
.await?;
assert_eq!(client.grpc_subchannel_count, 1);
let client = Subscriber::builder()
.with_credentials(Anonymous::new().build())
.with_grpc_subchannel_count(0)
.build()
.await?;
assert_eq!(client.grpc_subchannel_count, 1);
let client = Subscriber::builder()
.with_credentials(Anonymous::new().build())
.with_grpc_subchannel_count(8)
.build()
.await?;
assert_eq!(client.grpc_subchannel_count, 8);
let builder = client.streaming_pull("projects/p/subscriptions/s");
assert_eq!(builder.grpc_subchannel_count, 8);
Ok(())
}
}