def test_run_in_transaction_w_abort_w_retry_metadata_deadline(self): import datetime from google.gax.errors import GaxError from google.gax.grpc import exc_to_code from grpc import StatusCode from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( Transaction as TransactionPB) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.spanner.transaction import Transaction from google.cloud.spanner import session as MUT from google.cloud._testing import _Monkey TABLE_NAME = 'citizens' COLUMNS = ['email', 'first_name', 'last_name', 'age'] VALUES = [ ['*****@*****.**', 'Phred', 'Phlyntstone', 32], ['*****@*****.**', 'Bharney', 'Rhubble', 31], ] TRANSACTION_ID = b'FACEDACE' RETRY_SECONDS = 1 RETRY_NANOS = 3456 transaction_pb = TransactionPB(id=TRANSACTION_ID) now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) gax_api = _SpannerApi( _begin_transaction_response=transaction_pb, _commit_abort_count=1, _commit_abort_retry_seconds=RETRY_SECONDS, _commit_abort_retry_nanos=RETRY_NANOS, _commit_response=response, ) database = _Database(self.DATABASE_NAME) database.spanner_api = gax_api session = self._make_one(database) session._session_id = 'DEADBEEF' called_with = [] def unit_of_work(txn, *args, **kw): called_with.append((txn, args, kw)) txn.insert(TABLE_NAME, COLUMNS, VALUES) time_module = _FauxTimeModule() with _Monkey(MUT, time=time_module): with self.assertRaises(GaxError) as exc: session.run_in_transaction( unit_of_work, 'abc', some_arg='def', timeout_secs=0.01) self.assertEqual(exc_to_code(exc.exception.cause), StatusCode.ABORTED) self.assertIsNone(time_module._slept) self.assertEqual(len(called_with), 1) txn, args, kw = called_with[0] self.assertIsInstance(txn, Transaction) self.assertIsNone(txn.committed) self.assertEqual(args, ('abc',)) self.assertEqual(kw, {'some_arg': 'def'})
def test_context_mgr_success(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( TransactionOptions) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.spanner.batch import Batch now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) database = _Database(self.DATABASE_NAME) api = database.spanner_api = _FauxSpannerClient() api._commit_response = response pool = database._pool = _Pool() session = _Session(database) pool.put(session) checkout = self._make_one(database) with checkout as batch: self.assertIsNone(pool._session) self.assertIsInstance(batch, Batch) self.assertIs(batch._session, session) self.assertIs(pool._session, session) self.assertEqual(batch.committed, now) (session_name, mutations, single_use_txn, options) = api._committed self.assertIs(session_name, self.SESSION_NAME) self.assertEqual(mutations, []) self.assertIsInstance(single_use_txn, TransactionOptions) self.assertTrue(single_use_txn.HasField('read_write')) self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def test_run_in_transaction_w_abort_w_retry_metadata(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( Transaction as TransactionPB) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.spanner.transaction import Transaction from google.cloud.spanner import session as MUT from google.cloud._testing import _Monkey TABLE_NAME = 'citizens' COLUMNS = ['email', 'first_name', 'last_name', 'age'] VALUES = [ ['*****@*****.**', 'Phred', 'Phlyntstone', 32], ['*****@*****.**', 'Bharney', 'Rhubble', 31], ] TRANSACTION_ID = b'FACEDACE' RETRY_SECONDS = 12 RETRY_NANOS = 3456 transaction_pb = TransactionPB(id=TRANSACTION_ID) now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) gax_api = _SpannerApi( _begin_transaction_response=transaction_pb, _commit_abort_count=1, _commit_abort_retry_seconds=RETRY_SECONDS, _commit_abort_retry_nanos=RETRY_NANOS, _commit_response=response, ) database = _Database(self.DATABASE_NAME) database.spanner_api = gax_api session = self._make_one(database) session._session_id = 'DEADBEEF' called_with = [] def unit_of_work(txn, *args, **kw): called_with.append((txn, args, kw)) txn.insert(TABLE_NAME, COLUMNS, VALUES) time_module = _FauxTimeModule() with _Monkey(MUT, time=time_module): committed = session.run_in_transaction( unit_of_work, 'abc', some_arg='def') self.assertEqual(time_module._slept, RETRY_SECONDS + RETRY_NANOS / 1.0e9) self.assertEqual(committed, now) self.assertEqual(len(called_with), 2) for index, (txn, args, kw) in enumerate(called_with): self.assertIsInstance(txn, Transaction) if index == 1: self.assertEqual(txn.committed, committed) else: self.assertIsNone(txn.committed) self.assertEqual(args, ('abc',)) self.assertEqual(kw, {'some_arg': 'def'})
def test_context_mgr_success(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( Transaction as TransactionPB) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp transaction_pb = TransactionPB(id=self.TRANSACTION_ID) database = _Database() now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) database = _Database() api = database.spanner_api = _FauxSpannerAPI( _begin_transaction_response=transaction_pb, _commit_response=response) session = _Session(database) transaction = self._make_one(session) with transaction: transaction.insert(TABLE_NAME, COLUMNS, VALUES) self.assertEqual(transaction.committed, now) session_id, mutations, txn_id, options = api._committed self.assertEqual(session_id, self.SESSION_NAME) self.assertEqual(txn_id, self.TRANSACTION_ID) self.assertEqual(mutations, transaction._mutations) self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def test_commit_ok(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.spanner.keyset import KeySet from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) keys = [[0], [1], [2]] keyset = KeySet(keys=keys) response = CommitResponse(commit_timestamp=now_pb) database = _Database() api = database.spanner_api = _FauxSpannerAPI( _commit_response=response) session = _Session(database) transaction = self._make_one(session) transaction._transaction_id = self.TRANSACTION_ID transaction.delete(TABLE_NAME, keyset) transaction.commit() self.assertEqual(transaction.committed, now) self.assertIsNone(session._transaction) session_id, mutations, txn_id, options = api._committed self.assertEqual(session_id, session.name) self.assertEqual(txn_id, self.TRANSACTION_ID) self.assertEqual(mutations, transaction._mutations) self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def test_context_mgr_failure(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) database = _Database() api = database.spanner_api = _FauxSpannerAPI(_commit_response=response) session = _Session(database) batch = self._make_one(session) class _BailOut(Exception): pass with self.assertRaises(_BailOut): with batch: batch.insert(TABLE_NAME, COLUMNS, VALUES) raise _BailOut() self.assertEqual(batch.committed, None) self.assertEqual(api._committed, None) self.assertEqual(len(batch._mutations), 1)
def test_context_mgr_success(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( TransactionOptions) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) database = _Database() api = database.spanner_api = _FauxSpannerAPI(_commit_response=response) session = _Session(database) batch = self._make_one(session) with batch: batch.insert(TABLE_NAME, COLUMNS, VALUES) self.assertEqual(batch.committed, now) (session, mutations, single_use_txn, options) = api._committed self.assertEqual(session, self.SESSION_NAME) self.assertEqual(mutations, batch._mutations) self.assertIsInstance(single_use_txn, TransactionOptions) self.assertTrue(single_use_txn.HasField('read_write')) self.assertEqual(options.kwargs['metadata'], [('google-cloud-resource-prefix', database.name)])
def test_run_in_transaction_w_abort_no_retry_metadata(self): import datetime from google.cloud.proto.spanner.v1.spanner_pb2 import CommitResponse from google.cloud.proto.spanner.v1.transaction_pb2 import ( Transaction as TransactionPB) from google.cloud._helpers import UTC from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.spanner.transaction import Transaction TABLE_NAME = 'citizens' COLUMNS = ['email', 'first_name', 'last_name', 'age'] VALUES = [ ['*****@*****.**', 'Phred', 'Phlyntstone', 32], ['*****@*****.**', 'Bharney', 'Rhubble', 31], ] TRANSACTION_ID = b'FACEDACE' transaction_pb = TransactionPB(id=TRANSACTION_ID) now = datetime.datetime.utcnow().replace(tzinfo=UTC) now_pb = _datetime_to_pb_timestamp(now) response = CommitResponse(commit_timestamp=now_pb) gax_api = _SpannerApi( _begin_transaction_response=transaction_pb, _commit_abort_count=1, _commit_response=response, ) database = _Database(self.DATABASE_NAME) database.spanner_api = gax_api session = self._make_one(database) session._session_id = 'DEADBEEF' called_with = [] def unit_of_work(txn, *args, **kw): called_with.append((txn, args, kw)) txn.insert(TABLE_NAME, COLUMNS, VALUES) return 'answer' return_value = session.run_in_transaction(unit_of_work, 'abc', some_arg='def') self.assertEqual(len(called_with), 2) for index, (txn, args, kw) in enumerate(called_with): self.assertIsInstance(txn, Transaction) self.assertEqual(return_value, 'answer') self.assertEqual(args, ('abc', )) self.assertEqual(kw, {'some_arg': 'def'})