Skip to main content

mongodb/operation/
commit_transaction.rs

1use std::time::Duration;
2
3use crate::bson::rawdoc;
4
5use crate::{
6    bson_compat::{cstr, CStr},
7    cmap::{Command, RawCommandResponse, StreamDescription},
8    error::Result,
9    operation::{append_options_to_raw_document, OperationWithDefaults, Retryability},
10    options::{Acknowledgment, TransactionOptions, WriteConcern},
11};
12
13use super::{ExecutionContext, WriteConcernOnlyBody};
14
15pub(crate) struct CommitTransaction {
16    options: Option<TransactionOptions>,
17}
18
19impl CommitTransaction {
20    pub(crate) fn new(options: Option<TransactionOptions>) -> Self {
21        Self { options }
22    }
23}
24
25impl OperationWithDefaults for CommitTransaction {
26    type O = ();
27
28    const NAME: &'static CStr = cstr!("commitTransaction");
29
30    fn build(&mut self, _description: &StreamDescription) -> Result<Command> {
31        let mut body = rawdoc! {
32            Self::NAME: 1,
33        };
34
35        append_options_to_raw_document(&mut body, self.options.as_ref())?;
36
37        Ok(Command::new(Self::NAME, "admin", body))
38    }
39
40    fn handle_response<'a>(
41        &'a self,
42        response: &RawCommandResponse,
43        _context: ExecutionContext<'a>,
44    ) -> Result<Self::O> {
45        let response: WriteConcernOnlyBody = response.body()?;
46        response.validate()
47    }
48
49    fn write_concern(&self) -> Option<&WriteConcern> {
50        self.options
51            .as_ref()
52            .and_then(|opts| opts.write_concern.as_ref())
53    }
54
55    fn retryability(&self) -> Retryability {
56        Retryability::Write
57    }
58
59    // Updates the write concern to use w: majority and a w_timeout of 10000 if w_timeout is not
60    // already set. The write concern on a commitTransaction command should be updated if a
61    // commit is being retried internally or by the user.
62    fn update_for_retry(&mut self) {
63        let options = self
64            .options
65            .get_or_insert_with(|| TransactionOptions::builder().build());
66        match &mut options.write_concern {
67            Some(write_concern) => {
68                write_concern.w = Some(Acknowledgment::Majority);
69                if write_concern.w_timeout.is_none() {
70                    write_concern.w_timeout = Some(Duration::from_millis(10000));
71                }
72            }
73            None => {
74                options.write_concern = Some(
75                    WriteConcern::builder()
76                        .w(Acknowledgment::Majority)
77                        .w_timeout(Duration::from_millis(10000))
78                        .build(),
79                );
80            }
81        }
82    }
83
84    #[cfg(feature = "opentelemetry")]
85    type Otel = crate::otel::Witness<Self>;
86}
87
88#[cfg(feature = "opentelemetry")]
89impl crate::otel::OtelInfoDefaults for CommitTransaction {
90    fn target(&self) -> crate::otel::OperationTarget<'_> {
91        crate::otel::OperationTarget::ADMIN
92    }
93}