%PDF- %PDF-
Direktori : /home/opti/optisoftcom-new/perl/usr/lib/perl5/MongoDB/Role/ |
Current File : /home/opti/optisoftcom-new/perl/usr/lib/perl5/MongoDB/Role/_SessionSupport.pm |
# Copyright 2018 - present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. use strict; use warnings; package MongoDB::Role::_SessionSupport; # MongoDB role to add support for sessions on Ops use version; our $VERSION = 'v2.0.2'; use Moo::Role; use MongoDB::_Types -types, 'to_IxHash'; use MongoDB::_Constants; use Safe::Isa; use boolean; use namespace::clean; requires qw/ session retryable_write /; sub _apply_session_and_cluster_time { my ( $self, $link, $query_ref ) = @_; # Assume that no session means no session support. Also means no way of # getting clusterTime. return unless defined $self->session; # Also assumption that the session was created from the current client - # not an issue in implicit sessions, but explicit sessions may have been # created by another client in the same scope. This should have been # checked further up the call chain $$query_ref = to_IxHash( $$query_ref ); ($$query_ref)->Push( 'lsid' => $self->session->session_id ); if ( $self->retryable_write || ! $self->session->_in_transaction_state( TXN_NONE ) ) { ($$query_ref)->Push( 'txnNumber' => $self->session->_server_session->transaction_id ); } if ( ! $self->session->_in_transaction_state( TXN_NONE ) ) { ($$query_ref)->Push( 'autocommit' => false ); } if ( $self->session->_in_transaction_state( TXN_STARTING ) ) { ($$query_ref)->Push( 'startTransaction' => true ); ($$query_ref)->Push( @{ $self->session->_get_transaction_read_concern->as_args( $self->session ) } ); } elsif ( ! $self->session->_in_transaction_state( TXN_NONE ) ) { # read concern only valid outside a transaction or when starting ($$query_ref)->Delete( 'readConcern' ); } # write concern not allowed in transactions except when ending. We can # safely delete it here as you can only pass writeConcern through by # arguments to client of collection. if ( $self->session->_in_transaction_state( TXN_STARTING, TXN_IN_PROGRESS ) ) { ($$query_ref)->Delete( 'writeConcern' ); } if ( $self->session->_in_transaction_state( TXN_ABORTED, TXN_COMMITTED ) && ! ($$query_ref)->EXISTS('writeConcern') ) { ($$query_ref)->Push( @{ $self->session->_get_transaction_write_concern->as_args() } ); } # MUST be the last thing to touch the transaction state before sending, # so the various starting specific query modifications can be applied # The spec states that this should happen after the command even on error, # so happening before the command is sent is still valid if ( $self->session->_in_transaction_state( TXN_STARTING ) ) { $self->session->_set__transaction_state( TXN_IN_PROGRESS ); } $self->session->_server_session->update_last_use; my $cluster_time = $self->session->get_latest_cluster_time; if ( defined $cluster_time && $link->supports_clusterTime ) { # Gossip the clusterTime ($$query_ref)->Push( '$clusterTime' => $cluster_time ); } return; } # Somethign about this makes me wonder if clustertime is not going to be set # when it should: not all requests have sessions, but any response has the # chance to have a clustertime. If we do not have a client available to put the # clustertime in, then depending on the response there may be no way to # retreive the clustertime further down the call stack. sub _update_session_and_cluster_time { my ( $self, $response ) = @_; # No point continuing as theres nothing to do even if clusterTime is returned return unless defined $self->session; my $cluster_time = $self->__extract_from( $response, '$clusterTime' ); if ( defined $cluster_time ) { $self->session->client->_update_cluster_time( $cluster_time ); $self->session->advance_cluster_time( $cluster_time ); } return; } sub _update_session_pre_assert { my ( $self, $response ) = @_; return unless defined $self->session; my $operation_time = $self->__extract_from( $response, 'operationTime' ); $self->session->advance_operation_time( $operation_time ) if defined $operation_time; return; } # Certain errors have to happen as soon as possible, such as write concern # errors in a retryable write. This has to be seperate to the other functions # due to not all result objects having the base response inside, so cannot be # used to parse operationTime or $clusterTime sub _assert_session_errors { my ( $self, $response ) = @_; if ( $self->retryable_write ) { $response->assert_no_write_concern_error; } return; } sub _update_session_connection_error { my ( $self, $err ) = @_; return unless defined $self->session; return $self->session->_maybe_apply_error_labels( $err ); } sub __extract_from { my ( $self, $response, $key ) = @_; if ( $response->$_isa( 'MongoDB::CommandResult' ) ) { return $response->output->{ $key }; } else { return $response->{ $key }; } } 1;