Created
September 21, 2011 01:19
-
-
Save bhbryant/1230938 to your computer and use it in GitHub Desktop.
auto-failover ReplicaSet config for MongoMapper, by way of ruby driver
This file contains 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 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 | |
end | |
end | |
private | |
def log_retry(retry_number) | |
puts "A Mongo::ConnectionFailure was raised. Retry attempt ##{retry_number}." | |
end | |
end |
This file contains 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 |
If you could give me a hand modifying it to work that would be fantastic.
Getting a too many arguments error on the initialize
Thank you for this brilliant gist !
@thomasdavis, you should take a look at my fork I had to make.
Basically, it does not require you to change your connection adapter/class and fix the too many arguments error.
Good morning guys, I saw this and seems to work really well.
So my question is... is this gist already implemented into a gem or something like that?
If not, I'll apply as is here :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@bhbryant aha even I got here.
Trying to make it work with latest mongo gem, rs_list is a different format now