pub(crate) mod common;
pub mod event;
pub(crate) mod options;
pub mod session;
#[cfg(test)]
use std::collections::VecDeque;
use std::{
pin::Pin,
task::{Context, Poll},
};
use derive_where::derive_where;
use futures_core::Stream;
use futures_util::FutureExt;
use serde::de::DeserializeOwned;
#[cfg(test)]
use tokio::sync::oneshot;
use crate::{
change_stream::event::ResumeToken,
cursor::poll_state::{poll_panic, PollState},
error::Result,
Cursor,
};
use common::{ChangeStreamData, WatchArgs};
#[derive_where(Debug)]
pub struct ChangeStream<T>
where
T: DeserializeOwned,
{
inner: ChangeStreamState<T>,
}
impl<T> ChangeStream<T>
where
T: DeserializeOwned,
{
pub(crate) fn new(cursor: Cursor<()>, args: WatchArgs, data: ChangeStreamData) -> Self {
Self {
inner: PollState::new(Box::new(CursorWrapper::new(cursor, args, data))),
}
}
pub fn resume_token(&self) -> Option<ResumeToken> {
poll_panic!(self.inner.state()).data.resume_token.clone()
}
pub fn with_type<D: DeserializeOwned>(self) -> ChangeStream<D> {
ChangeStream {
inner: PollState::new(poll_panic!(self.inner.into_state())),
}
}
pub fn is_alive(&self) -> bool {
!poll_panic!(self.inner.state().and_then(|state| state.cursor.raw())).is_exhausted()
}
pub async fn next_if_any(&mut self) -> Result<Option<T>> {
Ok(self
.inner
.state_mut()?
.next_if_any(&mut ())
.await?
.into_option())
}
#[cfg(test)]
pub(crate) fn set_kill_watcher(&mut self, tx: oneshot::Sender<()>) -> Result<()> {
self.inner
.state_mut()?
.cursor
.raw_mut()?
.set_kill_watcher(tx);
Ok(())
}
#[cfg(test)]
pub(crate) fn current_batch(&self) -> Result<&VecDeque<crate::bson::RawDocumentBuf>> {
self.inner.state()?.cursor.batch()
}
#[cfg(test)]
pub(crate) fn client(&self) -> Result<&crate::Client> {
Ok(self.inner.state()?.cursor.raw()?.client())
}
}
impl<T> Stream for ChangeStream<T>
where
T: DeserializeOwned,
{
type Item = Result<T>;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.get_mut().inner.poll_next_step(
cx,
|mut state| {
async move {
let out = state.next_event(&mut ()).await;
(state, out)
}
.boxed()
},
|_, out| out.transpose(),
)
}
}
type CursorWrapper = common::CursorWrapper<Cursor<()>>;
type ChangeStreamState<T> = PollState<'static, Box<CursorWrapper>, Result<Option<T>>>;
impl common::InnerCursor for Cursor<()> {
type Session = ();
async fn try_advance(
&mut self,
_session: &mut Self::Session,
) -> Result<crate::cursor::stream::AdvanceResult> {
self.try_advance().await
}
fn get_resume_token(&self) -> Result<Option<ResumeToken>> {
common::get_resume_token(self.batch()?, self.raw()?.post_batch_resume_token())
}
fn current(&self) -> &crate::bson::RawDocument {
self.current()
}
async fn execute_watch(
&mut self,
args: WatchArgs,
mut data: ChangeStreamData,
_session: &mut Self::Session,
) -> Result<(Self, WatchArgs)> {
data.implicit_session = self.raw_mut()?.take_implicit_session();
let client = self.raw()?.client().clone();
let new_stream: ChangeStream<event::ChangeStreamEvent<()>> = client
.execute_watch(args.pipeline, args.options, args.target, Some(data))
.await?;
let new_wrapper = new_stream.inner.into_state()?;
Ok((new_wrapper.cursor, new_wrapper.args))
}
fn set_drop_address(&mut self, from: &Self) -> Result<()> {
self.raw_mut()?
.set_drop_address(from.raw()?.address().clone());
Ok(())
}
}