Skip to content

Commit 265e207

Browse files
authored
fix: add NOT_FOUND error check in __exit__ method of SessionCheckout. (#718)
* fix: Inside SnapshotCheckout __exit__ block check if NotFound exception was raised for the session and create new session if needed * test: add test for SnapshotCheckout __exit__ checks * refactor: lint fixes * test: add test case for NotFound Error in SessionCheckout context but unrelated to Sessions
1 parent 7642eba commit 265e207

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

‎google/cloud/spanner_v1/database.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,12 @@ def __enter__(self):
868868

869869
def __exit__(self, exc_type, exc_val, exc_tb):
870870
"""End ``with`` block."""
871+
if isinstance(exc_val, NotFound):
872+
# If NotFound exception occurs inside the with block
873+
# then we validate if the session still exists.
874+
if not self._session.exists():
875+
self._session = self._database._pool._new_session()
876+
self._session.create()
871877
self._database._pool.put(self._session)
872878

873879

‎tests/unit/test_database.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import mock
1919
from google.api_core import gapic_v1
20-
2120
from google.cloud.spanner_v1.param_types import INT64
2221
from google.api_core.retry import Retry
2322

@@ -1792,6 +1791,66 @@ class Testing(Exception):
17921791

17931792
self.assertIs(pool._session, session)
17941793

1794+
def test_context_mgr_session_not_found_error(self):
1795+
from google.cloud.exceptions import NotFound
1796+
1797+
database = _Database(self.DATABASE_NAME)
1798+
session = _Session(database, name="session-1")
1799+
session.exists = mock.MagicMock(return_value=False)
1800+
pool = database._pool = _Pool()
1801+
new_session = _Session(database, name="session-2")
1802+
new_session.create = mock.MagicMock(return_value=[])
1803+
pool._new_session = mock.MagicMock(return_value=new_session)
1804+
1805+
pool.put(session)
1806+
checkout = self._make_one(database)
1807+
1808+
self.assertEqual(pool._session, session)
1809+
with self.assertRaises(NotFound):
1810+
with checkout as _:
1811+
raise NotFound("Session not found")
1812+
# Assert that session-1 was removed from pool and new session was added.
1813+
self.assertEqual(pool._session, new_session)
1814+
1815+
def test_context_mgr_table_not_found_error(self):
1816+
from google.cloud.exceptions import NotFound
1817+
1818+
database = _Database(self.DATABASE_NAME)
1819+
session = _Session(database, name="session-1")
1820+
session.exists = mock.MagicMock(return_value=True)
1821+
pool = database._pool = _Pool()
1822+
pool._new_session = mock.MagicMock(return_value=[])
1823+
1824+
pool.put(session)
1825+
checkout = self._make_one(database)
1826+
1827+
self.assertEqual(pool._session, session)
1828+
with self.assertRaises(NotFound):
1829+
with checkout as _:
1830+
raise NotFound("Table not found")
1831+
# Assert that session-1 was not removed from pool.
1832+
self.assertEqual(pool._session, session)
1833+
pool._new_session.assert_not_called()
1834+
1835+
def test_context_mgr_unknown_error(self):
1836+
database = _Database(self.DATABASE_NAME)
1837+
session = _Session(database)
1838+
pool = database._pool = _Pool()
1839+
pool._new_session = mock.MagicMock(return_value=[])
1840+
pool.put(session)
1841+
checkout = self._make_one(database)
1842+
1843+
class Testing(Exception):
1844+
pass
1845+
1846+
self.assertEqual(pool._session, session)
1847+
with self.assertRaises(Testing):
1848+
with checkout as _:
1849+
raise Testing("Unknown error.")
1850+
# Assert that session-1 was not removed from pool.
1851+
self.assertEqual(pool._session, session)
1852+
pool._new_session.assert_not_called()
1853+
17951854

17961855
class TestBatchSnapshot(_BaseTest):
17971856
TABLE = "table_name"

0 commit comments

Comments
 (0)