-
-
Save bhbryant/1230938 to your computer and use it in GitHub Desktop.
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']) | |
# 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 |
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 |
bhbryant
commented
Oct 8, 2011
via email
Makes sense! I think my main point is-- this must exist somewhere in the toolchain. Currently your gist ranks really high in Google because it is the only thing that works right now :)
@bhbryant aha even I got here.
Trying to make it work with latest mongo gem, rs_list is a different format now
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 :)