use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use anyhow::{Context, Result};
use async_channel::{Receiver, Sender};
use crate::config::Config;
use crate::storage::Storage;
use crate::types::token::PipelineCancellationToken;
use crate::types::{DeletionStatistics, S3Object};
#[derive(Debug, Clone, PartialEq)]
pub enum SendResult {
Success,
Closed,
}
pub struct Stage {
pub config: Config,
pub target: Storage,
pub receiver: Option<Receiver<S3Object>>,
pub sender: Option<Sender<S3Object>>,
pub cancellation_token: PipelineCancellationToken,
pub has_warning: Arc<AtomicBool>,
}
impl Stage {
pub fn new(
config: Config,
target: Storage,
receiver: Option<Receiver<S3Object>>,
sender: Option<Sender<S3Object>>,
cancellation_token: PipelineCancellationToken,
has_warning: Arc<AtomicBool>,
) -> Self {
Self {
config,
target,
receiver,
sender,
cancellation_token,
has_warning,
}
}
pub async fn send(&self, object: S3Object) -> Result<SendResult> {
let result = self
.sender
.as_ref()
.expect("Stage sender not initialized: this stage cannot send objects")
.send(object)
.await
.context("async_channel::Sender::send() failed.");
if let Err(e) = result {
return if !self.is_channel_closed() {
Err(e)
} else {
Ok(SendResult::Closed)
};
}
Ok(SendResult::Success)
}
pub fn is_channel_closed(&self) -> bool {
self.sender
.as_ref()
.expect("Stage sender not initialized: this stage cannot send objects")
.is_closed()
}
pub async fn send_stats(&self, stats: DeletionStatistics) {
let _ = self.target.get_stats_sender().send(stats).await;
}
pub fn set_warning(&self) {
self.has_warning.store(true, Ordering::SeqCst);
}
}