blob: 357d575316ae810ed88629fe1771769c104135f5 [file]
use crate::streaming::partitions::partition::Partition;
use crate::streaming::topics::topic::Topic;
use crate::streaming::topics::COMPONENT;
use error_set::ErrContext;
use iggy::error::IggyError;
use iggy::locking::IggySharedMut;
use iggy::locking::IggySharedMutFn;
use iggy::utils::timestamp::IggyTimestamp;
const MAX_PARTITIONS_COUNT: u32 = 100_000;
impl Topic {
pub fn has_partitions(&self) -> bool {
!self.partitions.is_empty()
}
pub fn get_partitions_count(&self) -> u32 {
self.partitions.len() as u32
}
pub async fn add_partitions(&mut self, count: u32) -> Result<Vec<u32>, IggyError> {
if count == 0 {
return Ok(vec![]);
}
let current_partitions_count = self.partitions.len() as u32;
if current_partitions_count + count > MAX_PARTITIONS_COUNT {
return Err(IggyError::TooManyPartitions);
}
let mut partition_ids = Vec::with_capacity(count as usize);
for partition_id in current_partitions_count + 1..=current_partitions_count + count {
let partition = Partition::create(
self.stream_id,
self.topic_id,
partition_id,
true,
self.config.clone(),
self.storage.clone(),
self.message_expiry,
self.messages_count_of_parent_stream.clone(),
self.messages_count.clone(),
self.size_of_parent_stream.clone(),
self.size_bytes.clone(),
self.segments_count_of_parent_stream.clone(),
IggyTimestamp::now(),
)
.await;
self.partitions
.insert(partition_id, IggySharedMut::new(partition));
partition_ids.push(partition_id)
}
Ok(partition_ids)
}
pub async fn add_persisted_partitions(&mut self, count: u32) -> Result<Vec<u32>, IggyError> {
let partition_ids = self
.add_partitions(count)
.await
.with_error_context(|error| {
format!("{COMPONENT} (error: {error}) - failed to add partitions, count: {count}")
})?;
for partition_id in &partition_ids {
let partition = self.partitions.get(partition_id).unwrap();
let mut partition = partition.write().await;
partition.persist().await.with_error_context(|error| {
format!(
"{COMPONENT} (error: {error}) - failed to persist partition with id: {}",
partition.partition_id
)
})?;
}
Ok(partition_ids)
}
pub async fn delete_persisted_partitions(
&mut self,
mut count: u32,
) -> Result<Option<DeletedPartitions>, IggyError> {
if count == 0 {
return Ok(None);
}
let current_partitions_count = self.partitions.len() as u32;
if count > current_partitions_count {
count = current_partitions_count;
}
let mut segments_count = 0;
let mut messages_count = 0;
for partition_id in current_partitions_count - count + 1..=current_partitions_count {
let partition = self.partitions.remove(&partition_id).unwrap();
let mut partition = partition.write().await;
let partition_messages_count = partition.get_messages_count();
segments_count += partition.get_segments_count();
messages_count += partition_messages_count;
partition.delete().await.with_error_context(|error| {
format!(
"{COMPONENT} (error: {error}) - failed to delete partition with ID: {partition_id} in topic with ID: {}",
self.topic_id
)
})?;
}
Ok(Some(DeletedPartitions {
segments_count,
messages_count,
}))
}
}
pub struct DeletedPartitions {
pub segments_count: u32,
pub messages_count: u64,
}