-
-
Save mrkurt/2254747 to your computer and use it in GitHub Desktop.
auto-failover ReplicaSet config for MongoMapper, by way of ruby driver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
replica_sets = mm_env['replica_sets'] # node1:port&node2:port | |
rs_list = replica_sets.split("&").map {|rs| host,port = rs.split(":"); [host,port.to_i] } | |
MongoMapper.connection = Mongo::RetryReplicaSetConnection.new(*(rs_list << {:read_secondary => true, :auto_refresh => true })) | |
MongoMapper.database = mm_env['database'] | |
MongoMapper.database.authenticate(mm_env['username'], mm_env['password']) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
## pulled from mongoid | |
# Provides behaviour for retrying commands on connection failure. | |
module Mongo::Retry | |
# Retries command on connection failures. | |
# | |
# This is useful when using replica sets. When a primary server wents | |
# down and a command is issued, the driver will raise a | |
# Mongo::ConnectionFailure. We wait a little bit, because nodes are | |
# electing themselves, and then retry the given command. | |
# | |
# By setting Mongoid.max_retries_on_connection_failure to a value of 0, | |
# no attempt will be made, immediately raising connection failure. | |
# Otherwise it will attempt to make the specified number of retries | |
# and then raising the exception to clients. | |
# | |
# @example Retry the command. | |
# retry_on_connection_failure do | |
# collection.send(name, *args) | |
# end | |
# | |
# @since 2.0.0 | |
def retry_on_connection_failure | |
retries = 0 | |
begin | |
yield | |
rescue Mongo::ConnectionFailure => ex | |
retries += 1 | |
raise ex if retries > 30 # Config.max_retries_on_connection_failure | |
Kernel.sleep(0.5) ## Todo.. modify for event machine | |
log_retry retries | |
retry | |
rescue Mongo::OperationFailure => ex | |
if ex.message =~ /not master/ | |
retries += 1 | |
raise ex if retries > 30 | |
Kernel.sleep(0.5) | |
log_retry retries | |
retry | |
else | |
raise ex | |
end | |
end | |
end | |
private | |
def log_retry(retry_number) | |
puts "A Mongo::ConnectionFailure was raised. Retry attempt ##{retry_number}." | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Mongo::RetryReplicaSetConnection < Mongo::ReplSetConnection | |
## wraps basic send message calls in catch blocks to auto retry connection | |
## per: http://permalink.gmane.org/gmane.comp.db.mongodb.user/25261 | |
# After looking at the Ruby MongoDB driver code it appears that we could | |
# handle this transparently in the following methods: | |
# Connection::send_message | |
# Connection::send_message_with_safe_check | |
# Connection::receive_message | |
# I put together a new Connection class that is derived from | |
# ReplSetConnection to implement this behavior. | |
## This is ripped from Mongoid block | |
include Mongo::Retry | |
def send_message(operation, message, opts={}) | |
retry_on_connection_failure do | |
super(operation, message, opts) | |
end | |
end | |
def send_message_with_safe_check(operation, message, db_name, log_message=nil, last_error_params=false) | |
retry_on_connection_failure do | |
super(operation, message, db_name, log_message, last_error_params) | |
end | |
end | |
def receive_message(operation, message, log_message=nil, socket=nil, command=false) | |
retry_on_connection_failure do | |
super(operation, message, log_message, socket, command) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment