Skip to content

Commit 266a587

Browse files
committed
Merge branch 'master' into rubocop-enable
2 parents 451abae + 058632f commit 266a587

7 files changed

Lines changed: 267 additions & 9 deletions

File tree

.evergreen/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ buildvariants:
12731273
- matrix_name: CSOT
12741274
matrix_spec:
12751275
ruby: "ruby-4.0"
1276-
mongodb-version: "8.0"
1276+
mongodb-version: ["8.0", "rapid"]
12771277
topology: replica-set-single-node
12781278
os: ubuntu2204
12791279
display_name: "CSOT - ${mongodb-version}"
@@ -1532,7 +1532,7 @@ buildvariants:
15321532
auth-and-ssl: "noauth-and-nossl"
15331533
ruby: ["ruby-4.0", "ruby-3.4", "ruby-3.3", "ruby-3.2", "ruby-3.1"]
15341534
topology: [replica-set, sharded-cluster]
1535-
mongodb-version: [ '6.0', '7.0', '8.0' ]
1535+
mongodb-version: [ '6.0', '7.0', '8.0', 'rapid' ]
15361536
os: ubuntu2204
15371537
fle: helper
15381538
display_name: "FLE: ${mongodb-version} ${topology} ${ruby}"

.evergreen/config/standard.yml.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ buildvariants:
151151
- matrix_name: CSOT
152152
matrix_spec:
153153
ruby: <%= latest_ruby %>
154-
mongodb-version: <%= latest_stable_mdb %>
154+
mongodb-version: <%= stable_and_rapid %>
155155
topology: replica-set-single-node
156156
os: ubuntu2204
157157
display_name: "CSOT - ${mongodb-version}"
@@ -350,7 +350,7 @@ buildvariants:
350350
auth-and-ssl: "noauth-and-nossl"
351351
ruby: <%= supported_mri_rubies_3_ubuntu %>
352352
topology: [replica-set, sharded-cluster]
353-
mongodb-version: [ '6.0', '7.0', '8.0' ]
353+
mongodb-version: [ '6.0', '7.0', '8.0', 'rapid' ]
354354
os: ubuntu2204
355355
fle: helper
356356
display_name: "FLE: ${mongodb-version} ${topology} ${ruby}"

spec/integration/sdam_prose_spec.rb

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,120 @@
6060
end
6161
end
6262
end
63+
64+
describe 'Connection Pool Backpressure' do
65+
min_server_fcv '8.2'
66+
require_topology :single
67+
68+
let(:subscriber) { Mrss::EventSubscriber.new }
69+
70+
let(:client) do
71+
new_local_client(
72+
SpecConfig.instance.addresses,
73+
SpecConfig.instance.all_test_options.merge(
74+
max_connecting: 100,
75+
max_pool_size: 100,
76+
),
77+
).tap do |client|
78+
client.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)
79+
end
80+
end
81+
82+
after do
83+
sleep 1
84+
admin_db = root_authorized_client.use('admin').database
85+
86+
if defined?(@prev_ingressConnectionEstablishmentRateLimiterEnabled) &&
87+
defined?(@prev_ingressConnectionEstablishmentRatePerSec) &&
88+
defined?(@prev_ingressConnectionEstablishmentBurstCapacitySecs) &&
89+
defined?(@prev_ingressConnectionEstablishmentMaxQueueDepth)
90+
admin_db.command(
91+
setParameter: 1,
92+
ingressConnectionEstablishmentRateLimiterEnabled: @prev_ingressConnectionEstablishmentRateLimiterEnabled,
93+
)
94+
admin_db.command(
95+
setParameter: 1,
96+
ingressConnectionEstablishmentRatePerSec: @prev_ingressConnectionEstablishmentRatePerSec,
97+
)
98+
admin_db.command(
99+
setParameter: 1,
100+
ingressConnectionEstablishmentBurstCapacitySecs: @prev_ingressConnectionEstablishmentBurstCapacitySecs,
101+
)
102+
admin_db.command(
103+
setParameter: 1,
104+
ingressConnectionEstablishmentMaxQueueDepth: @prev_ingressConnectionEstablishmentMaxQueueDepth,
105+
)
106+
else
107+
# Fallback: at least disable the limiter if previous values were not captured.
108+
admin_db.command(
109+
setParameter: 1,
110+
ingressConnectionEstablishmentRateLimiterEnabled: false,
111+
)
112+
end
113+
end
114+
115+
it 'generates checkout failures when the ingress connection rate limiter is active' do
116+
admin_db = root_authorized_client.use('admin').database
117+
118+
# Capture current ingress connection establishment parameters so they can be restored.
119+
current_params = admin_db.command(
120+
getParameter: 1,
121+
ingressConnectionEstablishmentRateLimiterEnabled: 1,
122+
ingressConnectionEstablishmentRatePerSec: 1,
123+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
124+
ingressConnectionEstablishmentMaxQueueDepth: 1,
125+
).first
126+
127+
@prev_ingressConnectionEstablishmentRateLimiterEnabled =
128+
current_params['ingressConnectionEstablishmentRateLimiterEnabled']
129+
@prev_ingressConnectionEstablishmentRatePerSec =
130+
current_params['ingressConnectionEstablishmentRatePerSec']
131+
@prev_ingressConnectionEstablishmentBurstCapacitySecs =
132+
current_params['ingressConnectionEstablishmentBurstCapacitySecs']
133+
@prev_ingressConnectionEstablishmentMaxQueueDepth =
134+
current_params['ingressConnectionEstablishmentMaxQueueDepth']
135+
136+
# Enable the ingress rate limiter with test-specific values.
137+
admin_db.command(
138+
setParameter: 1,
139+
ingressConnectionEstablishmentRateLimiterEnabled: true,
140+
)
141+
admin_db.command(
142+
setParameter: 1,
143+
ingressConnectionEstablishmentRatePerSec: 20,
144+
)
145+
admin_db.command(
146+
setParameter: 1,
147+
ingressConnectionEstablishmentBurstCapacitySecs: 1,
148+
)
149+
admin_db.command(
150+
setParameter: 1,
151+
ingressConnectionEstablishmentMaxQueueDepth: 1,
152+
)
153+
154+
# Add a document so $where has something to process.
155+
client.use('test')['test'].delete_many
156+
client.use('test')['test'].insert_one({})
157+
158+
# Run 100 parallel find_one operations that contend for connections.
159+
threads = 100.times.map do
160+
Thread.new do
161+
begin
162+
client.use('test')['test'].find(
163+
'$where' => 'function() { sleep(2000); return true; }'
164+
).first
165+
rescue StandardError
166+
# Ignore connection errors (including checkout timeouts).
167+
end
168+
end
169+
end
170+
threads.each(&:join)
171+
172+
checkout_failed = subscriber.select_published_events(
173+
Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed
174+
)
175+
176+
expect(checkout_failed.length).to be >= 10
177+
end
178+
end
63179
end

spec/integration/secondary_reads_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
end_stats = get_read_counters
2626

27-
end_stats[:secondary].should be_within(10).of(start_stats[:secondary])
27+
end_stats[:secondary].should be_within(50).of(start_stats[:secondary])
2828
end_stats[:primary].should >= start_stats[:primary] + 30
2929
end
3030
end
@@ -45,7 +45,7 @@
4545

4646
end_stats = get_read_counters
4747

48-
end_stats[:primary].should be_within(10).of(start_stats[:primary])
48+
end_stats[:primary].should be_within(50).of(start_stats[:primary])
4949
end_stats[:secondary].should >= start_stats[:secondary] + 30
5050
end
5151
end

spec/mongo/retryable/token_bucket_spec.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,16 @@
6767
end
6868

6969
describe 'thread safety' do
70-
let(:bucket) { described_class.new(capacity: 1000) }
70+
# Use capacity 2000, start at 1000 tokens.
71+
# With 500 consumes and 500 deposits, floor/ceiling cannot be hit:
72+
# min possible = 1000 - 500 = 500 > 0 (all consumes succeed)
73+
# max possible = 1000 + 500 = 1500 < 2000 (all deposits effective)
74+
# So the net change is guaranteed to be 0, making the assertion reliable.
75+
let(:bucket) do
76+
b = described_class.new(capacity: 2000)
77+
b.consume(1000)
78+
b
79+
end
7180

7281
def run_concurrent_operations(bucket)
7382
threads = []

spec/spec_tests/data/sdam_unified/minPoolSize-error.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ initialData: &initialData
2121
documents: []
2222

2323
tests:
24-
- description: Network error on minPoolSize background creation
24+
- description: Server error on minPoolSize background creation
2525
operations:
2626
# Configure the initial monitor handshake to succeed but the
2727
# first or second background minPoolSize establishments to fail.
@@ -38,7 +38,7 @@ tests:
3838
- hello
3939
- isMaster
4040
appName: SDAMminPoolSizeError
41-
closeConnection: true
41+
errorCode: 91
4242
- name: createEntities
4343
object: testRunner
4444
arguments:
@@ -54,6 +54,7 @@ tests:
5454
heartbeatFrequencyMS: 10000
5555
appname: SDAMminPoolSizeError
5656
minPoolSize: 10
57+
serverMonitoringMode: poll
5758
serverSelectionTimeoutMS: 1000
5859
- database:
5960
id: &database database
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
description: pool-cleared-on-min-pool-size-population-error
3+
4+
schemaVersion: "1.4"
5+
6+
runOnRequirements:
7+
# failCommand appName requirements
8+
- minServerVersion: "4.4"
9+
serverless: forbid
10+
topologies: [ single ]
11+
12+
createEntities:
13+
- client:
14+
id: &setupClient setupClient
15+
useMultipleMongoses: false
16+
17+
tests:
18+
- description: Pool is cleared on authentication error during minPoolSize population
19+
runOnRequirements:
20+
# failCommand appName requirements
21+
- auth: true
22+
operations:
23+
- name: failPoint
24+
object: testRunner
25+
arguments:
26+
client: *setupClient
27+
failPoint:
28+
configureFailPoint: failCommand
29+
mode:
30+
times: 1
31+
data:
32+
failCommands:
33+
- saslContinue
34+
appName: authErrorTest
35+
errorCode: 18
36+
- name: createEntities
37+
object: testRunner
38+
arguments:
39+
entities:
40+
- client:
41+
id: &client client
42+
observeEvents:
43+
- poolReadyEvent
44+
- poolClearedEvent
45+
- connectionClosedEvent
46+
uriOptions:
47+
appname: authErrorTest
48+
minPoolSize: 1
49+
50+
- name: waitForEvent
51+
object: testRunner
52+
arguments:
53+
client: *client
54+
event:
55+
poolReadyEvent: {}
56+
count: 1
57+
58+
- name: waitForEvent
59+
object: testRunner
60+
arguments:
61+
client: *client
62+
event:
63+
poolClearedEvent: {}
64+
count: 1
65+
66+
- name: waitForEvent
67+
object: testRunner
68+
arguments:
69+
client: *client
70+
event:
71+
connectionClosedEvent: {}
72+
count: 1
73+
74+
- description: Pool is not cleared on handshake error during minPoolSize population
75+
operations:
76+
- name: failPoint
77+
object: testRunner
78+
arguments:
79+
client: *setupClient
80+
failPoint:
81+
configureFailPoint: failCommand
82+
mode:
83+
skip: 1 # skip one to let monitoring thread to move pool to ready state
84+
data:
85+
failCommands:
86+
- hello
87+
- isMaster
88+
appName: authErrorTest
89+
closeConnection: true
90+
91+
- name: createEntities
92+
object: testRunner
93+
arguments:
94+
entities:
95+
- client:
96+
id: &client client
97+
observeEvents:
98+
- poolReadyEvent
99+
- poolClearedEvent
100+
- connectionClosedEvent
101+
uriOptions:
102+
appname: authErrorTest
103+
minPoolSize: 5
104+
maxConnecting: 1
105+
# ensure that once we've connected to the server, the failCommand won't
106+
# be triggered by monitors and will only be triggered by handshakes
107+
serverMonitoringMode: poll
108+
heartbeatFrequencyMS: 1000000
109+
110+
- name: waitForEvent
111+
object: testRunner
112+
arguments:
113+
client: *client
114+
event:
115+
poolReadyEvent: {}
116+
count: 1
117+
118+
- name: waitForEvent
119+
object: testRunner
120+
arguments:
121+
client: *client
122+
event:
123+
connectionClosedEvent: {}
124+
count: 1
125+
126+
- name: assertEventCount
127+
object: testRunner
128+
arguments:
129+
client: *client
130+
event:
131+
poolClearedEvent: {}
132+
count: 0

0 commit comments

Comments
 (0)