@@ -834,6 +834,134 @@ func TestConnection(t *testing.T) {
834834 t .Errorf ("LocalAddresses do not match. got %v; want %v" , got , want )
835835 }
836836 })
837+
838+ t .Run ("pinning" , func (t * testing.T ) {
839+ makeMultipleConnections := func (t * testing.T , numConns int ) (* pool , []* Connection ) {
840+ t .Helper ()
841+
842+ addr := address .Address ("" )
843+ pool , err := newPool (poolConfig {Address : addr })
844+ assert .Nil (t , err , "newPool error: %v" , err )
845+
846+ err = pool .sem .Acquire (context .Background (), int64 (numConns ))
847+ assert .Nil (t , err , "error acquiring semaphore: %v" , err )
848+
849+ conns := make ([]* Connection , 0 , numConns )
850+ for i := 0 ; i < numConns ; i ++ {
851+ conn , err := newConnection (addr )
852+ assert .Nil (t , err , "newConnection error: %v" , err )
853+ conn .pool = pool
854+ conns = append (conns , & Connection {connection : conn })
855+ }
856+ return pool , conns
857+ }
858+ makeOneConnection := func (t * testing.T ) (* pool , * Connection ) {
859+ t .Helper ()
860+
861+ pool , conns := makeMultipleConnections (t , 1 )
862+ return pool , conns [0 ]
863+ }
864+
865+ assertPoolPinnedStats := func (t * testing.T , p * pool , cursorConns , txnConns uint64 ) {
866+ t .Helper ()
867+
868+ assert .Equal (t , cursorConns , p .pinnedCursorConnections , "expected %d connections to be pinned to cursors, got %d" ,
869+ cursorConns , p .pinnedCursorConnections )
870+ assert .Equal (t , txnConns , p .pinnedTransactionConnections , "expected %d connections to be pinned to transactions, got %d" ,
871+ txnConns , p .pinnedTransactionConnections )
872+ }
873+
874+ t .Run ("cursors" , func (t * testing.T ) {
875+ pool , conn := makeOneConnection (t )
876+ err := conn .PinToCursor ()
877+ assert .Nil (t , err , "PinToCursor error: %v" , err )
878+ assertPoolPinnedStats (t , pool , 1 , 0 )
879+
880+ err = conn .UnpinFromCursor ()
881+ assert .Nil (t , err , "UnpinFromCursor error: %v" , err )
882+
883+ err = conn .Close ()
884+ assert .Nil (t , err , "Close error: %v" , err )
885+ assertPoolPinnedStats (t , pool , 0 , 0 )
886+ })
887+ t .Run ("transactions" , func (t * testing.T ) {
888+ pool , conn := makeOneConnection (t )
889+ err := conn .PinToTransaction ()
890+ assert .Nil (t , err , "PinToTransaction error: %v" , err )
891+ assertPoolPinnedStats (t , pool , 0 , 1 )
892+
893+ err = conn .UnpinFromTransaction ()
894+ assert .Nil (t , err , "UnpinFromTransaction error: %v" , err )
895+
896+ err = conn .Close ()
897+ assert .Nil (t , err , "Close error: %v" , err )
898+ assertPoolPinnedStats (t , pool , 0 , 0 )
899+ })
900+ t .Run ("pool is only updated for first reference" , func (t * testing.T ) {
901+ pool , conn := makeOneConnection (t )
902+ err := conn .PinToTransaction ()
903+ assert .Nil (t , err , "PinToTransaction error: %v" , err )
904+ assertPoolPinnedStats (t , pool , 0 , 1 )
905+
906+ err = conn .PinToCursor ()
907+ assert .Nil (t , err , "PinToCursor error: %v" , err )
908+ assertPoolPinnedStats (t , pool , 0 , 1 )
909+
910+ err = conn .UnpinFromCursor ()
911+ assert .Nil (t , err , "UnpinFromCursor error: %v" , err )
912+ assertPoolPinnedStats (t , pool , 0 , 1 )
913+
914+ err = conn .UnpinFromTransaction ()
915+ assert .Nil (t , err , "UnpinFromTransaction error: %v" , err )
916+ assertPoolPinnedStats (t , pool , 0 , 1 )
917+
918+ err = conn .Close ()
919+ assert .Nil (t , err , "Close error: %v" , err )
920+ assertPoolPinnedStats (t , pool , 0 , 0 )
921+ })
922+ t .Run ("multiple connections from a pool" , func (t * testing.T ) {
923+ pool , conns := makeMultipleConnections (t , 2 )
924+ first , second := conns [0 ], conns [1 ]
925+
926+ err := first .PinToTransaction ()
927+ assert .Nil (t , err , "PinToTransaction error: %v" , err )
928+ err = second .PinToCursor ()
929+ assert .Nil (t , err , "PinToCursor error: %v" , err )
930+ assertPoolPinnedStats (t , pool , 1 , 1 )
931+
932+ err = first .UnpinFromTransaction ()
933+ assert .Nil (t , err , "UnpinFromTransaction error: %v" , err )
934+ err = first .Close ()
935+ assert .Nil (t , err , "Close error: %v" , err )
936+ assertPoolPinnedStats (t , pool , 1 , 0 )
937+
938+ err = second .UnpinFromCursor ()
939+ assert .Nil (t , err , "UnpinFromCursor error: %v" , err )
940+ err = second .Close ()
941+ assert .Nil (t , err , "Close error: %v" , err )
942+ assertPoolPinnedStats (t , pool , 0 , 0 )
943+ })
944+ t .Run ("close is ignored if connection is pinned" , func (t * testing.T ) {
945+ pool , conn := makeOneConnection (t )
946+ err := conn .PinToCursor ()
947+ assert .Nil (t , err , "PinToCursor error: %v" , err )
948+
949+ err = conn .Close ()
950+ assert .Nil (t , err , "Close error" )
951+ assert .NotNil (t , conn .connection , "expected connection to be pinned but it was released to the pool" )
952+ assertPoolPinnedStats (t , pool , 1 , 0 )
953+ })
954+ t .Run ("expire forcefully returns connection to pool" , func (t * testing.T ) {
955+ pool , conn := makeOneConnection (t )
956+ err := conn .PinToCursor ()
957+ assert .Nil (t , err , "PinToCursor error: %v" , err )
958+
959+ err = conn .Expire ()
960+ assert .Nil (t , err , "Expire error" )
961+ assert .Nil (t , conn .connection , "expected connection to be released to the pool but was not" )
962+ assertPoolPinnedStats (t , pool , 0 , 0 )
963+ })
964+ })
837965 })
838966}
839967
0 commit comments