@@ -14,6 +14,14 @@ def initialize(operation, cluster)
1414 @cluster = cluster
1515 end
1616
17+ def max_read_retries
18+ cluster . max_read_retries
19+ end
20+
21+ def read_retry_interval
22+ cluster . read_retry_interval
23+ end
24+
1725 def read
1826 read_with_retry do
1927 operation . execute
@@ -81,14 +89,80 @@ def write
8189
8290 context 'when an operation failure occurs' do
8391
84- before do
85- expect ( operation ) . to receive ( :execute ) . and_raise ( Mongo ::Error ::OperationFailure ) . ordered
92+ context 'when the cluster is not a mongos' do
93+
94+ before do
95+ expect ( operation ) . to receive ( :execute ) . and_raise ( Mongo ::Error ::OperationFailure ) . ordered
96+ expect ( cluster ) . to receive ( :sharded? ) . and_return ( false )
97+ end
98+
99+ it 'raises an exception' do
100+ expect {
101+ retryable . read
102+ } . to raise_error ( Mongo ::Error ::OperationFailure )
103+ end
86104 end
87105
88- it 'raises an exception' do
89- expect {
90- retryable . read
91- } . to raise_error ( Mongo ::Error ::OperationFailure )
106+ context 'when the cluster is a mongos' do
107+
108+ context 'when the operation failure is not retryable' do
109+
110+ let ( :error ) do
111+ Mongo ::Error ::OperationFailure . new ( 'not authorized' )
112+ end
113+
114+ before do
115+ expect ( operation ) . to receive ( :execute ) . and_raise ( error ) . ordered
116+ expect ( cluster ) . to receive ( :sharded? ) . and_return ( true )
117+ end
118+
119+ it 'raises the exception' do
120+ expect {
121+ retryable . read
122+ } . to raise_error ( Mongo ::Error ::OperationFailure )
123+ end
124+ end
125+
126+ context 'when the operation failure is retryable' do
127+
128+ let ( :error ) do
129+ Mongo ::Error ::OperationFailure . new ( 'no master' )
130+ end
131+
132+ context 'when the retry succeeds' do
133+
134+ before do
135+ expect ( operation ) . to receive ( :execute ) . and_raise ( error ) . ordered
136+ expect ( cluster ) . to receive ( :sharded? ) . and_return ( true )
137+ expect ( cluster ) . to receive ( :max_read_retries ) . and_return ( 1 ) . ordered
138+ expect ( cluster ) . to receive ( :read_retry_interval ) . and_return ( 0.1 ) . ordered
139+ expect ( operation ) . to receive ( :execute ) . and_return ( true ) . ordered
140+ end
141+
142+ it 'returns the result' do
143+ expect ( retryable . read ) . to be true
144+ end
145+ end
146+
147+ context 'when the retry fails once and then succeeds' do
148+
149+ before do
150+ expect ( operation ) . to receive ( :execute ) . and_raise ( error ) . ordered
151+ expect ( cluster ) . to receive ( :sharded? ) . and_return ( true )
152+ expect ( cluster ) . to receive ( :max_read_retries ) . and_return ( 1 ) . ordered
153+ expect ( cluster ) . to receive ( :read_retry_interval ) . and_return ( 0.1 ) . ordered
154+ expect ( operation ) . to receive ( :execute ) . and_raise ( error ) . ordered
155+ expect ( cluster ) . to receive ( :sharded? ) . and_return ( true )
156+ expect ( cluster ) . to receive ( :max_read_retries ) . and_return ( 1 ) . ordered
157+ expect ( cluster ) . to receive ( :read_retry_interval ) . and_return ( 0.1 ) . ordered
158+ expect ( operation ) . to receive ( :execute ) . and_return ( true ) . ordered
159+ end
160+
161+ it 'returns the result' do
162+ expect ( retryable . read ) . to be true
163+ end
164+ end
165+ end
92166 end
93167 end
94168 end
0 commit comments