Skip to content

Instantly share code, notes, and snippets.

@benmacleod
Created October 25, 2011 15:53
Show Gist options
  • Save benmacleod/1313235 to your computer and use it in GitHub Desktop.
Save benmacleod/1313235 to your computer and use it in GitHub Desktop.
Connection code
require 'mongo/retry'
require 'mongo/retry_replica_set_connection'
if ENV['MONGOHQ_REPLICASET_URL']
# MongoMapper.config = {RAILS_ENV => {'uri' => ENV['MONGOHQ_REPLICASET_URL']}}
parser = Mongo::URIParser.new(ENV['MONGOHQ_REPLICASET_URL']) #* begin
MongoMapper.config = {
RAILS_ENV => {
'uri' => nil,
'hosts' => parser.nodes,
'database' => parser.auths[0]['db_name'],
'username' => parser.auths[0]['username'],
'password' => parser.auths[0]['password']
}
}
# parser = Mongo::URIParser.new(MongoMapper.config[RAILS_ENV]['uri']) #* begin
# mm_env = {}
# mm_env['uri'] = nil
# mm_env['hosts'] = parser.nodes
# mm_env['database'] = parser.auths[0]['db_name']
# mm_env['username'] = parser.auths[0]['username']
# mm_env['password'] = parser.auths[0]['password']
#MongoMapper.connect(mm_env, {:read => :secondary, :auto_refresh => true }) #* end
MongoMapper.connect(RAILS_ENV, {:read => :secondary, :auto_refresh => true }) # Use this instead of above lines between begin and end and also below lines if/when MongoMapper Rails 2 branch supports multiple hosts/ports separated by commas
# MongoMapper.connection = Mongo::RetryReplicaSetConnection.new(*(mm_env['hosts'] << {:read => :secondary, :auto_refresh => true }))
# MongoMapper.database = mm_env['database']
# MongoMapper.database.authenticate(mm_env['username'], mm_env['password'])
else
if ENV['MONGOHQ_URL']
MongoMapper.config = {RAILS_ENV => {'uri' => ENV['MONGOHQ_URL']}}
else
MongoMapper.config = {RAILS_ENV => {'uri' => "mongodb://localhost/torsion_#{Rails.env}"}}
end
MongoMapper.connect(RAILS_ENV, {:slave_ok => true, :logger => Rails.logger})
end
# 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, read=:primary, exhaust=false)
retry_on_connection_failure do
super(operation, message, log_message, socket, command, read, exhaust)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment