use std::sync::Arc;
use crate::models::{ContinuationToken, CosmosOperation, CosmosResponse};
use super::context::PipelineContext;
use super::node::{PageResult, PipelineNode};
use super::snapshot::PipelineNodeState;
pub(crate) struct Pipeline {
root: Box<dyn PipelineNode>,
}
impl std::fmt::Debug for Pipeline {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Pipeline").finish_non_exhaustive()
}
}
impl Pipeline {
pub(crate) fn new(root: Box<dyn PipelineNode>) -> Self {
debug_assert!(
!root.topology_can_change(),
"pipeline root cannot be a node type that can be affected by topology changes that require splitting or merging"
);
Self { root }
}
#[cfg(test)]
pub(crate) fn root(&self) -> &dyn PipelineNode {
&*self.root
}
#[cfg(test)]
pub(crate) fn into_root(self) -> Box<dyn PipelineNode> {
self.root
}
pub(crate) async fn next_page(
&mut self,
context: &mut PipelineContext<'_>,
) -> crate::error::Result<Option<CosmosResponse>> {
match self.root.next_page(context).await? {
PageResult::Page { response, .. } => Ok(Some(response)),
PageResult::Drained => Ok(None),
PageResult::SplitRequired { .. } => Err(crate::error::CosmosError::builder()
.with_status(crate::error::CosmosStatus::CLIENT_ROOT_NODE_CANNOT_REQUEST_SPLIT)
.with_message(
"root node cannot request a split; splits must be handled by a parent node",
)
.build()),
}
}
pub(crate) fn snapshot_state(&self) -> PipelineNodeState {
self.root.snapshot_state()
}
}
pub struct OperationPlan {
pub(crate) pipeline: Pipeline,
operation: Arc<CosmosOperation>,
}
impl OperationPlan {
pub(crate) fn new(pipeline: Pipeline, operation: Arc<CosmosOperation>) -> Self {
Self {
pipeline,
operation,
}
}
pub fn to_continuation_token(&self) -> crate::error::Result<ContinuationToken> {
ContinuationToken::encode_v1(&self.operation, &self.pipeline.snapshot_state())
}
}