use super::builder::Append;
use super::dispatcher::Dispatcher;
use super::format::DataFormat;
use super::pool::StreamPool;
use super::retry_policy::RetryOptions;
use std::sync::Arc;
#[derive(Debug)]
pub struct DefaultWriter<F> {
pub(crate) inner: Arc<Dispatcher>,
pub(crate) write_stream: String,
pub(crate) format: F,
}
impl<F> DefaultWriter<F>
where
F: DataFormat,
{
pub(crate) fn new(
pool: Arc<StreamPool>,
retry_options: RetryOptions,
write_stream: String,
format: F,
) -> Self {
let inner = Arc::new(Dispatcher::new(pool, retry_options));
Self {
inner,
write_stream,
format,
}
}
pub fn append(&self, rows: F::Rows) -> Append {
let req = self.format.make_request(&self.write_stream, rows);
Append::new(self.inner.clone(), req)
}
}
#[cfg(test)]
mod tests {
use super::super::pool::StreamPoolOptions;
use super::*;
use crate::error::AppendError;
use crate::write::test::*;
use bigquery_grpc_mock::{MockBigQueryWrite, start};
use gaxi::grpc::tonic::{Response as TonicResponse, Status as TonicStatus};
use tokio::sync::mpsc;
#[tokio::test]
async fn basic_success() -> anyhow::Result<()> {
let (response_tx, response_rx) = mpsc::channel(10);
let mut mock = MockBigQueryWrite::new();
mock.expect_append_rows()
.return_once(|_| Ok(TonicResponse::from(response_rx)));
let (endpoint, _server) = start("0.0.0.0:0", mock).await?;
let transport = Arc::new(test_transport(endpoint).await?);
let pool = Arc::new(StreamPool::new(transport, StreamPoolOptions::default()));
let writer = DefaultWriter::new(pool, test_retry_options(), write_stream(), format());
response_tx.send(Ok(convert(&test_response(1)))).await?;
let resp = writer.append(rows(1)).send().await?;
assert_eq!(resp.offset, Some(1));
response_tx.send(Ok(convert(&test_response(2)))).await?;
let resp = writer.append(rows(2)).send().await?;
assert_eq!(resp.offset, Some(2));
response_tx.send(Ok(convert(&test_response(3)))).await?;
let resp = writer.append(rows(3)).send().await?;
assert_eq!(resp.offset, Some(3));
response_tx
.send(Err(TonicStatus::failed_precondition("fail")))
.await?;
let err = writer.append(rows(4)).send().await.expect_err("fail");
assert!(matches!(err, AppendError::Rpc { source: _ }), "{err:?}");
Ok(())
}
}