|
64 | 64 | configureFailPoint: 'failCommand', mode: 'off') |
65 | 65 | end |
66 | 66 | end |
| 67 | + |
| 68 | + describe 'Connection Pool Backpressure' do |
| 69 | + min_server_fcv '8.2' |
| 70 | + require_topology :single |
| 71 | + |
| 72 | + let(:subscriber) { Mrss::EventSubscriber.new } |
| 73 | + |
| 74 | + let(:client) do |
| 75 | + new_local_client( |
| 76 | + SpecConfig.instance.addresses, |
| 77 | + SpecConfig.instance.all_test_options.merge( |
| 78 | + max_connecting: 100, |
| 79 | + max_pool_size: 100, |
| 80 | + ), |
| 81 | + ).tap do |client| |
| 82 | + client.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber) |
| 83 | + end |
| 84 | + end |
| 85 | + |
| 86 | + after do |
| 87 | + sleep 1 |
| 88 | + root_authorized_client.use('admin').database.command( |
| 89 | + setParameter: 1, |
| 90 | + ingressConnectionEstablishmentRateLimiterEnabled: false, |
| 91 | + ) |
| 92 | + end |
| 93 | + |
| 94 | + it 'generates checkout failures when the ingress connection rate limiter is active' do |
| 95 | + # Enable the ingress rate limiter. |
| 96 | + root_authorized_client.use('admin').database.command( |
| 97 | + setParameter: 1, |
| 98 | + ingressConnectionEstablishmentRateLimiterEnabled: true, |
| 99 | + ) |
| 100 | + root_authorized_client.use('admin').database.command( |
| 101 | + setParameter: 1, |
| 102 | + ingressConnectionEstablishmentRatePerSec: 20, |
| 103 | + ) |
| 104 | + root_authorized_client.use('admin').database.command( |
| 105 | + setParameter: 1, |
| 106 | + ingressConnectionEstablishmentBurstCapacitySecs: 1, |
| 107 | + ) |
| 108 | + root_authorized_client.use('admin').database.command( |
| 109 | + setParameter: 1, |
| 110 | + ingressConnectionEstablishmentMaxQueueDepth: 1, |
| 111 | + ) |
| 112 | + |
| 113 | + # Add a document so $where has something to process. |
| 114 | + client.use('test')['test'].delete_many |
| 115 | + client.use('test')['test'].insert_one({}) |
| 116 | + |
| 117 | + # Run 100 parallel find_one operations that contend for connections. |
| 118 | + threads = 100.times.map do |
| 119 | + Thread.new do |
| 120 | + begin |
| 121 | + client.use('test')['test'].find( |
| 122 | + '$where' => 'function() { sleep(2000); return true; }' |
| 123 | + ).first |
| 124 | + rescue StandardError |
| 125 | + # Ignore connection errors (including checkout timeouts). |
| 126 | + end |
| 127 | + end |
| 128 | + end |
| 129 | + threads.each(&:join) |
| 130 | + |
| 131 | + checkout_failed = subscriber.select_published_events( |
| 132 | + Mongo::Monitoring::Event::Cmap::ConnectionCheckOutFailed |
| 133 | + ) |
| 134 | + |
| 135 | + expect(checkout_failed.length).to be >= 10 |
| 136 | + end |
| 137 | + end |
67 | 138 | end |
0 commit comments