File Coverage

blib/lib/MongoDB/Role/_ReadPrefModifier.pm
Criterion Covered Total %
statement 24 64 37.5
branch 0 28 0.0
condition 0 19 0.0
subroutine 8 11 72.7
pod n/a
total 32 122 26.2


line stmt bran cond sub pod time code
1             # Copyright 2014 - present MongoDB, Inc.
2             #
3             # Licensed under the Apache License, Version 2.0 (the "License");
4             # you may not use this file except in compliance with the License.
5             # You may obtain a copy of the License at
6             #
7             # http://www.apache.org/licenses/LICENSE-2.0
8             #
9             # Unless required by applicable law or agreed to in writing, software
10             # distributed under the License is distributed on an "AS IS" BASIS,
11             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12             # See the License for the specific language governing permissions and
13             # limitations under the License.
14              
15 59     59   84555 use strict;
  59         157  
  59         1920  
16 59     59   333 use warnings;
  59         128  
  59         2138  
17              
18             package MongoDB::Role::_ReadPrefModifier;
19              
20             # MongoDB role to modify OP_QUERY query document or flags to account
21             # for topology-specific treatment of a read-preference (if any)
22              
23 59     59   328 use version;
  59         116  
  59         351  
24             our $VERSION = 'v2.2.0';
25              
26 59     59   4484 use Moo::Role;
  59         196  
  59         384  
27              
28 59     59   20659 use MongoDB::Error;
  59         133  
  59         7303  
29 59     59   784 use MongoDB::ReadPreference;
  59         140  
  59         2031  
30 59     59   431 use MongoDB::_Types -types, 'to_IxHash';
  59         147  
  59         482  
31              
32 59     59   354095 use namespace::clean;
  59         156  
  59         441  
33              
34             requires qw/read_preference/;
35              
36             my $PRIMARY = MongoDB::ReadPreference->new()->_as_hashref;
37             my $PRIMARYPREFERRED =
38             MongoDB::ReadPreference->new( mode => 'primaryPreferred' )->_as_hashref;
39              
40             sub _apply_op_msg_read_prefs {
41 0     0     my ( $self, $link, $topology_type, $query_flags, $query_ref ) = @_;
42              
43 0   0       $topology_type ||= "";
44 0           my $read_pref = $self->read_preference;
45 0 0         my $read_pref_doc = $read_pref ? $read_pref->_as_hashref : $PRIMARY;
46              
47 0 0 0       if ( $topology_type eq 'Single' && ! ($link->server && $link->server->type eq 'Mongos') ) {
      0        
48             # For direct connection to a non-mongos single server, allow any server
49             # type, overriding the provided read preference
50 0           $read_pref_doc = $PRIMARYPREFERRED;
51             }
52              
53 0           $$query_ref = to_IxHash($$query_ref);
54 0           ($$query_ref)->Push( '$readPreference' => $read_pref_doc );
55              
56 0           return;
57             }
58              
59             sub _apply_op_query_read_prefs {
60 0     0     my ( $self, $link, $topology_type, $query_flags, $query_ref ) = @_;
61              
62 0   0       $topology_type ||= "";
63 0           my $read_pref = $self->read_preference;
64              
65 0 0         if ( $topology_type eq 'Single' ) {
    0          
    0          
66 0 0 0       if ( $link->server && $link->server->type eq 'Mongos' ) {
67 0           $self->_apply_mongos_read_prefs( $read_pref, $query_flags, $query_ref );
68             }
69             else {
70 0           $query_flags->{slave_ok} = 1;
71             }
72             }
73 0           elsif ( grep { $topology_type eq $_ } qw/ReplicaSetNoPrimary ReplicaSetWithPrimary/ )
74             {
75 0 0 0       if ( !$read_pref || $read_pref->mode eq 'primary' ) {
76 0           $query_flags->{slave_ok} = 0;
77             }
78             else {
79 0           $query_flags->{slave_ok} = 1;
80             }
81             }
82             elsif ( $topology_type eq 'Sharded' ) {
83 0           $self->_apply_mongos_read_prefs( $read_pref, $query_flags, $query_ref );
84             }
85             else {
86 0           MongoDB::InternalError->throw("can't query topology type '$topology_type'");
87             }
88              
89 0           return;
90             }
91              
92             sub _apply_mongos_read_prefs {
93 0     0     my ( $self, $read_pref, $query_flags, $query_ref ) = @_;
94 0 0         my $mode = $read_pref ? $read_pref->mode : 'primary';
95 0           my $need_read_pref;
96              
97 0 0         if ( $mode eq 'primary' ) {
    0          
    0          
98 0           $query_flags->{slave_ok} = 0;
99             }
100 0           elsif ( grep { $mode eq $_ } qw/secondary primaryPreferred nearest/ ) {
101 0           $query_flags->{slave_ok} = 1;
102 0           $need_read_pref = 1;
103             }
104             elsif ( $mode eq 'secondaryPreferred' ) {
105 0           $query_flags->{slave_ok} = 1;
106 0 0 0       $need_read_pref = 1
107             unless $read_pref->has_empty_tag_sets && $read_pref->max_staleness_seconds == -1;
108             }
109             else {
110 0           MongoDB::InternalError->throw("invalid read preference mode '$mode'");
111             }
112              
113 0 0         if ($need_read_pref) {
114 0           $$query_ref = to_IxHash($$query_ref);
115 0 0         if ( !($$query_ref)->FETCH('$query') ) {
116 0           $$query_ref = Tie::IxHash->new( '$query' => $$query_ref );
117             }
118 0           ($$query_ref)->Push( '$readPreference' => $read_pref->_as_hashref );
119             }
120              
121 0           return;
122             }
123              
124             1;