spec/mongo/retryable_spec.rb in mongo-2.12.4 vs spec/mongo/retryable_spec.rb in mongo-2.13.0.beta1
- old
+ new
@@ -216,15 +216,17 @@
context 'when the retry fails once and then succeeds' do
let(:max_read_retries) { 2 }
before do
expect(retryable).to receive(:select_server).ordered
- expect(operation).to receive(:execute).and_raise(error).ordered
+ expect(operation).to receive(:execute).and_raise(error.dup).ordered
expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
expect(retryable).to receive(:select_server).ordered
- expect(operation).to receive(:execute).and_raise(error).ordered
+ # Since exception is mutated when notes are added to it,
+ # we need to ensure each attempt starts with a pristine exception.
+ expect(operation).to receive(:execute).and_raise(error.dup).ordered
expect(client).to receive(:read_retry_interval).and_return(0.1).ordered
expect(retryable).to receive(:select_server).ordered
expect(operation).to receive(:execute).and_return(true).ordered
end
@@ -348,79 +350,63 @@
it 'executes the operation twice' do
expect(retryable.write).to be true
end
end
- context 'when a not master error occurs' do
-
- before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('not master')).ordered
- expect(cluster).to receive(:scan!).and_return(true).ordered
- expect(operation).to receive(:execute).and_return(true).ordered
+ context 'when an operation failure error occurs with a RetryableWriteError label' do
+ let(:error) do
+ Mongo::Error::OperationFailure.new(nil, nil, labels: ['RetryableWriteError'])
end
- it_behaves_like 'executes the operation twice'
- end
-
- context 'when a node is recovering error occurs' do
-
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('node is recovering')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
expect(cluster).to receive(:scan!).and_return(true).ordered
expect(operation).to receive(:execute).and_return(true).ordered
end
it_behaves_like 'executes the operation twice'
end
- context 'when a retryable error occurs with a code' do
-
+ context 'when an operation failure error occurs without a RetryableWriteError label' do
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('message missing', nil,
- :code => 91, :code_name => 'ShutdownInProgress')).ordered
- expect(cluster).to receive(:scan!).and_return(true).ordered
- expect(operation).to receive(:execute).and_return(true).ordered
- end
-
- it_behaves_like 'executes the operation twice'
- end
-
- context 'when a normal operation failure occurs' do
-
- before do
expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
end
it 'raises an exception' do
expect {
retryable.write
}.to raise_error(Mongo::Error::OperationFailure)
end
end
- context 'when a socket error occurs' do
+ context 'when a socket error occurs with a RetryableWriteError label' do
+ let(:error) do
+ error = Mongo::Error::SocketError.new('socket error')
+ error.add_label('RetryableWriteError')
+ error
+ end
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::SocketError.new('socket error')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
end
it 'raises an exception' do
expect {
retryable.write
}.to raise_error(Mongo::Error::SocketError)
end
end
- context 'when a socket timeout occurs' do
+ context 'when a socket timeout error occurs with a RetryableWriteError label' do
+ let(:error) do
+ error = Mongo::Error::SocketTimeoutError.new('socket timeout error')
+ error.add_label('RetryableWriteError')
+ error
+ end
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::SocketTimeoutError.new('socket timeout')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
end
it 'raises an exception' do
expect {
retryable.write
@@ -439,11 +425,10 @@
expect {
retryable.write
}.to raise_error(Mongo::Error::UnsupportedCollation)
end
end
-
end
describe '#write_with_retry - modern' do
let(:retryable) do
@@ -473,88 +458,104 @@
it 'executes the operation twice' do
expect(retryable.write).to be true
end
end
- context 'when a not master error occurs' do
+ context 'when an operation failure error occurs with a RetryableWriteError label' do
+ let(:error) do
+ Mongo::Error::OperationFailure.new(nil, nil, labels: ['RetryableWriteError'])
+ end
before do
server = cluster.next_primary
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('not master')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
expect(operation).to receive(:execute).and_return(true).ordered
end
it_behaves_like 'executes the operation twice'
end
- context 'when a node is recovering error occurs' do
-
+ context 'when an operation failure error occurs without a RetryableWriteError label' do
before do
- server = cluster.next_primary
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('node is recovering')).ordered
- expect(operation).to receive(:execute).and_return(true).ordered
+ expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
end
- it_behaves_like 'executes the operation twice'
+ it 'raises an exception' do
+ expect {
+ retryable.write
+ }.to raise_error(Mongo::Error::OperationFailure)
+ end
end
- context 'when a retryable error occurs with a code' do
+ context 'when a socket error occurs with a RetryableWriteError label' do
+ let(:error) do
+ error = Mongo::Error::SocketError.new('socket error')
+ error.add_label('RetryableWriteError')
+ error
+ end
before do
- server = cluster.next_primary
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::OperationFailure.new('message missing', nil,
- :code => 91, :code_name => 'ShutdownInProgress')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
+ # This is where the server would be marked unknown, but since
+ # we are not tracking which server the operation was sent to,
+ # we are not able to assert this.
+ # There is no explicit cluster scan requested.
expect(operation).to receive(:execute).and_return(true).ordered
end
it_behaves_like 'executes the operation twice'
end
- context 'when a normal operation failure occurs' do
+ context 'when a socket error occurs without a RetryableWriteError label' do
+ let(:error) do
+ Mongo::Error::SocketError.new('socket error')
+ end
before do
- expect(operation).to receive(:execute).and_raise(Mongo::Error::OperationFailure).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
end
it 'raises an exception' do
expect {
retryable.write
- }.to raise_error(Mongo::Error::OperationFailure)
+ }.to raise_error(Mongo::Error::SocketError)
end
end
- context 'when a socket error occurs' do
+ context 'when a socket timeout occurs with a RetryableWriteError label' do
+ let(:error) do
+ error = Mongo::Error::SocketTimeoutError.new('socket timeout error')
+ error.add_label('RetryableWriteError')
+ error
+ end
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::SocketError.new('socket error')).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
# This is where the server would be marked unknown, but since
# we are not tracking which server the operation was sent to,
# we are not able to assert this.
- # There is no explicit cluster scan requested.
+ # There is no explicit cluster scan requested (and the operation may
+ # end up being sent to the same server it was sent to originally).
expect(operation).to receive(:execute).and_return(true).ordered
end
it_behaves_like 'executes the operation twice'
end
- context 'when a socket timeout occurs' do
+ context 'when a socket timeout occurs without a RetryableWriteError label' do
+ let(:error) do
+ Mongo::Error::SocketTimeoutError.new('socket timeout error')
+ end
before do
- expect(operation).to receive(:execute).and_raise(
- Mongo::Error::SocketTimeoutError.new('socket timeout')).ordered
- # This is where the server would be marked unknown, but since
- # we are not tracking which server the operation was sent to,
- # we are not able to assert this.
- # There is no explicit cluster scan requested (and the operation may
- # end up being sent to the same server it was sent to originally).
- expect(operation).to receive(:execute).and_return(true).ordered
+ expect(operation).to receive(:execute).and_raise(error).ordered
end
- it_behaves_like 'executes the operation twice'
+ it 'raises an exception' do
+ expect {
+ retryable.write
+ }.to raise_error(Mongo::Error::SocketTimeoutError)
+ end
end
context 'when a non-retryable exception occurs' do
before do