Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
Start flushing out clean failover strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
durran committed Mar 4, 2013
1 parent 741a0e5 commit 87c5c7f
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 8 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ tmp/
.replica
mongo.key
TODO
.DS_Store
32 changes: 32 additions & 0 deletions lib/moped/failover.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# encoding: utf-8
require "moped/failover/ignore"

module Moped

# Provides behaviour around failover scenarios for different types of
# exceptions that get raised on connection and execution of operations.
#
# @since 2.0.0
module Failover
extend self

# Hash lookup for the failover classes based off the exception type.
#
# @since 2.0.0
STRATEGIES = {}.freeze

# Get the appropriate failover handler given the provided exception.
#
# @example Get the failover handler for an IOError.
# Moped::Failover.get(IOError)
#
# @param [ Exception ] exception The raised exception.
#
# @return [ Object ] The failover handler.
#
# @since 2.0.0
def get(exception)
STRATEGIES.fetch(exception, Ignore).new(exception)
end
end
end
44 changes: 44 additions & 0 deletions lib/moped/failover/ignore.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# encoding: utf-8
module Moped
module Failover

# Ignore is for the case when we get exceptions we do not know about, or
# exceptions we deem are proper user errors and should be re-raised.
#
# @since 2.0.0
class Ignore

# @!attribute exception
# @return [ Exception ] The raised exception.
attr_reader :exception

# Instantiate the new Ignore handler.
#
# @example Instantiate the new ignore handler.
# Moped::Failover::Ignore.new(exception)
#
# @param [ Exception ] exception The raised exception.
#
# @since 2.0.0
def initialize(exception)
@exception = exception
end

# Executes the failover strategy. In the case of ignore, we just re-raise
# the exception that was thrown previously.
#
# @example Execute the ignore strategy.
# ignore.execute(node)
#
# @param [ Node ] node The node the exception got raised on.
# @param [ Proc ] block The optional block.
#
# @raise [ Exception ] The exception that was previously thrown.
#
# @since 2.0.0
def execute(node, &block)
raise(exception)
end
end
end
end
15 changes: 14 additions & 1 deletion lib/moped/node.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# encoding: utf-8
require "moped/failover"
require "moped/read"

module Moped

# Represents a client to a node in a server cluster.
Expand Down Expand Up @@ -132,13 +136,22 @@ def down?
# @return [ nil ] nil.
#
# @since 1.0.0
def ensure_connected
def ensure_connected(&block)
# Don't run the reconnection login if we're already inside an
# +ensure_connected+ block.
return yield if Threaded.executing?(:connection)
Threaded.begin(:connection)
retry_on_failure = true

# @todo: Durran: Let's get failover scenarios to look like this:
#
# begin
# connect unless connected?
# yield
# rescue Exception => e
# Failover.get(e).execute(self, &block)
# end

begin
connect unless connected?
yield
Expand Down
2 changes: 1 addition & 1 deletion lib/moped/read_preference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module ReadPreference
primary_preferred: PrimaryPreferred,
secondary: Secondary,
secondary_preferred: SecondaryPreferred
}
}.freeze

# Get a read preference for the provided name. Valid names are:
# - :nearest
Expand Down
1 change: 0 additions & 1 deletion lib/moped/session.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# encoding: utf-8
require "moped/read"
require "moped/read_preference"

module Moped
Expand Down
8 changes: 3 additions & 5 deletions lib/moped/write.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ module Moped
class Write

# The operation can be a Protocol::Insert, Protocol::Update,
# Protocol::Delete, Protocol::Command.
# Protocol::Delete
def initialize(operation)
@operation = operation
end

def execute(node)
reply = node.process(operation)
# @todo: Durran check the reply for failover situations and handle them
# here.
reply
node.process(operation)
# Check our write concern and then do the right thing.
end
end
end
40 changes: 40 additions & 0 deletions spec/moped/failover/ignore_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require "spec_helper"

describe Moped::Failover::Ignore do

describe "#initialize" do

let(:exception) do
RuntimeError.new
end

let(:ignore) do
described_class.new(exception)
end

it "sets the exception" do
expect(ignore.exception).to eq(exception)
end
end

describe "#execute" do

let(:exception) do
RuntimeError.new
end

let(:node) do
Moped::Node.new("127.0.0.1:27017")
end

let(:ignore) do
described_class.new(exception)
end

it "raises the exception" do
expect {
ignore.execute(node)
}.to raise_error(exception)
end
end
end
18 changes: 18 additions & 0 deletions spec/moped/failover_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require "spec_helper"

describe Moped::Failover do

describe ".get" do

context "when providing an unregistered exception" do

let(:failover) do
described_class.get(RuntimeError)
end

it "returns ignore" do
expect(failover).to be_a(Moped::Failover::Ignore)
end
end
end
end

0 comments on commit 87c5c7f

Please sign in to comment.