-
-
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 |
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 :)
This works really well! Why is this not in mongomapper?