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

Commit

Permalink
Dont re-login when using multi-session
Browse files Browse the repository at this point in the history
When creating multiple sessions, they should share the same pool, with
the same connections. Node.refresh commands need to have the credentials
before running, otherwise we will reconnect(logout/login) into the
server.

[fixes #237]
  • Loading branch information
arthurnn committed Nov 23, 2013
1 parent da92f1b commit 4ba8add
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
41 changes: 36 additions & 5 deletions lib/moped/cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,32 @@ class Cluster
# @return [ Array<Node> ] The seed nodes.
attr_reader :options, :peers, :seeds

# Get the credentials for the cluster.
# Add a credential to the cluster
#
# @example Get the applied credentials.
# node.credentials
#
# @return [ Hash ] The credentials.
# @return [ Boolean ] true
#
# @since 2.0.0
def credentials
def add_credential(db, username, password)
@credentials ||= {}
@credentials[db] = [ username, password ]
apply_credentials
end

# Remove a credential from the cluster
#
# @example Get the applied credentials.
# node.delete_credential(database_name)
#
# @return [ Boolean ] true
#
# @since 2.0.0
def delete_credential(db)
return true unless @credentials
@credentials.delete(db)
apply_credentials
end

# Disconnects all nodes in the cluster. This should only be used in cases
Expand Down Expand Up @@ -224,7 +240,6 @@ def with_primary(&block)
if node = nodes.find(&:primary?)
begin
node.ensure_primary do
node.credentials = credentials
return yield(node)
end
rescue Errors::ConnectionFailure, Errors::ReplicaSetReconfigured
Expand Down Expand Up @@ -252,7 +267,6 @@ def with_secondary(&block)
available_nodes = nodes.select(&:secondary?).shuffle!
while node = available_nodes.shift
begin
node.credentials = credentials
return yield(node)
rescue Errors::ConnectionFailure => e
next
Expand All @@ -263,6 +277,23 @@ def with_secondary(&block)

private

# Apply the credentials on all nodes
#
# @api private
#
# @example Apply the credentials.
# cluster.apply_credentials
#
# @return [ Boolean ] True
#
# @since 2.0.0
def apply_credentials
seeds.each do |node|
node.credentials = @credentials || {}
end
true
end

# Get the boundary where a node that is down would need to be refreshed.
#
# @api private
Expand Down
4 changes: 2 additions & 2 deletions lib/moped/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def initialize(session, name)
#
# @since 1.0.0
def login(username, password)
cluster.credentials[name] = [ username, password ]
cluster.add_credential(name, username, password)
end

# Log out from the current database.
Expand All @@ -122,7 +122,7 @@ def login(username, password)
#
# @since 1.0.0
def logout
cluster.credentials.delete(name)
cluster.delete_credential(name)
end
end
end
29 changes: 29 additions & 0 deletions spec/moped/cluster_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -477,5 +477,34 @@
end

it_behaves_like "authenticable session"

context "when creating multiple sessions" do

before do
session.login(*Support::MongoHQ.auth_credentials)
end

let(:session_two) do
Support::MongoHQ.auth_session(true, pool_size: 1)
end

let(:connection) do
conn = nil
session.cluster.seeds.first.connection { |c| conn = c }
conn
end

it "logs in only once" do
expect(connection).to receive(:login).once.and_call_original
session.command(ping: 1).should eq("ok" => 1)
session_two.command(ping: 1).should eq("ok" => 1)
end

it "does not logout" do
expect(connection).to receive(:logout).never
session.command(ping: 1).should eq("ok" => 1)
session_two.command(ping: 1).should eq("ok" => 1)
end
end
end
end

3 comments on commit 4ba8add

@brndnblck
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@arthurnn
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix was quite simple, but it took me a few hours of debugging =). Also find some weird dead-locks when N+1 Sessions are created on threads at the same time, and N being the number of connections on the pool. Will see what I can do about that one too.

@brndnblck
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been there :-) The joys of debugging a connection pool! Glad you were able to get to the bottom of it.

Please sign in to comment.