Skip to content

Instantly share code, notes, and snippets.

@wojtha
Created January 16, 2018 10:25
Show Gist options
  • Save wojtha/46dea98f4ee24c2cc62afaaa7a1046cc to your computer and use it in GitHub Desktop.
Save wojtha/46dea98f4ee24c2cc62afaaa7a1046cc to your computer and use it in GitHub Desktop.
Module Mongo::Retry provides retry support on mongo connection or operation failures
# Module Mongo::Retry provides retry support on mongo connection or operation failures
#
# @note Bit enhanced replacement of Mongo::Retryable (included Mongo Ruby Driver since 2.1.0)
#
# @see https://jira.mongodb.org/browse/SERVER-14322
# @see https://gist.github.com/bhbryant/1230938
# @see https://www.compose.com/articles/your-drivers-are-not-magic-testing-your-application-for-high-availability/
# @see https://gist.github.com/reidmorrison/1498297
# @see https://github.com/reidmorrison/mongo_ha
# @see https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/retryable.rb
#
# @note Mongo::Retryable has much more robust implementation since 2.5.0
#
# @see https://jira.mongodb.org/projects/RUBY/issues/RUBY-1229
# @see https://github.com/mongodb/mongo-ruby-driver/commit/9940a93a79ba82a195c5ab8f8454d8781cd7db97#diff-6bc98b755c989c59b44ca84ce384e457
#
module Mongo::Retry
# Wrapper to rescue Mongo::ConnectionFailure exeptions which is recommended by official
# documentation when working with replica sets.
#
# @example Usage
# retry_on_connection_failure(10) do
# collection.find(id: id)
# end
#
# @param [Integer] max_retries: 60 The maximum retries of the wrapped operation
# @param [Float] wait_sec: 0.5 The waiting time in seconds before next retry
#
# @return The result of the block
#
def retry_on_connection_failure(max_retries: 40, wait_sec: 0.5)
retries = 0
begin
yield
rescue Mongo::ConnectionFailure => ex
retries += 1
raise ex if retries > max_retries
Kernel.sleep(wait_sec)
retry
end
end
# Wrapper to rescue Mongo::OperationFailure exeptions and retry the command.
#
# @example Retry find_and_modify command which often fails with Mongo::OperationFailure
# retry_on_operation_failure(max_retries: 30, wait_sec: 0.1) do
# collection.find_and_modify({
# query: { '_id' => id },
# update: { '$set' => attributes },
# })
# end
#
# @param [Integer] max_retries: 60 The maximum retries of the wrapped operation
# @param [Float] wait_sec: 0.1 The waiting time in seconds before next retry
#
# @return The result of the block
#
def retry_on_operation_failure(max_retries: 1, wait_sec: 0.0)
retries = 0
begin
yield
rescue Mongo::OperationFailure => ex
retries += 1
raise ex if retries > max_retries
Kernel.sleep(wait_sec)
retry
end
end
# Wrapper to rescue Mongo::ConnectionFailure as well as Mongo::OperationFailure exeptions and
# retry the command.
#
# @example Retry find_and_modify command which often fails with Mongo::OperationFailure
# retry_on_mongo_failure(op_retries: 2) do
# collection.find_and_modify({
# query: { '_id' => id },
# update: { '$set' => attributes },
# })
# end
#
# @param [Integer] max_retries: 60 The maximum retries of the wrapped operation
# @param [Float] wait_sec: 0.1 The waiting time in seconds before next retry
#
# @return The result of the block
#
def retry_on_mongo_failure(max_retries: 40, wait_sec: 0.5, op_retries: 5, op_wait_sec: 0.3)
retries = 0
begin
yield
rescue Mongo::OperationFailure => ex
retries += 1
raise ex if retries > op_retries
Kernel.sleep(op_wait_sec)
retry
rescue Mongo::ConnectionFailure => ex
retries += 1
raise ex if retries > max_retries
Kernel.sleep(wait_sec)
retry
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment