1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
# frozen_string_literal: true
# rubocop:todo all
require 'spec_helper'
describe 'Transaction pinning' do
require_mri
let(:client) { authorized_client.with(max_pool_size: 4) }
let(:collection_name) { 'tx_pinning' }
let(:collection) { client[collection_name] }
before do
authorized_client[collection_name].insert_many([{test: 1}] * 200)
end
let(:server) { client.cluster.next_primary }
clean_slate
context 'non-lb' do
require_topology :sharded
min_server_fcv '4.2'
# Start several transactions, then complete each of them.
# Force each transaction to be on its own connection.
before do
client.reconnect if client.closed?
4.times do |i|
# Collections cannot be created inside transactions.
client["tx_pin_t#{i}"].drop
client["tx_pin_t#{i}"].create
end
end
after do
if pool = server.pool_internal
pool.close
end
end
it 'works' do
sessions = []
connections = []
4.times do |i|
session = client.start_session
session.start_transaction
client["tx_pin_t#{i}"].insert_one({test: 1}, session: session)
session.pinned_server.should be_a(Mongo::Server)
sessions << session
connections << server.pool.check_out
end
server.pool.size.should == 4
connections.each do |c|
server.pool.check_in(c)
end
sessions.each_with_index do |session, i|
client["tx_pin_t#{i}"].insert_one({test: 2}, session: session)
session.commit_transaction
end
end
end
context 'lb' do
require_topology :load_balanced
min_server_fcv '4.2'
# In load-balanced topology, we cannot create new connections to a
# particular service.
context 'when no connection is available' do
require_no_linting
before do
client.reconnect if client.closed?
client["tx_pin"].drop
client["tx_pin"].create
end
it 'raises MissingConnection' do
session = client.start_session
session.start_transaction
client["tx_pin"].insert_one({test: 1}, session: session)
session.pinned_server.should be nil
session.pinned_connection_global_id.should_not be nil
server.pool.size.should == 1
service_id = server.pool.instance_variable_get(:@available_connections).first.service_id
server.pool.clear(service_id: service_id)
server.pool.size.should == 0
lambda do
client["tx_pin"].insert_one({test: 2}, session: session)
end.should raise_error(Mongo::Error::MissingConnection)
end
end
context 'when connection is available' do
before do
client.reconnect if client.closed?
end
it 'uses the available connection' do
sessions = []
connections = []
4.times do |i|
session = client.start_session
session.start_transaction
client["tx_pin_t#{i}"].insert_one({test: 1}, session: session)
session.pinned_server.should be nil
session.pinned_connection_global_id.should_not be nil
sessions << session
connections << server.pool.check_out
end
server.pool.size.should == 4
connections.each do |c|
server.pool.check_in(c)
end
sessions.each_with_index do |session, i|
client["tx_pin_t#{i}"].insert_one({test: 2}, session: session)
session.commit_transaction
end
end
end
end
end
|