Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support aborted transactions internal retry #544

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions google/cloud/spanner_dbapi/connection.py
Expand Up @@ -8,6 +8,7 @@

import warnings

from google.api_core.exceptions import Aborted
from google.api_core.gapic_v1.client_info import ClientInfo
from google.cloud import spanner_v1 as spanner

Expand Down Expand Up @@ -198,9 +199,13 @@ def commit(self):
if self._autocommit:
warnings.warn(AUTOCOMMIT_MODE_WARNING, UserWarning, stacklevel=2)
elif self._transaction:
self._transaction.commit()
self._release_session()
self._statements = []
try:
self._transaction.commit()
self._release_session()
self._statements = []
IlyaFaer marked this conversation as resolved.
Show resolved Hide resolved
except Aborted:
self.retry_transaction()
self.commit()
IlyaFaer marked this conversation as resolved.
Show resolved Hide resolved

def rollback(self):
"""Rolls back any pending transaction.
Expand Down
44 changes: 44 additions & 0 deletions tests/unit/spanner_dbapi/test_connection.py
Expand Up @@ -444,3 +444,47 @@ def test_retry_transaction_checksum_mismatch(self):
):
with self.assertRaises(Aborted):
connection.retry_transaction()

def test_commit_retry_aborted_statements(self):
"""Check that retried transaction executing the same statements."""
from google.api_core.exceptions import Aborted
from google.cloud.spanner_dbapi.checksum import ResultsChecksum
from google.cloud.spanner_dbapi.connection import connect

row = ["field1", "field2"]
with mock.patch(
"google.cloud.spanner_v1.instance.Instance.exists",
return_value=True,
):
with mock.patch(
"google.cloud.spanner_v1.database.Database.exists",
return_value=True,
):
connection = connect("test-instance", "test-database")

cursor = connection.cursor()
cursor._checksum = ResultsChecksum()
cursor._checksum.consume_result(row)

statement = {
"sql": "SELECT 1",
"params": [],
"param_types": {},
"checksum": cursor._checksum,
}
connection._statements.append(statement)
connection._transaction = mock.Mock()

with mock.patch.object(
connection._transaction,
"commit",
side_effect=(Aborted("Aborted"), None),
):
with mock.patch(
"google.cloud.spanner_dbapi.connection.Connection.run_statement",
return_value=([row], ResultsChecksum()),
) as run_mock:

connection.commit()

run_mock.assert_called_with(statement, retried=True)
2 changes: 1 addition & 1 deletion tests/unit/spanner_dbapi/test_cursor.py
Expand Up @@ -500,11 +500,11 @@ def test_fetchone_retry_aborted(self):
retry_mock.assert_called_with()

def test_fetchone_retry_aborted_statements(self):
"""Check that retried transaction executing the same statements."""
from google.api_core.exceptions import Aborted
from google.cloud.spanner_dbapi.checksum import ResultsChecksum
from google.cloud.spanner_dbapi.connection import connect

"""Check that retried transaction executing the same statements."""
row = ["field1", "field2"]
with mock.patch(
"google.cloud.spanner_v1.instance.Instance.exists",
Expand Down