Gouzi Mohaled
Ajout du dossier lib
84d2a97
use core::marker::{Send, Sync};
use std::future::{self, Future};
use std::path::Path;
use common::tar_ext;
use common::types::TelemetryDetail;
use segment::types::SnapshotFormat;
use super::local_shard::clock_map::RecoveryPoint;
use super::update_tracker::UpdateTracker;
use crate::operations::types::{CollectionError, CollectionResult};
use crate::shards::dummy_shard::DummyShard;
use crate::shards::forward_proxy_shard::ForwardProxyShard;
use crate::shards::local_shard::LocalShard;
use crate::shards::proxy_shard::ProxyShard;
use crate::shards::queue_proxy_shard::QueueProxyShard;
use crate::shards::shard_trait::ShardOperation;
use crate::shards::telemetry::LocalShardTelemetry;
pub type ShardId = u32;
pub type PeerId = u64;
/// List of peers that should be used to place replicas of a shard
pub type ShardReplicasPlacement = Vec<PeerId>;
/// List of shards placements. Each element defines placements of replicas for a single shard.
///
/// Number of elements corresponds to the number of shards.
/// Example: [
/// [1, 2],
/// [2, 3],
/// [3, 4]
/// ] - 3 shards, each has 2 replicas
pub type ShardsPlacement = Vec<ShardReplicasPlacement>;
/// Shard
///
/// Contains a part of the collection's points
pub enum Shard {
Local(LocalShard),
Proxy(ProxyShard),
ForwardProxy(ForwardProxyShard),
QueueProxy(QueueProxyShard),
Dummy(DummyShard),
}
impl Shard {
pub fn variant_name(&self) -> &str {
match self {
Shard::Local(_) => "local shard",
Shard::Proxy(_) => "proxy shard",
Shard::ForwardProxy(_) => "forward proxy shard",
Shard::QueueProxy(_) => "queue proxy shard",
Shard::Dummy(_) => "dummy shard",
}
}
pub fn get(&self) -> &(dyn ShardOperation + Sync + Send + '_) {
match self {
Shard::Local(local_shard) => local_shard,
Shard::Proxy(proxy_shard) => proxy_shard,
Shard::ForwardProxy(proxy_shard) => proxy_shard,
Shard::QueueProxy(proxy_shard) => proxy_shard,
Shard::Dummy(dummy_shard) => dummy_shard,
}
}
pub async fn get_telemetry_data(&self, detail: TelemetryDetail) -> LocalShardTelemetry {
let mut telemetry = match self {
Shard::Local(local_shard) => {
let mut shard_telemetry = local_shard.get_telemetry_data(detail);
// can't take sync locks in async fn so local_shard_status() has to be
// called outside get_telemetry_data()
shard_telemetry.status = Some(local_shard.local_shard_status().await.0);
shard_telemetry
}
Shard::Proxy(proxy_shard) => proxy_shard.get_telemetry_data(detail),
Shard::ForwardProxy(proxy_shard) => proxy_shard.get_telemetry_data(detail),
Shard::QueueProxy(proxy_shard) => proxy_shard.get_telemetry_data(detail),
Shard::Dummy(dummy_shard) => dummy_shard.get_telemetry_data(),
};
telemetry.variant_name = Some(self.variant_name().to_string());
telemetry
}
pub async fn create_snapshot(
&self,
temp_path: &Path,
tar: &tar_ext::BuilderExt,
format: SnapshotFormat,
save_wal: bool,
) -> CollectionResult<()> {
match self {
Shard::Local(local_shard) => {
local_shard
.create_snapshot(temp_path, tar, format, save_wal)
.await
}
Shard::Proxy(proxy_shard) => {
proxy_shard
.create_snapshot(temp_path, tar, format, save_wal)
.await
}
Shard::ForwardProxy(proxy_shard) => {
proxy_shard
.create_snapshot(temp_path, tar, format, save_wal)
.await
}
Shard::QueueProxy(proxy_shard) => {
proxy_shard
.create_snapshot(temp_path, tar, format, save_wal)
.await
}
Shard::Dummy(dummy_shard) => {
dummy_shard
.create_snapshot(temp_path, tar, format, save_wal)
.await
}
}
}
pub async fn on_optimizer_config_update(&self) -> CollectionResult<()> {
match self {
Shard::Local(local_shard) => local_shard.on_optimizer_config_update().await,
Shard::Proxy(proxy_shard) => proxy_shard.on_optimizer_config_update().await,
Shard::ForwardProxy(proxy_shard) => proxy_shard.on_optimizer_config_update().await,
Shard::QueueProxy(proxy_shard) => proxy_shard.on_optimizer_config_update().await,
Shard::Dummy(dummy_shard) => dummy_shard.on_optimizer_config_update().await,
}
}
pub fn trigger_optimizers(&self) {
match self {
Shard::Local(local_shard) => local_shard.trigger_optimizers(),
Shard::Proxy(proxy_shard) => proxy_shard.trigger_optimizers(),
Shard::ForwardProxy(forward_proxy_shard) => {
forward_proxy_shard.trigger_optimizers();
}
Shard::QueueProxy(queue_proxy_shard) => queue_proxy_shard.trigger_optimizers(),
Shard::Dummy(_) => (),
}
}
pub fn is_update_in_progress(&self) -> bool {
self.update_tracker()
.map_or(false, UpdateTracker::is_update_in_progress)
}
pub fn watch_for_update(&self) -> impl Future<Output = ()> {
let update_watcher = self.update_tracker().map(UpdateTracker::watch_for_update);
async move {
match update_watcher {
Some(update_watcher) => update_watcher.await,
None => future::pending().await,
}
}
}
fn update_tracker(&self) -> Option<&UpdateTracker> {
let update_tracker = match self {
Self::Local(local_shard) => local_shard.update_tracker(),
Self::Proxy(proxy_shard) => proxy_shard.update_tracker(),
Self::ForwardProxy(proxy_shard) => proxy_shard.update_tracker(),
Self::QueueProxy(proxy_shard) => proxy_shard.update_tracker(),
Self::Dummy(_) => return None,
};
Some(update_tracker)
}
pub async fn shard_recovery_point(&self) -> CollectionResult<RecoveryPoint> {
match self {
Self::Local(local_shard) => Ok(local_shard.recovery_point().await),
Self::ForwardProxy(proxy_shard) => Ok(proxy_shard.wrapped_shard.recovery_point().await),
Self::Proxy(_) | Self::QueueProxy(_) | Self::Dummy(_) => {
Err(CollectionError::service_error(format!(
"Recovery point not supported on {}",
self.variant_name(),
)))
}
}
}
pub async fn update_cutoff(&self, cutoff: &RecoveryPoint) -> CollectionResult<()> {
match self {
Self::Local(local_shard) => local_shard.update_cutoff(cutoff).await,
Self::Proxy(_) | Self::ForwardProxy(_) | Self::QueueProxy(_) | Self::Dummy(_) => {
return Err(CollectionError::service_error(format!(
"Setting cutoff point not supported on {}",
self.variant_name(),
)));
}
}
Ok(())
}
pub async fn resolve_wal_delta(
&self,
recovery_point: RecoveryPoint,
) -> CollectionResult<Option<u64>> {
let wal = match self {
Self::Local(local_shard) => &local_shard.wal,
Self::Proxy(_) | Self::ForwardProxy(_) | Self::QueueProxy(_) | Self::Dummy(_) => {
return Err(CollectionError::service_error(format!(
"Cannot resolve WAL delta on {}",
self.variant_name(),
)));
}
};
// Resolve WAL delta and report
match wal.resolve_wal_delta(recovery_point).await {
Ok(Some(version)) => {
log::debug!(
"Resolved WAL delta from {version}, which counts {} records",
wal.wal.lock().last_index().saturating_sub(version),
);
Ok(Some(version))
}
Ok(None) => {
log::debug!("Resolved WAL delta that is empty");
Ok(None)
}
Err(err) => Err(CollectionError::service_error(format!(
"Failed to resolve WAL delta on local shard: {err}"
))),
}
}
pub fn wal_version(&self) -> CollectionResult<Option<u64>> {
match self {
Self::Local(local_shard) => local_shard.wal.wal_version().map_err(|err| {
CollectionError::service_error(format!(
"Cannot get WAL version on {}: {err}",
self.variant_name(),
))
}),
Self::Proxy(_) | Self::ForwardProxy(_) | Self::QueueProxy(_) | Self::Dummy(_) => {
Err(CollectionError::service_error(format!(
"Cannot get WAL version on {}",
self.variant_name(),
)))
}
}
}
}