use super::Export;
use crate::processor::{BatchResponse, DiagnosticReport};
use eyre::Result;
use serde::Serialize;
use tokio::sync::{mpsc, oneshot};
#[derive(Clone)]
pub struct StreamExporter {
docs_tx: Option<mpsc::Sender<usize>>,
}
impl Default for StreamExporter {
fn default() -> Self {
Self::new()
}
}
impl StreamExporter {
pub fn new() -> Self {
StreamExporter { docs_tx: None }
}
}
impl Export for StreamExporter {
fn get_docs_rx(&mut self) -> mpsc::Receiver<usize> {
let (tx, rx) = mpsc::channel::<usize>(100);
self.docs_tx = Some(tx);
rx
}
async fn is_connected(&self) -> bool {
true
}
async fn batch_send<T>(&self, index: String, docs: Vec<T>) -> Result<BatchResponse>
where
T: Serialize + Sized + Send + Sync,
{
let start_time = tokio::time::Instant::now();
let doc_count = docs.len() as u32;
let mut batch = BatchResponse::new(doc_count);
batch.status_code = 200;
tracing::debug!("{} wrote {} docs to stdout", index, doc_count);
for doc in docs {
serde_json::to_writer(std::io::stdout(), &doc)?;
println!();
}
batch.size = doc_count;
batch.time = start_time.elapsed().as_millis() as u32;
Ok(batch)
}
async fn batch_tx<T>(&self, index: String, docs: Vec<T>) -> Result<oneshot::Receiver<BatchResponse>>
where
T: Serialize + Sized + Send + Sync + 'static,
{
let (tx, rx) = oneshot::channel();
let doc_count = docs.len() as u32;
match self.batch_send(index, docs).await {
Ok(batch_response) => {
if tx.send(batch_response).is_err() {
tracing::error!("Failed to send batch response");
}
}
Err(e) => {
tracing::warn!("Stream write failed: {}", e);
if tx.send(BatchResponse::failed(doc_count, 0)).is_err() {
tracing::error!("Failed to send failed batch response");
}
}
}
Ok(rx)
}
async fn save_report(&self, report: &DiagnosticReport) -> Result<()> {
println!("{}", serde_json::to_string(report)?);
Ok(())
}
}
impl std::fmt::Display for StreamExporter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "stdout")
}
}