diff --git a/driver/src/operation.rs b/driver/src/operation.rs index 9e7e189a9..7233d1224 100644 --- a/driver/src/operation.rs +++ b/driver/src/operation.rs @@ -126,10 +126,8 @@ impl Retryability { } } -/// A trait modeling the behavior of a server side operation. -/// -/// No methods in this trait should have default behaviors to ensure that wrapper operations -/// replicate all behavior. Default behavior is provided by the `OperationDefault` trait. +/// A trait modeling the behavior of a server side operation. This should not be implemented +/// directly; use either the `BaseOperation` or `WrappedOperation` traits. pub(crate) trait Operation { /// The output type of this operation. type O; @@ -291,9 +289,9 @@ impl From<&Collection> for OperationTarget { } } -// A mirror of the `Operation` trait, with default behavior where appropriate. Should only be +// A mirror of the `Operation` trait, with default behavior where appropriate. Should be // implemented by operation types that do not delegate to other operations. -pub(crate) trait OperationWithDefaults: Send + Sync { +pub(crate) trait BaseOperation: Send + Sync { /// The output type of this operation. type O; @@ -411,66 +409,193 @@ pub(crate) trait OperationWithDefaults: Send + Sync { type Otel: crate::otel::OtelWitness; } -impl Operation for T +/// We'd like both `BaseOperation` and `WrappedOperation` to automatically implement `Operation`. +/// However, Rust only allows one blanket impl per trait, so we can't do both +/// `impl Operation for T` and `impl Operation for T`. +/// +/// To work around this, `OperationDispatch` provides an indirection: the one blanket impl for +/// `Operation` is a generic `OperationDispatch`, and each specialized version of the trait +/// has a blanket impl for `OperationDispatch` with a specific type parameter. +/// +/// `OperationImpl` is a helper trait for this setup that binds specific impls to the appropriate +/// dispatch type. +pub(crate) trait OperationDispatch { + type O; + const NAME: &'static CStr; + const ZERO_COPY: bool; + fn build(&mut self, description: &StreamDescription) -> Result; + fn extract_at_cluster_time(&self, response: &RawDocument) -> Result>; + fn handle_response<'a>( + &'a self, + response: Cow<'a, RawCommandResponse>, + context: ExecutionContext<'a>, + ) -> BoxFuture<'a, Result>; + fn handle_error(&self, error: Error) -> Result; + fn selection_criteria(&self) -> Feature<&SelectionCriteria>; + fn read_concern(&self) -> Feature<&ReadConcern>; + fn write_concern(&self) -> Feature<&WriteConcern>; + fn supports_sessions(&self) -> bool; + fn retryability(&self, options: &ClientOptions) -> Retryability; + fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool; + fn update_for_retry(&mut self, retry: Option<&Retry>); + fn override_criteria(&self) -> OverrideCriteriaFn; + fn pinned_connection(&self) -> Option<&PinnedConnectionHandle>; + fn name(&self) -> &CStr; + fn target(&self) -> OperationTarget; + #[cfg(feature = "opentelemetry")] + type Otel: crate::otel::OtelWitness; +} + +macro_rules! operation_dispatch { + ($trait:path, $tag:ty, $handle_response:ident) => { + impl OperationDispatch<$tag> for T { + operation_dispatch_body! { $trait, $handle_response } + } + }; +} + +macro_rules! operation_dispatch_body { + ($trait:path, $handle_response:ident) => { + type O = ::O; + const NAME: &'static CStr = ::NAME; + const ZERO_COPY: bool = ::ZERO_COPY; + fn build(&mut self, description: &StreamDescription) -> Result { + ::build(self, description) + } + fn extract_at_cluster_time(&self, response: &RawDocument) -> Result> { + ::extract_at_cluster_time(self, response) + } + fn handle_response<'a>( + &'a self, + response: Cow<'a, RawCommandResponse>, + context: ExecutionContext<'a>, + ) -> BoxFuture<'a, Result> { + ::$handle_response(self, response, context) + } + fn handle_error(&self, error: Error) -> Result { + ::handle_error(self, error) + } + fn selection_criteria(&self) -> Feature<&SelectionCriteria> { + ::selection_criteria(self) + } + fn read_concern(&self) -> Feature<&ReadConcern> { + ::read_concern(self) + } + fn write_concern(&self) -> Feature<&WriteConcern> { + ::write_concern(self) + } + fn supports_sessions(&self) -> bool { + ::supports_sessions(self) + } + fn retryability(&self, options: &ClientOptions) -> Retryability { + ::retryability(self, options) + } + fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool { + ::is_backpressure_retryable(self, options) + } + fn update_for_retry(&mut self, retry: Option<&Retry>) { + ::update_for_retry(self, retry) + } + fn override_criteria(&self) -> OverrideCriteriaFn { + ::override_criteria(self) + } + fn pinned_connection(&self) -> Option<&PinnedConnectionHandle> { + ::pinned_connection(self) + } + fn name(&self) -> &CStr { + ::name(self) + } + fn target(&self) -> OperationTarget { + ::target(self) + } + #[cfg(feature = "opentelemetry")] + type Otel = ::Otel; + }; +} + +pub(crate) trait OperationImpl { + type Kind; +} + +impl Operation for T where - T: Send + Sync, + T: OperationImpl + OperationDispatch + Send + Sync, { - type O = T::O; - const NAME: &'static CStr = T::NAME; - const ZERO_COPY: bool = T::ZERO_COPY; - fn build(&mut self, description: &StreamDescription) -> Result { - self.build(description) - } - fn extract_at_cluster_time(&self, response: &RawDocument) -> Result> { - self.extract_at_cluster_time(response) - } + operation_dispatch_body! { OperationDispatch, handle_response } +} + +pub(crate) struct Base; + +operation_dispatch! { BaseOperation, Base, handle_response_async } + +/// A trait for operations that delegate most behavior to another wrapped operation. +pub(crate) trait WrappedOperation { + // Required + type Wrapped: Operation; + type O; + #[cfg(feature = "opentelemetry")] + type Otel: crate::otel::OtelWitness; + + fn wrapped(&self) -> &Self::Wrapped; + fn wrapped_mut(&mut self) -> &mut Self::Wrapped; + fn handle_response<'a>( &'a self, response: Cow<'a, RawCommandResponse>, context: ExecutionContext<'a>, - ) -> BoxFuture<'a, Result> { - self.handle_response_async(response, context) + ) -> BoxFuture<'a, Result>; + + // Delegated to wrapped + const NAME: &'static CStr = Self::Wrapped::NAME; + const ZERO_COPY: bool = Self::Wrapped::ZERO_COPY; + fn build(&mut self, description: &StreamDescription) -> Result { + self.wrapped_mut().build(description) } fn handle_error(&self, error: Error) -> Result { - self.handle_error(error) + Err(error) + } + fn extract_at_cluster_time(&self, response: &RawDocument) -> Result> { + self.wrapped().extract_at_cluster_time(response) } fn selection_criteria(&self) -> Feature<&SelectionCriteria> { - self.selection_criteria() + self.wrapped().selection_criteria() } fn read_concern(&self) -> Feature<&ReadConcern> { - self.read_concern() + self.wrapped().read_concern() } fn write_concern(&self) -> Feature<&WriteConcern> { - self.write_concern() + self.wrapped().write_concern() } fn supports_sessions(&self) -> bool { - self.supports_sessions() + self.wrapped().supports_sessions() } fn retryability(&self, options: &ClientOptions) -> Retryability { - self.retryability(options) + self.wrapped().retryability(options) } fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool { - self.is_backpressure_retryable(options) + self.wrapped().is_backpressure_retryable(options) } fn update_for_retry(&mut self, retry: Option<&Retry>) { - self.update_for_retry(retry) + self.wrapped_mut().update_for_retry(retry); } fn override_criteria(&self) -> OverrideCriteriaFn { - self.override_criteria() + self.wrapped().override_criteria() } fn pinned_connection(&self) -> Option<&PinnedConnectionHandle> { - self.pinned_connection() + self.wrapped().pinned_connection() } fn name(&self) -> &CStr { - self.name() + self.wrapped().name() } fn target(&self) -> OperationTarget { - self.target() + self.wrapped().target() } - #[cfg(feature = "opentelemetry")] - type Otel = ::Otel; } +pub(crate) struct Wrapped; + +operation_dispatch! { WrappedOperation, Wrapped, handle_response } + fn should_redact_body(body: &RawDocumentBuf) -> bool { if let Some(Ok((command_name, _))) = body.into_iter().next() { HELLO_COMMAND_NAMES.contains(command_name.to_lowercase().as_str()) diff --git a/driver/src/operation/abort_transaction.rs b/driver/src/operation/abort_transaction.rs index 8277f7e6f..cddd55f29 100644 --- a/driver/src/operation/abort_transaction.rs +++ b/driver/src/operation/abort_transaction.rs @@ -4,12 +4,12 @@ use crate::{ client::{session::TransactionPin, Retry}, cmap::{conn::PinnedConnectionHandle, Command, RawCommandResponse, StreamDescription}, error::Result, - operation::Retryability, + operation::{Base, OperationImpl, Retryability}, options::{ClientOptions, SelectionCriteria, WriteConcern}, Client, }; -use super::{ExecutionContext, OperationWithDefaults, WriteConcernOnlyBody}; +use super::{BaseOperation, ExecutionContext, WriteConcernOnlyBody}; pub(crate) struct AbortTransaction { write_concern: Option, @@ -31,7 +31,7 @@ impl AbortTransaction { } } -impl OperationWithDefaults for AbortTransaction { +impl BaseOperation for AbortTransaction { type O = (); const NAME: &'static CStr = cstr!("abortTransaction"); @@ -89,5 +89,9 @@ impl OperationWithDefaults for AbortTransaction { type Otel = crate::otel::Witness; } +impl OperationImpl for AbortTransaction { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for AbortTransaction {} diff --git a/driver/src/operation/aggregate.rs b/driver/src/operation/aggregate.rs index 6c6d0da45..c6a4b9a59 100644 --- a/driver/src/operation/aggregate.rs +++ b/driver/src/operation/aggregate.rs @@ -7,16 +7,11 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, cursor::common::CursorSpecification, error::Result, - operation::{append_options, OperationTarget, Retryability}, + operation::{append_options, Base, OperationImpl, OperationTarget, Retryability}, options::{AggregateOptions, ClientOptions, ReadPreference, SelectionCriteria, WriteConcern}, }; -use super::{ - ExecutionContext, - OperationWithDefaults, - WriteConcernOnlyBody, - SERVER_4_4_0_WIRE_VERSION, -}; +use super::{BaseOperation, ExecutionContext, WriteConcernOnlyBody, SERVER_4_4_0_WIRE_VERSION}; #[derive(Debug)] pub(crate) struct Aggregate { @@ -51,7 +46,7 @@ impl Aggregate { // IMPORTANT: If new method implementations are added here, make sure `ChangeStreamAggregate` has // the equivalent delegations. -impl OperationWithDefaults for Aggregate { +impl BaseOperation for Aggregate { type O = CursorSpecification; const NAME: &'static CStr = cstr!("aggregate"); @@ -177,6 +172,10 @@ impl OperationWithDefaults for Aggregate { type Otel = crate::otel::Witness; } +impl OperationImpl for Aggregate { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Aggregate { fn output_cursor_id(output: &Self::O) -> Option { diff --git a/driver/src/operation/aggregate/change_stream.rs b/driver/src/operation/aggregate/change_stream.rs index 7b66a045a..8922b8067 100644 --- a/driver/src/operation/aggregate/change_stream.rs +++ b/driver/src/operation/aggregate/change_stream.rs @@ -4,12 +4,18 @@ use crate::{ common::{ChangeStreamData, WatchArgs}, event::ResumeToken, }, - client::Retry, cmap::{Command, RawCommandResponse, StreamDescription}, cursor::common::CursorSpecification, error::Result, - operation::{append_options, ExecutionContext, Operation, Retryability}, - options::{ChangeStreamOptions, ClientOptions, SelectionCriteria, WriteConcern}, + operation::{ + append_options, + ExecutionContext, + Operation, + OperationImpl, + Wrapped, + WrappedOperation, + }, + options::ChangeStreamOptions, }; use super::Aggregate; @@ -43,12 +49,18 @@ impl ChangeStreamAggregate { } } -impl Operation for ChangeStreamAggregate { +impl WrappedOperation for ChangeStreamAggregate { + type Wrapped = Aggregate; type O = (CursorSpecification, ChangeStreamData); + const ZERO_COPY: bool = true; - const NAME: &'static crate::bson_compat::CStr = Aggregate::NAME; + fn wrapped(&self) -> &Self::Wrapped { + &self.inner + } - const ZERO_COPY: bool = true; + fn wrapped_mut(&mut self) -> &mut Self::Wrapped { + &mut self.inner + } fn build(&mut self, description: &StreamDescription) -> Result { if let Some(data) = &mut self.resume_data { @@ -80,13 +92,6 @@ impl Operation for ChangeStreamAggregate { self.inner.build(description) } - fn extract_at_cluster_time( - &self, - response: &crate::bson::RawDocument, - ) -> Result> { - self.inner.extract_at_cluster_time(response) - } - fn handle_response<'a>( &'a self, response: std::borrow::Cow<'a, RawCommandResponse>, @@ -105,7 +110,7 @@ impl Operation for ChangeStreamAggregate { effective_criteria: context.effective_criteria, }; let spec = { - use crate::operation::OperationWithDefaults; + use crate::operation::BaseOperation; self.inner.handle_response_cow(response, inner_context)? }; @@ -133,57 +138,13 @@ impl Operation for ChangeStreamAggregate { .boxed() } - fn selection_criteria(&self) -> crate::operation::Feature<&SelectionCriteria> { - self.inner.selection_criteria() - } - - fn write_concern(&self) -> crate::operation::Feature<&WriteConcern> { - self.inner.write_concern() - } - - fn retryability(&self, options: &ClientOptions) -> Retryability { - self.inner.retryability(options) - } - - fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool { - self.inner.is_backpressure_retryable(options) - } - - fn target(&self) -> crate::operation::OperationTarget { - self.inner.target() - } - - fn handle_error(&self, error: crate::error::Error) -> Result { - Err(error) - } - - fn read_concern(&self) -> crate::operation::Feature<&crate::options::ReadConcern> { - self.inner.read_concern() - } - - fn supports_sessions(&self) -> bool { - self.inner.supports_sessions() - } - - fn update_for_retry(&mut self, retry: Option<&Retry>) { - self.inner.update_for_retry(retry); - } - - fn override_criteria(&self) -> crate::operation::OverrideCriteriaFn { - self.inner.override_criteria() - } - - fn pinned_connection(&self) -> Option<&crate::cmap::conn::PinnedConnectionHandle> { - self.inner.pinned_connection() - } - - fn name(&self) -> &crate::bson_compat::CStr { - self.inner.name() - } - #[cfg(feature = "opentelemetry")] type Otel = crate::otel::Witness; } +impl OperationImpl for ChangeStreamAggregate { + type Kind = Wrapped; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for ChangeStreamAggregate {} diff --git a/driver/src/operation/bulk_write.rs b/driver/src/operation/bulk_write.rs index d95a96646..5aa99f876 100644 --- a/driver/src/operation/bulk_write.rs +++ b/driver/src/operation/bulk_write.rs @@ -16,8 +16,10 @@ use crate::{ error::{BulkWriteError, Error, ErrorKind, Result}, operation::{ run_command::RunCommand, + Base, + BaseOperation, GetMore, - OperationWithDefaults, + OperationImpl, MAX_ENCRYPTED_WRITE_SIZE, }, options::{BulkWriteOptions, ClientOptions, OperationType, WriteModel}, @@ -341,7 +343,7 @@ where } } -impl OperationWithDefaults for BulkWrite<'_, R> +impl BaseOperation for BulkWrite<'_, R> where R: BulkWriteResult, { @@ -528,5 +530,9 @@ where type Otel = crate::otel::Witness; } +impl OperationImpl for BulkWrite<'_, R> { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for BulkWrite<'_, R> {} diff --git a/driver/src/operation/commit_transaction.rs b/driver/src/operation/commit_transaction.rs index 291b7b04e..1e8541329 100644 --- a/driver/src/operation/commit_transaction.rs +++ b/driver/src/operation/commit_transaction.rs @@ -6,7 +6,7 @@ use crate::{ client::Retry, cmap::{Command, RawCommandResponse, StreamDescription}, error::Result, - operation::{append_options_to_raw_document, OperationWithDefaults, Retryability}, + operation::{append_options_to_raw_document, Base, BaseOperation, OperationImpl, Retryability}, options::{Acknowledgment, ClientOptions, TransactionOptions, WriteConcern}, Client, }; @@ -27,7 +27,7 @@ impl CommitTransaction { } } -impl OperationWithDefaults for CommitTransaction { +impl BaseOperation for CommitTransaction { type O = (); const NAME: &'static CStr = cstr!("commitTransaction"); @@ -96,5 +96,9 @@ impl OperationWithDefaults for CommitTransaction { type Otel = crate::otel::Witness; } +impl OperationImpl for CommitTransaction { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for CommitTransaction {} diff --git a/driver/src/operation/count.rs b/driver/src/operation/count.rs index 09ef28da2..9e39c0341 100644 --- a/driver/src/operation/count.rs +++ b/driver/src/operation/count.rs @@ -1,5 +1,6 @@ use crate::{ bson::rawdoc, + operation::{Base, OperationImpl}, options::{ClientOptions, SelectionCriteria}, Collection, }; @@ -11,7 +12,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, coll::options::EstimatedDocumentCountOptions, error::{Error, Result}, - operation::{OperationWithDefaults, Retryability}, + operation::{BaseOperation, Retryability}, }; use super::{append_options_to_raw_document, ExecutionContext}; @@ -30,7 +31,7 @@ impl Count { } } -impl OperationWithDefaults for Count { +impl BaseOperation for Count { type O = u64; const NAME: &'static CStr = cstr!("count"); @@ -88,6 +89,10 @@ impl OperationWithDefaults for Count { type Otel = crate::otel::Witness; } +impl OperationImpl for Count { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Count {} diff --git a/driver/src/operation/count_documents.rs b/driver/src/operation/count_documents.rs index 86a8af143..99a16a5e3 100644 --- a/driver/src/operation/count_documents.rs +++ b/driver/src/operation/count_documents.rs @@ -3,12 +3,11 @@ use std::convert::TryInto; use serde::Deserialize; use crate::{ - bson::{doc, Document, RawDocument}, - client::Retry, - cmap::{Command, RawCommandResponse, StreamDescription}, + bson::{doc, Document}, + cmap::RawCommandResponse, error::{Error, ErrorKind, Result}, - operation::{aggregate::Aggregate, Operation}, - options::{AggregateOptions, ClientOptions, CountOptions, SelectionCriteria}, + operation::{aggregate::Aggregate, OperationImpl, Wrapped, WrappedOperation}, + options::{AggregateOptions, ClientOptions, CountOptions}, }; use super::{ExecutionContext, Retryability, SingleCursorResult}; @@ -73,22 +72,17 @@ impl CountDocuments { } } -impl Operation for CountDocuments { +impl WrappedOperation for CountDocuments { + type Wrapped = Aggregate; type O = u64; - - const NAME: &'static crate::bson_compat::CStr = Aggregate::NAME; - const ZERO_COPY: bool = false; - fn build(&mut self, description: &StreamDescription) -> Result { - self.aggregate.build(description) + fn wrapped(&self) -> &Self::Wrapped { + &self.aggregate } - fn extract_at_cluster_time( - &self, - response: &RawDocument, - ) -> Result> { - self.aggregate.extract_at_cluster_time(response) + fn wrapped_mut(&mut self) -> &mut Self::Wrapped { + &mut self.aggregate } fn handle_response<'a>( @@ -104,10 +98,6 @@ impl Operation for CountDocuments { .boxed() } - fn selection_criteria(&self) -> super::Feature<&SelectionCriteria> { - self.aggregate.selection_criteria() - } - fn retryability(&self, options: &ClientOptions) -> Retryability { Retryability::read(options) } @@ -116,46 +106,14 @@ impl Operation for CountDocuments { options.retry_reads != Some(false) } - fn target(&self) -> super::OperationTarget { - self.aggregate.target() - } - - fn read_concern(&self) -> super::Feature<&crate::options::ReadConcern> { - self.aggregate.read_concern() - } - - fn handle_error(&self, error: Error) -> Result { - Err(error) - } - - fn write_concern(&self) -> super::Feature<&crate::options::WriteConcern> { - self.aggregate.write_concern() - } - - fn supports_sessions(&self) -> bool { - self.aggregate.supports_sessions() - } - - fn update_for_retry(&mut self, retry: Option<&Retry>) { - self.aggregate.update_for_retry(retry); - } - - fn override_criteria(&self) -> super::OverrideCriteriaFn { - self.aggregate.override_criteria() - } - - fn pinned_connection(&self) -> Option<&crate::cmap::conn::PinnedConnectionHandle> { - self.aggregate.pinned_connection() - } - - fn name(&self) -> &crate::bson_compat::CStr { - self.aggregate.name() - } - #[cfg(feature = "opentelemetry")] type Otel = crate::otel::Witness; } +impl OperationImpl for CountDocuments { + type Kind = Wrapped; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for CountDocuments {} diff --git a/driver/src/operation/create.rs b/driver/src/operation/create.rs index dc45bdda0..dd410855d 100644 --- a/driver/src/operation/create.rs +++ b/driver/src/operation/create.rs @@ -5,7 +5,13 @@ use crate::{ bson_compat::{cstr, CStr}, cmap::{Command, RawCommandResponse, StreamDescription}, error::Result, - operation::{append_options_to_raw_document, OperationWithDefaults, WriteConcernOnlyBody}, + operation::{ + append_options_to_raw_document, + Base, + BaseOperation, + OperationImpl, + WriteConcernOnlyBody, + }, options::{CreateCollectionOptions, WriteConcern}, }; @@ -26,7 +32,7 @@ impl Create { } } -impl OperationWithDefaults for Create { +impl BaseOperation for Create { type O = (); const NAME: &'static CStr = cstr!("create"); @@ -65,6 +71,10 @@ impl OperationWithDefaults for Create { type Otel = crate::otel::Witness; } +impl OperationImpl for Create { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Create { fn log_name(&self) -> &str { diff --git a/driver/src/operation/create_indexes.rs b/driver/src/operation/create_indexes.rs index 5a97c2cd3..9e35805ea 100644 --- a/driver/src/operation/create_indexes.rs +++ b/driver/src/operation/create_indexes.rs @@ -7,7 +7,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, error::{ErrorKind, Result}, index::IndexModel, - operation::{append_options_to_raw_document, OperationWithDefaults}, + operation::{append_options_to_raw_document, Base, BaseOperation, OperationImpl}, options::{CreateIndexOptions, WriteConcern}, results::CreateIndexesResult, }; @@ -35,7 +35,7 @@ impl CreateIndexes { } } -impl OperationWithDefaults for CreateIndexes { +impl BaseOperation for CreateIndexes { type O = CreateIndexesResult; const NAME: &'static CStr = cstr!("createIndexes"); @@ -97,5 +97,9 @@ impl OperationWithDefaults for CreateIndexes { type Otel = crate::otel::Witness; } +impl OperationImpl for CreateIndexes { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for CreateIndexes {} diff --git a/driver/src/operation/delete.rs b/driver/src/operation/delete.rs index ee289ad21..28596fcf1 100644 --- a/driver/src/operation/delete.rs +++ b/driver/src/operation/delete.rs @@ -4,7 +4,14 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, collation::Collation, error::{convert_insert_many_error, Result}, - operation::{append_options, OperationWithDefaults, Retryability, WriteResponseBody}, + operation::{ + append_options, + Base, + BaseOperation, + OperationImpl, + Retryability, + WriteResponseBody, + }, options::{ClientOptions, DeleteOptions, Hint, WriteConcern}, results::DeleteResult, Collection, @@ -40,7 +47,7 @@ impl Delete { } } -impl OperationWithDefaults for Delete { +impl BaseOperation for Delete { type O = DeleteResult; const NAME: &'static CStr = cstr!("delete"); @@ -113,5 +120,9 @@ impl OperationWithDefaults for Delete { type Otel = crate::otel::Witness; } +impl OperationImpl for Delete { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Delete {} diff --git a/driver/src/operation/distinct.rs b/driver/src/operation/distinct.rs index 8ea17420f..8407b94ce 100644 --- a/driver/src/operation/distinct.rs +++ b/driver/src/operation/distinct.rs @@ -6,7 +6,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, coll::options::DistinctOptions, error::Result, - operation::{OperationWithDefaults, Retryability}, + operation::{Base, BaseOperation, OperationImpl, Retryability}, options::{ClientOptions, SelectionCriteria}, Collection, }; @@ -36,7 +36,7 @@ impl Distinct { } } -impl OperationWithDefaults for Distinct { +impl BaseOperation for Distinct { type O = Vec; const NAME: &'static CStr = cstr!("distinct"); @@ -97,6 +97,10 @@ impl OperationWithDefaults for Distinct { type Otel = crate::otel::Witness; } +impl OperationImpl for Distinct { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Distinct {} diff --git a/driver/src/operation/drop_collection.rs b/driver/src/operation/drop_collection.rs index f3194a5a2..fd8c46fc5 100644 --- a/driver/src/operation/drop_collection.rs +++ b/driver/src/operation/drop_collection.rs @@ -5,7 +5,13 @@ use crate::{ bson_compat::{cstr, CStr}, cmap::{Command, RawCommandResponse, StreamDescription}, error::{Error, Result}, - operation::{append_options_to_raw_document, OperationWithDefaults, WriteConcernOnlyBody}, + operation::{ + append_options_to_raw_document, + Base, + BaseOperation, + OperationImpl, + WriteConcernOnlyBody, + }, options::{DropCollectionOptions, WriteConcern}, }; @@ -26,7 +32,7 @@ impl DropCollection { } } -impl OperationWithDefaults for DropCollection { +impl BaseOperation for DropCollection { type O = (); const NAME: &'static CStr = cstr!("drop"); @@ -73,6 +79,10 @@ impl OperationWithDefaults for DropCollection { type Otel = crate::otel::Witness; } +impl OperationImpl for DropCollection { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for DropCollection { fn log_name(&self) -> &str { diff --git a/driver/src/operation/drop_database.rs b/driver/src/operation/drop_database.rs index d455a8d96..57605fde0 100644 --- a/driver/src/operation/drop_database.rs +++ b/driver/src/operation/drop_database.rs @@ -5,7 +5,13 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, db::options::DropDatabaseOptions, error::Result, - operation::{append_options_to_raw_document, OperationWithDefaults, WriteConcernOnlyBody}, + operation::{ + append_options_to_raw_document, + Base, + BaseOperation, + OperationImpl, + WriteConcernOnlyBody, + }, options::WriteConcern, }; @@ -23,7 +29,7 @@ impl DropDatabase { } } -impl OperationWithDefaults for DropDatabase { +impl BaseOperation for DropDatabase { type O = (); const NAME: &'static CStr = cstr!("dropDatabase"); @@ -62,5 +68,9 @@ impl OperationWithDefaults for DropDatabase { type Otel = crate::otel::Witness; } +impl OperationImpl for DropDatabase { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for DropDatabase {} diff --git a/driver/src/operation/drop_indexes.rs b/driver/src/operation/drop_indexes.rs index 1e7b0e0a7..96fb7ae21 100644 --- a/driver/src/operation/drop_indexes.rs +++ b/driver/src/operation/drop_indexes.rs @@ -5,7 +5,7 @@ use crate::{ bson_compat::{cstr, CStr}, cmap::{Command, RawCommandResponse, StreamDescription}, error::Result, - operation::{append_options_to_raw_document, OperationWithDefaults}, + operation::{append_options_to_raw_document, Base, BaseOperation, OperationImpl}, options::{DropIndexOptions, WriteConcern}, }; @@ -31,7 +31,7 @@ impl DropIndexes { } } -impl OperationWithDefaults for DropIndexes { +impl BaseOperation for DropIndexes { type O = (); const NAME: &'static CStr = cstr!("dropIndexes"); @@ -73,5 +73,9 @@ impl OperationWithDefaults for DropIndexes { type Otel = crate::otel::Witness; } +impl OperationImpl for DropIndexes { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for DropIndexes {} diff --git a/driver/src/operation/find.rs b/driver/src/operation/find.rs index 3d38e6216..5ab0c983f 100644 --- a/driver/src/operation/find.rs +++ b/driver/src/operation/find.rs @@ -4,7 +4,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, cursor::common::CursorSpecification, error::{Error, Result}, - operation::{OperationWithDefaults, Retryability, SERVER_4_4_0_WIRE_VERSION}, + operation::{Base, BaseOperation, OperationImpl, Retryability, SERVER_4_4_0_WIRE_VERSION}, options::{ClientOptions, CursorType, FindOptions, SelectionCriteria}, Collection, }; @@ -32,7 +32,7 @@ impl Find { } } -impl OperationWithDefaults for Find { +impl BaseOperation for Find { type O = CursorSpecification; const NAME: &'static CStr = cstr!("find"); const ZERO_COPY: bool = true; @@ -137,6 +137,10 @@ impl OperationWithDefaults for Find { type Otel = crate::otel::Witness; } +impl OperationImpl for Find { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Find { fn output_cursor_id(output: &Self::O) -> Option { diff --git a/driver/src/operation/find_and_modify.rs b/driver/src/operation/find_and_modify.rs index 93c1e5562..60a644cad 100644 --- a/driver/src/operation/find_and_modify.rs +++ b/driver/src/operation/find_and_modify.rs @@ -15,7 +15,9 @@ use crate::{ operation::{ append_options_to_raw_document, find_and_modify::options::Modification, - OperationWithDefaults, + Base, + BaseOperation, + OperationImpl, Retryability, }, options::{ClientOptions, WriteConcern}, @@ -55,7 +57,7 @@ impl FindAndModify { } } -impl OperationWithDefaults for FindAndModify { +impl BaseOperation for FindAndModify { type O = Option; const NAME: &'static CStr = cstr!("findAndModify"); @@ -131,5 +133,9 @@ impl OperationWithDefaults for FindAndModify { type Otel = crate::otel::Witness; } +impl OperationImpl for FindAndModify { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for FindAndModify {} diff --git a/driver/src/operation/get_more.rs b/driver/src/operation/get_more.rs index f06518572..448c94918 100644 --- a/driver/src/operation/get_more.rs +++ b/driver/src/operation/get_more.rs @@ -7,7 +7,7 @@ use crate::{ cmap::{conn::PinnedConnectionHandle, Command, RawCommandResponse, StreamDescription}, cursor::common::{CursorInformation, CursorReply}, error::Result, - operation::OperationWithDefaults, + operation::{Base, BaseOperation, OperationImpl}, options::SelectionCriteria, results::GetMoreResult, Namespace, @@ -43,7 +43,7 @@ impl<'conn> GetMore<'conn> { } } -impl OperationWithDefaults for GetMore<'_> { +impl BaseOperation for GetMore<'_> { type O = GetMoreResult; const NAME: &'static CStr = cstr!("getMore"); @@ -124,6 +124,10 @@ impl OperationWithDefaults for GetMore<'_> { type Otel = crate::otel::Witness; } +impl OperationImpl for GetMore<'_> { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for GetMore<'_> { #[cfg(feature = "opentelemetry")] diff --git a/driver/src/operation/insert.rs b/driver/src/operation/insert.rs index 13b639167..adc6b05a4 100644 --- a/driver/src/operation/insert.rs +++ b/driver/src/operation/insert.rs @@ -12,7 +12,7 @@ use crate::{ checked::Checked, cmap::{Command, RawCommandResponse, StreamDescription}, error::{Error, ErrorKind, InsertManyError, Result}, - operation::{OperationWithDefaults, Retryability, WriteResponseBody}, + operation::{Base, BaseOperation, OperationImpl, Retryability, WriteResponseBody}, options::{ClientOptions, InsertManyOptions, WriteConcern}, results::InsertManyResult, Collection, @@ -51,7 +51,7 @@ impl<'a> Insert<'a> { } } -impl OperationWithDefaults for Insert<'_> { +impl BaseOperation for Insert<'_> { type O = InsertManyResult; const NAME: &'static CStr = cstr!("insert"); @@ -186,5 +186,9 @@ impl OperationWithDefaults for Insert<'_> { type Otel = crate::otel::Witness; } +impl OperationImpl for Insert<'_> { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Insert<'_> {} diff --git a/driver/src/operation/list_collections.rs b/driver/src/operation/list_collections.rs index dd7651317..db384c35d 100644 --- a/driver/src/operation/list_collections.rs +++ b/driver/src/operation/list_collections.rs @@ -4,7 +4,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, cursor::common::CursorSpecification, error::Result, - operation::{OperationWithDefaults, Retryability}, + operation::{Base, BaseOperation, OperationImpl, Retryability}, options::{ClientOptions, ListCollectionsOptions, ReadPreference, SelectionCriteria}, Database, }; @@ -32,7 +32,7 @@ impl ListCollections { } } -impl OperationWithDefaults for ListCollections { +impl BaseOperation for ListCollections { type O = CursorSpecification; const NAME: &'static CStr = cstr!("listCollections"); @@ -91,6 +91,10 @@ impl OperationWithDefaults for ListCollections { type Otel = crate::otel::Witness; } +impl OperationImpl for ListCollections { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for ListCollections { fn output_cursor_id(output: &Self::O) -> Option { diff --git a/driver/src/operation/list_databases.rs b/driver/src/operation/list_databases.rs index f7271372f..bf4319d42 100644 --- a/driver/src/operation/list_databases.rs +++ b/driver/src/operation/list_databases.rs @@ -7,7 +7,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, db::options::ListDatabasesOptions, error::Result, - operation::{OperationWithDefaults, Retryability}, + operation::{Base, BaseOperation, OperationImpl, Retryability}, selection_criteria::{ReadPreference, SelectionCriteria}, }; @@ -30,7 +30,7 @@ impl ListDatabases { } } -impl OperationWithDefaults for ListDatabases { +impl BaseOperation for ListDatabases { type O = Vec; const NAME: &'static CStr = cstr!("listDatabases"); @@ -71,6 +71,10 @@ impl OperationWithDefaults for ListDatabases { type Otel = crate::otel::Witness; } +impl OperationImpl for ListDatabases { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for ListDatabases {} diff --git a/driver/src/operation/list_indexes.rs b/driver/src/operation/list_indexes.rs index e8ba28ab2..0502d7ea7 100644 --- a/driver/src/operation/list_indexes.rs +++ b/driver/src/operation/list_indexes.rs @@ -5,7 +5,7 @@ use crate::{ cmap::{Command, RawCommandResponse, StreamDescription}, cursor::common::CursorSpecification, error::Result, - operation::OperationWithDefaults, + operation::{Base, BaseOperation, OperationImpl}, options::{ClientOptions, ListIndexesOptions}, selection_criteria::{ReadPreference, SelectionCriteria}, Collection, @@ -24,7 +24,7 @@ impl ListIndexes { } } -impl OperationWithDefaults for ListIndexes { +impl BaseOperation for ListIndexes { type O = CursorSpecification; const NAME: &'static CStr = cstr!("listIndexes"); @@ -78,6 +78,10 @@ impl OperationWithDefaults for ListIndexes { type Otel = crate::otel::Witness; } +impl OperationImpl for ListIndexes { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for ListIndexes { fn output_cursor_id(output: &Self::O) -> Option { diff --git a/driver/src/operation/raw_output.rs b/driver/src/operation/raw_output.rs index 78e19c152..f3a0e1145 100644 --- a/driver/src/operation/raw_output.rs +++ b/driver/src/operation/raw_output.rs @@ -1,11 +1,9 @@ use futures_util::FutureExt; use crate::{ - bson_compat::CStr, - client::Retry, - cmap::{Command, RawCommandResponse, StreamDescription}, + cmap::RawCommandResponse, error::Result, - options::{ClientOptions, SelectionCriteria}, + operation::{OperationImpl, Wrapped, WrappedOperation}, BoxFuture, }; @@ -16,20 +14,17 @@ use super::{ExecutionContext, Operation}; #[derive(Clone)] pub(crate) struct RawOutput(pub(crate) Op); -impl Operation for RawOutput { +impl WrappedOperation for RawOutput { + type Wrapped = Op; type O = RawCommandResponse; - const NAME: &'static CStr = Op::NAME; const ZERO_COPY: bool = true; - fn build(&mut self, description: &StreamDescription) -> Result { - self.0.build(description) + fn wrapped(&self) -> &Self::Wrapped { + &self.0 } - fn extract_at_cluster_time( - &self, - response: &crate::bson::RawDocument, - ) -> Result> { - self.0.extract_at_cluster_time(response) + fn wrapped_mut(&mut self) -> &mut Self::Wrapped { + &mut self.0 } fn handle_response<'a>( @@ -40,60 +35,16 @@ impl Operation for RawOutput { async move { Ok(response.into_owned()) }.boxed() } - fn handle_error(&self, error: crate::error::Error) -> Result { - Err(error) - } - - fn selection_criteria(&self) -> super::Feature<&SelectionCriteria> { - self.0.selection_criteria() - } - - fn read_concern(&self) -> super::Feature<&crate::options::ReadConcern> { - self.0.read_concern() - } - - fn write_concern(&self) -> super::Feature<&crate::options::WriteConcern> { - self.0.write_concern() - } - - fn supports_sessions(&self) -> bool { - self.0.supports_sessions() - } - - fn retryability(&self, options: &ClientOptions) -> super::Retryability { - self.0.retryability(options) - } - - fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool { - self.0.is_backpressure_retryable(options) - } - - fn update_for_retry(&mut self, retry: Option<&Retry>) { - self.0.update_for_retry(retry) - } - - fn override_criteria(&self) -> super::OverrideCriteriaFn { - self.0.override_criteria() - } - - fn pinned_connection(&self) -> Option<&crate::cmap::conn::PinnedConnectionHandle> { - self.0.pinned_connection() - } - - fn name(&self) -> &CStr { - self.0.name() - } - - fn target(&self) -> super::OperationTarget { - self.0.target() - } - #[cfg(feature = "opentelemetry")] type Otel = crate::otel::Witness; } +impl OperationImpl for RawOutput { + type Kind = Wrapped; +} + #[cfg(feature = "opentelemetry")] -impl crate::otel::OtelInfo for RawOutput { +impl crate::otel::OtelInfo for RawOutput { fn log_name(&self) -> &str { self.0.otel().log_name() } diff --git a/driver/src/operation/run_command.rs b/driver/src/operation/run_command.rs index 956903751..3156c373a 100644 --- a/driver/src/operation/run_command.rs +++ b/driver/src/operation/run_command.rs @@ -6,12 +6,13 @@ use crate::{ client::SESSIONS_UNSUPPORTED_COMMANDS, cmap::{conn::PinnedConnectionHandle, Command, RawCommandResponse, StreamDescription}, error::{Error, Result}, + operation::{Base, OperationImpl}, options::ClientOptions, selection_criteria::SelectionCriteria, Database, }; -use super::{ExecutionContext, OperationWithDefaults}; +use super::{BaseOperation, ExecutionContext}; #[derive(Debug, Clone)] pub(crate) struct RunCommand<'conn> { @@ -45,7 +46,7 @@ impl<'conn> RunCommand<'conn> { } } -impl OperationWithDefaults for RunCommand<'_> { +impl BaseOperation for RunCommand<'_> { type O = Document; // Since we can't actually specify a string statically here, we just put a descriptive string @@ -118,5 +119,9 @@ impl OperationWithDefaults for RunCommand<'_> { type Otel = crate::otel::Witness; } +impl OperationImpl for RunCommand<'_> { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for RunCommand<'_> {} diff --git a/driver/src/operation/run_cursor_command.rs b/driver/src/operation/run_cursor_command.rs index ffa19d648..3fab09ce9 100644 --- a/driver/src/operation/run_cursor_command.rs +++ b/driver/src/operation/run_cursor_command.rs @@ -2,13 +2,18 @@ use futures_util::FutureExt; use crate::{ bson_compat::{cstr, CStr}, - client::Retry, - cmap::{conn::PinnedConnectionHandle, Command, RawCommandResponse, StreamDescription}, - concern::WriteConcern, + cmap::RawCommandResponse, cursor::common::CursorSpecification, - error::{Error, Result}, - operation::{run_command::RunCommand, Operation, SERVER_4_4_0_WIRE_VERSION}, - options::{ClientOptions, RunCursorCommandOptions, SelectionCriteria}, + error::Result, + operation::{ + run_command::RunCommand, + Operation, + OperationImpl, + Wrapped, + WrappedOperation, + SERVER_4_4_0_WIRE_VERSION, + }, + options::RunCursorCommandOptions, BoxFuture, }; @@ -32,70 +37,18 @@ impl<'conn> RunCursorCommand<'conn> { } } -impl Operation for RunCursorCommand<'_> { +impl<'conn> WrappedOperation for RunCursorCommand<'conn> { + type Wrapped = RunCommand<'conn>; type O = CursorSpecification; - const NAME: &'static CStr = cstr!("run_cursor_command"); - const ZERO_COPY: bool = true; - fn build(&mut self, description: &StreamDescription) -> Result { - self.run_command.build(description) - } - - fn extract_at_cluster_time( - &self, - response: &crate::bson::RawDocument, - ) -> Result> { - self.run_command.extract_at_cluster_time(response) - } - - fn handle_error(&self, error: Error) -> Result { - Err(error) - } - - fn selection_criteria(&self) -> super::Feature<&SelectionCriteria> { - self.run_command.selection_criteria() - } - - fn read_concern(&self) -> super::Feature<&crate::options::ReadConcern> { - self.run_command.read_concern() - } - - fn write_concern(&self) -> super::Feature<&WriteConcern> { - self.run_command.write_concern() - } - - fn supports_sessions(&self) -> bool { - self.run_command.supports_sessions() + fn wrapped(&self) -> &Self::Wrapped { + &self.run_command } - fn retryability(&self, options: &ClientOptions) -> crate::operation::Retryability { - self.run_command.retryability(options) - } - - fn is_backpressure_retryable(&self, options: &ClientOptions) -> bool { - self.run_command.is_backpressure_retryable(options) - } - - fn update_for_retry(&mut self, retry: Option<&Retry>) { - self.run_command.update_for_retry(retry) - } - - fn override_criteria(&self) -> super::OverrideCriteriaFn { - self.run_command.override_criteria() - } - - fn pinned_connection(&self) -> Option<&PinnedConnectionHandle> { - self.run_command.pinned_connection() - } - - fn name(&self) -> &CStr { - self.run_command.name() - } - - fn target(&self) -> super::OperationTarget { - self.run_command.target() + fn wrapped_mut(&mut self) -> &mut Self::Wrapped { + &mut self.run_command } fn handle_response<'a>( @@ -128,6 +81,10 @@ impl Operation for RunCursorCommand<'_> { type Otel = crate::otel::Witness; } +impl OperationImpl for RunCursorCommand<'_> { + type Kind = Wrapped; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfo for RunCursorCommand<'_> { fn log_name(&self) -> &str { diff --git a/driver/src/operation/search_index.rs b/driver/src/operation/search_index.rs index df3d73069..a02987c76 100644 --- a/driver/src/operation/search_index.rs +++ b/driver/src/operation/search_index.rs @@ -10,7 +10,7 @@ use crate::{ SearchIndexModel, }; -use super::{ExecutionContext, OperationWithDefaults}; +use super::{Base, BaseOperation, ExecutionContext, OperationImpl}; #[derive(Debug)] pub(crate) struct CreateSearchIndexes { @@ -24,7 +24,7 @@ impl CreateSearchIndexes { } } -impl OperationWithDefaults for CreateSearchIndexes { +impl BaseOperation for CreateSearchIndexes { type O = Vec; const NAME: &'static CStr = cstr!("createSearchIndexes"); @@ -76,6 +76,10 @@ impl OperationWithDefaults for CreateSearchIndexes { type Otel = crate::otel::Witness; } +impl OperationImpl for CreateSearchIndexes { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for CreateSearchIndexes {} @@ -96,7 +100,7 @@ impl UpdateSearchIndex { } } -impl OperationWithDefaults for UpdateSearchIndex { +impl BaseOperation for UpdateSearchIndex { type O = (); const NAME: &'static CStr = cstr!("updateSearchIndex"); @@ -135,6 +139,10 @@ impl OperationWithDefaults for UpdateSearchIndex { type Otel = crate::otel::Witness; } +impl OperationImpl for UpdateSearchIndex { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for UpdateSearchIndex {} @@ -150,7 +158,7 @@ impl DropSearchIndex { } } -impl OperationWithDefaults for DropSearchIndex { +impl BaseOperation for DropSearchIndex { type O = (); const NAME: &'static CStr = cstr!("dropSearchIndex"); @@ -192,5 +200,9 @@ impl OperationWithDefaults for DropSearchIndex { type Otel = crate::otel::Witness; } +impl OperationImpl for DropSearchIndex { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for DropSearchIndex {} diff --git a/driver/src/operation/update.rs b/driver/src/operation/update.rs index 97c213d84..08d21fc79 100644 --- a/driver/src/operation/update.rs +++ b/driver/src/operation/update.rs @@ -8,7 +8,7 @@ use crate::{ bson_util, cmap::{Command, RawCommandResponse, StreamDescription}, error::{convert_insert_many_error, Result}, - operation::{OperationWithDefaults, Retryability, WriteResponseBody}, + operation::{Base, BaseOperation, OperationImpl, Retryability, WriteResponseBody}, options::{ClientOptions, UpdateModifications, UpdateOptions, WriteConcern}, results::UpdateResult, Collection, @@ -94,7 +94,7 @@ impl Update { } } -impl OperationWithDefaults for Update { +impl BaseOperation for Update { type O = UpdateResult; const NAME: &'static CStr = cstr!("update"); @@ -217,6 +217,10 @@ impl OperationWithDefaults for Update { type Otel = crate::otel::Witness; } +impl OperationImpl for Update { + type Kind = Base; +} + #[cfg(feature = "opentelemetry")] impl crate::otel::OtelInfoDefaults for Update {}