From 4ba8add17340eb525f3745f2b3afc0c88d8e3d25 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Fri, 22 Nov 2013 22:14:46 -0500 Subject: [PATCH] Dont re-login when using multi-session 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] --- lib/moped/cluster.rb | 41 +++++++++++++++++++++++++++++++++----- lib/moped/database.rb | 4 ++-- spec/moped/cluster_spec.rb | 29 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/lib/moped/cluster.rb b/lib/moped/cluster.rb index 0666b6d..2bb17cb 100644 --- a/lib/moped/cluster.rb +++ b/lib/moped/cluster.rb @@ -32,16 +32,32 @@ class Cluster # @return [ Array ] 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 @@ -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 @@ -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 @@ -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 diff --git a/lib/moped/database.rb b/lib/moped/database.rb index 62f5956..ade102f 100644 --- a/lib/moped/database.rb +++ b/lib/moped/database.rb @@ -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. @@ -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 diff --git a/spec/moped/cluster_spec.rb b/spec/moped/cluster_spec.rb index c67df45..ab80284 100644 --- a/spec/moped/cluster_spec.rb +++ b/spec/moped/cluster_spec.rb @@ -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