use std::marker::PhantomData;
use crate::{
amqp::amqp_consumer::EventStream,
authorization::{event_hub_token_credential::EventHubTokenCredential, AzureNamedKeyCredential, AzureSasCredential},
core::BasicRetryPolicy,
event_hubs_properties::EventHubProperties,
event_hubs_retry_policy::EventHubsRetryPolicy,
EventHubConnection, EventHubsRetryOptions,
};
use super::{EventHubConsumerClientOptions, EventPosition, ReadEventOptions};
#[derive(Debug)]
pub struct EventHubConsumerClient<RP> {
connection: EventHubConnection,
retry_policy_marker: PhantomData<RP>,
options: EventHubConsumerClientOptions,
consumer_group: String,
}
impl EventHubConsumerClient<BasicRetryPolicy> {
pub const DEFAULT_CONSUMER_GROUP_NAME: &'static str = "$Default";
pub fn with_policy<P>() -> EventHubConsumerClientBuilder<P>
where
P: EventHubsRetryPolicy + Send,
{
EventHubConsumerClientBuilder {
_retry_policy_marker: PhantomData,
}
}
pub async fn new_from_connection_string(
consumer_group: impl Into<String>,
connection_string: impl Into<String>,
event_hub_name: impl Into<Option<String>>,
client_options: EventHubConsumerClientOptions,
) -> Result<Self, azure_core::Error> {
Self::with_policy()
.new_from_connection_string(
consumer_group,
connection_string,
event_hub_name,
client_options,
)
.await
}
pub async fn new_from_credential(
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: impl Into<EventHubTokenCredential>,
client_options: EventHubConsumerClientOptions,
) -> Result<Self, azure_core::Error> {
Self::with_policy()
.new_from_credential(
consumer_group,
fully_qualified_namespace,
event_hub_name,
credential,
client_options,
)
.await
}
pub async fn new_from_named_key_credential(
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: AzureNamedKeyCredential,
client_options: EventHubConsumerClientOptions,
) -> Result<Self, azure_core::Error> {
Self::with_policy()
.new_from_named_key_credential(
consumer_group,
fully_qualified_namespace,
event_hub_name,
credential,
client_options,
)
.await
}
pub async fn new_from_sas_credential(
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: AzureSasCredential,
client_options: EventHubConsumerClientOptions,
) -> Result<Self, azure_core::Error> {
Self::with_policy()
.new_from_sas_credential(
consumer_group,
fully_qualified_namespace,
event_hub_name,
credential,
client_options,
)
.await
}
pub fn with_connection(
consumer_group: impl Into<String>,
connection: &mut EventHubConnection,
client_options: EventHubConsumerClientOptions,
) -> Self {
Self::with_policy().with_connection(consumer_group, connection, client_options)
}
}
#[derive(Debug)]
pub struct EventHubConsumerClientBuilder<RP> {
_retry_policy_marker: PhantomData<RP>,
}
impl<RP> EventHubConsumerClientBuilder<RP> {
pub async fn new_from_connection_string(
self,
consumer_group: impl Into<String>,
connection_string: impl Into<String>,
event_hub_name: impl Into<Option<String>>,
client_options: EventHubConsumerClientOptions,
) -> Result<EventHubConsumerClient<RP>, azure_core::Error>
where
RP: EventHubsRetryPolicy + Send,
{
let connection = EventHubConnection::new_from_connection_string(
connection_string.into(),
event_hub_name.into(),
client_options.connection_options.clone(),
)
.await?;
Ok(EventHubConsumerClient {
connection,
retry_policy_marker: PhantomData,
options: client_options,
consumer_group: consumer_group.into(),
})
}
pub async fn new_from_credential(
self,
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: impl Into<EventHubTokenCredential>,
client_options: EventHubConsumerClientOptions,
) -> Result<EventHubConsumerClient<RP>, azure_core::Error>
where
RP: EventHubsRetryPolicy + Send,
{
let connection = EventHubConnection::new_from_credential(
fully_qualified_namespace.into(),
event_hub_name.into(),
credential.into(),
client_options.connection_options.clone(),
)
.await?;
Ok(EventHubConsumerClient {
connection,
retry_policy_marker: PhantomData,
options: client_options,
consumer_group: consumer_group.into(),
})
}
pub async fn new_from_named_key_credential(
self,
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: AzureNamedKeyCredential,
client_options: EventHubConsumerClientOptions,
) -> Result<EventHubConsumerClient<RP>, azure_core::Error>
where
RP: EventHubsRetryPolicy + Send,
{
let connection = EventHubConnection::new_from_named_key_credential(
fully_qualified_namespace.into(),
event_hub_name.into(),
credential,
client_options.connection_options.clone(),
)
.await?;
Ok(EventHubConsumerClient {
connection,
retry_policy_marker: PhantomData,
options: client_options,
consumer_group: consumer_group.into(),
})
}
pub async fn new_from_sas_credential(
self,
consumer_group: impl Into<String>,
fully_qualified_namespace: impl Into<String>,
event_hub_name: impl Into<String>,
credential: AzureSasCredential,
client_options: EventHubConsumerClientOptions,
) -> Result<EventHubConsumerClient<RP>, azure_core::Error>
where
RP: EventHubsRetryPolicy + Send,
{
let connection = EventHubConnection::new_from_sas_credential(
fully_qualified_namespace.into(),
event_hub_name.into(),
credential,
client_options.connection_options.clone(),
)
.await?;
Ok(EventHubConsumerClient {
connection,
retry_policy_marker: PhantomData,
options: client_options,
consumer_group: consumer_group.into(),
})
}
pub fn with_connection(
self,
consumer_group: impl Into<String>,
connection: &mut EventHubConnection,
client_options: EventHubConsumerClientOptions,
) -> EventHubConsumerClient<RP> {
EventHubConsumerClient {
connection: connection.clone_as_shared(),
retry_policy_marker: PhantomData,
options: client_options,
consumer_group: consumer_group.into(),
}
}
}
impl<RP> EventHubConsumerClient<RP>
where
RP: EventHubsRetryPolicy + From<EventHubsRetryOptions> + Send + Unpin,
{
pub async fn get_event_hub_properties(
&mut self,
) -> Result<EventHubProperties, azure_core::Error> {
self.connection
.get_properties(RP::from(self.options.retry_options.clone()))
.await
}
pub async fn get_partition_ids(&mut self) -> Result<Vec<String>, azure_core::Error> {
self.connection
.get_partition_ids(RP::from(self.options.retry_options.clone()))
.await
}
pub async fn get_partition_properties(
&mut self,
partition_id: &str,
) -> Result<crate::PartitionProperties, azure_core::Error> {
self.connection
.get_partition_properties(partition_id, RP::from(self.options.retry_options.clone()))
.await
}
pub async fn read_events_from_partition(
&mut self,
partition_id: &str,
starting_position: EventPosition,
read_event_options: ReadEventOptions,
) -> Result<EventStream<'_, RP>, azure_core::Error> {
let consumer = self
.connection
.create_transport_consumer(
&self.consumer_group,
partition_id,
self.options.identifier.clone(),
starting_position,
RP::from(self.options.retry_options.clone()),
read_event_options.track_last_enqueued_event_properties,
read_event_options.owner_level,
Some(read_event_options.prefetch_count),
)
.await?;
let event_stream = EventStream::with_consumer(
&mut self.connection.inner,
consumer,
);
Ok(event_stream)
}
pub async fn read_events(
&mut self,
start_reading_at_earliest_event: bool,
read_event_options: ReadEventOptions,
) -> Result<EventStream<'_, RP>, azure_core::Error>
where
RP: 'static,
{
let starting_position = match start_reading_at_earliest_event {
true => EventPosition::earliest(),
false => EventPosition::latest(),
};
let retry_policy = RP::from(self.options.retry_options.clone());
let partitions = self.connection.get_partition_ids(retry_policy).await?;
let mut consumers = Vec::with_capacity(partitions.len());
for partition in partitions {
let retry_policy = RP::from(self.options.retry_options.clone());
let consumer = self
.connection
.create_transport_consumer(
&self.consumer_group,
&partition,
self.options.identifier.clone(),
starting_position.clone(),
retry_policy,
read_event_options.track_last_enqueued_event_properties,
read_event_options.owner_level,
Some(read_event_options.prefetch_count),
)
.await?;
consumers.push(consumer);
}
let retry_policy = RP::from(self.options.retry_options.clone());
let event_stream = EventStream::with_multiple_consumers(
&mut self.connection.inner,
consumers,
retry_policy,
);
Ok(event_stream)
}
pub async fn close(self) -> Result<(), azure_core::Error> {
self.connection.close_if_owned().await
}
}