Skip to content

Commit 16a2cf4

Browse files
MONGOID-5255 Do not allow reuse of a closed client (#5207)
1 parent b181741 commit 16a2cf4

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

lib/mongoid/persistence_context.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ def ==(other)
122122
options == other.options
123123
end
124124

125+
# Whether the client of the context can be reused later, and therefore should
126+
# not be closed.
127+
#
128+
# If the persistence context is requested with :client option only, it means
129+
# that the context should use a client configured in mongoid.yml.
130+
# Such clients should not be closed when the context is cleared since they
131+
# will be reused later.
132+
#
133+
# @return [ true | false ] True if client can be reused, otherwise false.
134+
#
135+
# @api private
136+
def reusable_client?
137+
@options.keys == [:client]
138+
end
139+
125140
private
126141

127142
def set_options!(opts)
@@ -210,7 +225,7 @@ def get(object)
210225
def clear(object, cluster = nil, original_context = nil)
211226
if context = get(object)
212227
unless cluster.nil? || context.cluster.equal?(cluster)
213-
context.client.close
228+
context.client.close unless context.reusable_client?
214229
end
215230
end
216231
ensure

spec/mongoid/clients_spec.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,36 @@
10121012
end
10131013
end
10141014
end
1015+
1016+
context 'when requesting named client' do
1017+
let(:secondary_client) do
1018+
double(Mongo::Client).tap do |client|
1019+
allow(client).to receive(:cluster).and_return(double("cluster"))
1020+
end
1021+
end
1022+
1023+
before do
1024+
expect(Mongoid::Clients::Factory).to receive(:create)
1025+
.with(:secondary)
1026+
.and_return(secondary_client)
1027+
end
1028+
1029+
after do
1030+
Mongoid::Clients.clients.delete(:secondary)
1031+
end
1032+
1033+
it 'does not close the client' do
1034+
expect(secondary_client).not_to receive(:close)
1035+
1036+
Band.with(client: :default) do |klass|
1037+
klass.mongo_client
1038+
end
1039+
1040+
Band.with(client: :secondary) do |klass|
1041+
klass.mongo_client
1042+
end
1043+
end
1044+
end
10151045
end
10161046

10171047
context "when overriding the default database" do

spec/mongoid/persistence_context_spec.rb

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
end
4040
end
4141

42-
4342
describe '.get' do
4443

4544
let(:options) do
@@ -134,6 +133,32 @@
134133
end
135134
end
136135
end
136+
137+
context 'with reusable client' do
138+
let(:options) do
139+
{client: :some_client}
140+
end
141+
142+
let(:cluster) do
143+
double(Mongo::Cluster)
144+
end
145+
146+
let(:client) do
147+
double(Mongo::Client).tap do |client|
148+
allow(client).to receive(:cluster).and_return(cluster)
149+
end
150+
end
151+
152+
before do
153+
expect(Mongoid::Clients).to receive(:with_name).with(:some_client).and_return(client)
154+
expect(client).not_to receive(:close)
155+
end
156+
157+
it 'does not close the client' do
158+
described_class.set(object, options)
159+
described_class.clear(object, cluster.dup)
160+
end
161+
end
137162
end
138163

139164
describe '#initialize' do

0 commit comments

Comments
 (0)