@@ -906,6 +906,193 @@ def test_spans_get_and_leave_empty_pool(self):
906
906
self .assertSpanEvents ("pool.Get" , wantEventNames )
907
907
908
908
909
+ class TestTransactionPingingPool (unittest .TestCase ):
910
+ def _getTargetClass (self ):
911
+ from google .cloud .spanner_v1 .pool import TransactionPingingPool
912
+
913
+ return TransactionPingingPool
914
+
915
+ def _make_one (self , * args , ** kwargs ):
916
+ return self ._getTargetClass ()(* args , ** kwargs )
917
+
918
+ def test_ctor_defaults (self ):
919
+ pool = self ._make_one ()
920
+ self .assertIsNone (pool ._database )
921
+ self .assertEqual (pool .size , 10 )
922
+ self .assertEqual (pool .default_timeout , 10 )
923
+ self .assertEqual (pool ._delta .seconds , 3000 )
924
+ self .assertTrue (pool ._sessions .empty ())
925
+ self .assertTrue (pool ._pending_sessions .empty ())
926
+ self .assertEqual (pool .labels , {})
927
+ self .assertIsNone (pool .database_role )
928
+
929
+ def test_ctor_explicit (self ):
930
+ labels = {"foo" : "bar" }
931
+ database_role = "dummy-role"
932
+ pool = self ._make_one (
933
+ size = 4 ,
934
+ default_timeout = 30 ,
935
+ ping_interval = 1800 ,
936
+ labels = labels ,
937
+ database_role = database_role ,
938
+ )
939
+ self .assertIsNone (pool ._database )
940
+ self .assertEqual (pool .size , 4 )
941
+ self .assertEqual (pool .default_timeout , 30 )
942
+ self .assertEqual (pool ._delta .seconds , 1800 )
943
+ self .assertTrue (pool ._sessions .empty ())
944
+ self .assertTrue (pool ._pending_sessions .empty ())
945
+ self .assertEqual (pool .labels , labels )
946
+ self .assertEqual (pool .database_role , database_role )
947
+
948
+ def test_ctor_explicit_w_database_role_in_db (self ):
949
+ database_role = "dummy-role"
950
+ pool = self ._make_one ()
951
+ database = pool ._database = _Database ("name" )
952
+ SESSIONS = [_Session (database )] * 10
953
+ database ._sessions .extend (SESSIONS )
954
+ database ._database_role = database_role
955
+ pool .bind (database )
956
+ self .assertEqual (pool .database_role , database_role )
957
+
958
+ def test_bind (self ):
959
+ pool = self ._make_one ()
960
+ database = _Database ("name" )
961
+ SESSIONS = [_Session (database ) for _ in range (10 )]
962
+ database ._sessions .extend (SESSIONS )
963
+ pool .bind (database )
964
+
965
+ self .assertIs (pool ._database , database )
966
+ self .assertEqual (pool .size , 10 )
967
+ self .assertEqual (pool .default_timeout , 10 )
968
+ self .assertEqual (pool ._delta .seconds , 3000 )
969
+ self .assertTrue (pool ._sessions .full ())
970
+
971
+ api = database .spanner_api
972
+ self .assertEqual (api .batch_create_sessions .call_count , 5 )
973
+ for session in SESSIONS :
974
+ session .create .assert_not_called ()
975
+ txn = session ._transaction
976
+ txn .begin .assert_not_called ()
977
+
978
+ self .assertTrue (pool ._pending_sessions .empty ())
979
+
980
+ def test_bind_w_timestamp_race (self ):
981
+ import datetime
982
+ from google .cloud ._testing import _Monkey
983
+ from google .cloud .spanner_v1 import pool as MUT
984
+
985
+ NOW = datetime .datetime .utcnow ()
986
+ pool = self ._make_one ()
987
+ database = _Database ("name" )
988
+ SESSIONS = [_Session (database ) for _ in range (10 )]
989
+ database ._sessions .extend (SESSIONS )
990
+
991
+ with _Monkey (MUT , _NOW = lambda : NOW ):
992
+ pool .bind (database )
993
+
994
+ self .assertIs (pool ._database , database )
995
+ self .assertEqual (pool .size , 10 )
996
+ self .assertEqual (pool .default_timeout , 10 )
997
+ self .assertEqual (pool ._delta .seconds , 3000 )
998
+ self .assertTrue (pool ._sessions .full ())
999
+
1000
+ api = database .spanner_api
1001
+ self .assertEqual (api .batch_create_sessions .call_count , 5 )
1002
+ for session in SESSIONS :
1003
+ session .create .assert_not_called ()
1004
+ txn = session ._transaction
1005
+ txn .begin .assert_not_called ()
1006
+
1007
+ self .assertTrue (pool ._pending_sessions .empty ())
1008
+
1009
+ def test_put_full (self ):
1010
+ import queue
1011
+
1012
+ pool = self ._make_one (size = 4 )
1013
+ database = _Database ("name" )
1014
+ SESSIONS = [_Session (database ) for _ in range (4 )]
1015
+ database ._sessions .extend (SESSIONS )
1016
+ pool .bind (database )
1017
+
1018
+ with self .assertRaises (queue .Full ):
1019
+ pool .put (_Session (database ))
1020
+
1021
+ self .assertTrue (pool ._sessions .full ())
1022
+
1023
+ def test_put_non_full_w_active_txn (self ):
1024
+ pool = self ._make_one (size = 1 )
1025
+ session_queue = pool ._sessions = _Queue ()
1026
+ pending = pool ._pending_sessions = _Queue ()
1027
+ database = _Database ("name" )
1028
+ session = _Session (database )
1029
+ txn = session .transaction ()
1030
+
1031
+ pool .put (session )
1032
+
1033
+ self .assertEqual (len (session_queue ._items ), 1 )
1034
+ _ , queued = session_queue ._items [0 ]
1035
+ self .assertIs (queued , session )
1036
+
1037
+ self .assertEqual (len (pending ._items ), 0 )
1038
+ txn .begin .assert_not_called ()
1039
+
1040
+ def test_put_non_full_w_committed_txn (self ):
1041
+ pool = self ._make_one (size = 1 )
1042
+ session_queue = pool ._sessions = _Queue ()
1043
+ pending = pool ._pending_sessions = _Queue ()
1044
+ database = _Database ("name" )
1045
+ session = _Session (database )
1046
+ committed = session .transaction ()
1047
+ committed .committed = True
1048
+
1049
+ pool .put (session )
1050
+
1051
+ self .assertEqual (len (session_queue ._items ), 0 )
1052
+
1053
+ self .assertEqual (len (pending ._items ), 1 )
1054
+ self .assertIs (pending ._items [0 ], session )
1055
+ self .assertIsNot (session ._transaction , committed )
1056
+ session ._transaction .begin .assert_not_called ()
1057
+
1058
+ def test_put_non_full (self ):
1059
+ pool = self ._make_one (size = 1 )
1060
+ session_queue = pool ._sessions = _Queue ()
1061
+ pending = pool ._pending_sessions = _Queue ()
1062
+ database = _Database ("name" )
1063
+ session = _Session (database )
1064
+
1065
+ pool .put (session )
1066
+
1067
+ self .assertEqual (len (session_queue ._items ), 0 )
1068
+ self .assertEqual (len (pending ._items ), 1 )
1069
+ self .assertIs (pending ._items [0 ], session )
1070
+
1071
+ self .assertFalse (pending .empty ())
1072
+
1073
+ def test_begin_pending_transactions_empty (self ):
1074
+ pool = self ._make_one (size = 1 )
1075
+ pool .begin_pending_transactions () # no raise
1076
+
1077
+ def test_begin_pending_transactions_non_empty (self ):
1078
+ pool = self ._make_one (size = 1 )
1079
+ pool ._sessions = _Queue ()
1080
+
1081
+ database = _Database ("name" )
1082
+ TRANSACTIONS = [_make_transaction (object ())]
1083
+ PENDING_SESSIONS = [_Session (database , transaction = txn ) for txn in TRANSACTIONS ]
1084
+
1085
+ pending = pool ._pending_sessions = _Queue (* PENDING_SESSIONS )
1086
+ self .assertFalse (pending .empty ())
1087
+
1088
+ pool .begin_pending_transactions () # no raise
1089
+
1090
+ for txn in TRANSACTIONS :
1091
+ txn .begin .assert_not_called ()
1092
+
1093
+ self .assertTrue (pending .empty ())
1094
+
1095
+
909
1096
class TestSessionCheckout (unittest .TestCase ):
910
1097
def _getTargetClass (self ):
911
1098
from google .cloud .spanner_v1 .pool import SessionCheckout
0 commit comments