diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a67dfe959..fc3c4a4bd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,15 @@ snovault Change Log ---------- +7.1.2 +===== + +* In ``RDBStorage.update``: + * Use session.begin_nested for better stack hygiene. + * Better error message on integrity error to acknowledge possibility + of both UUID conflit *and* undefined UUID. + + 7.1.1 ===== diff --git a/pyproject.toml b/pyproject.toml index 643558b2e..e78ded493 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "dcicsnovault" -version = "7.1.1" +version = "7.1.1.1b0" # to become "7.1.2" description = "Storage support for 4DN Data Portals." authors = ["4DN-DCIC Team "] license = "MIT" diff --git a/snovault/storage.py b/snovault/storage.py index 0893519b2..b2cfb4649 100644 --- a/snovault/storage.py +++ b/snovault/storage.py @@ -475,19 +475,18 @@ def create(self, item_type, rid): def update(self, model, properties=None, sheets=None, unique_keys=None, links=None): session = self.DBSession() - sp = session.begin_nested() - try: - session.add(model) - self._update_properties(model, properties, sheets) - if links is not None: - self._update_rels(model, links) - if unique_keys is not None: - keys_add, keys_remove = self._update_keys(model, unique_keys) - sp.commit() - except (IntegrityError, FlushError): - sp.rollback() - else: - return + with session.begin_nested() as sp: + try: + session.add(model) + self._update_properties(model, properties, sheets) + if links is not None: + self._update_rels(model, links) + if unique_keys is not None: + keys_add, keys_remove = self._update_keys(model, unique_keys) + sp.commit() + return + except (IntegrityError, FlushError): + sp.rollback() # Try again more carefully try: @@ -497,7 +496,7 @@ def update(self, model, properties=None, sheets=None, unique_keys=None, links=No self._update_rels(model, links) session.flush() except (IntegrityError, FlushError): - msg = 'UUID conflict' + msg = 'Cannot update because of one or more conflicting (or undefined) UUIDs' raise HTTPConflict(msg) assert unique_keys is not None conflicts = [pk for pk in keys_add if session.query(Key).get(pk) is not None] diff --git a/snovault/tests/conftest.py b/snovault/tests/conftest.py index 970f40389..c1e95c840 100644 --- a/snovault/tests/conftest.py +++ b/snovault/tests/conftest.py @@ -1,9 +1,9 @@ -import os -import time -import tempfile +# import os +# import time +# import tempfile import pytest import logging -import subprocess +# import subprocess from ..elasticsearch.indexer_queue import QueueManager diff --git a/snovault/tests/test_embedding.py b/snovault/tests/test_embedding.py index 480365be1..3c1a5a0cc 100644 --- a/snovault/tests/test_embedding.py +++ b/snovault/tests/test_embedding.py @@ -1,5 +1,5 @@ import pytest -import time +# import time from dcicutils.misc_utils import ignored from dcicutils.qa_utils import notice_pytest_fixtures, Retry, Eventually @@ -112,9 +112,11 @@ def test_linked_uuids_object(content, dummy_request, threadlocals): # needed to track _linked_uuids dummy_request._indexing_view = True dummy_request.embed('/testing-link-sources-sno/', sources[0]['uuid'], '@@object') + def my_assertions(): assert dummy_request._linked_uuids == {('16157204-8c8f-4672-a1a4-14f4b8021fcd', 'TestingLinkSourceSno')} assert dummy_request._rev_linked_uuids_by_item == {} + Eventually.call_assertion(my_assertions) diff --git a/snovault/tests/test_storage.py b/snovault/tests/test_storage.py index a78eca505..290381af1 100644 --- a/snovault/tests/test_storage.py +++ b/snovault/tests/test_storage.py @@ -1,7 +1,7 @@ from unittest import mock import pytest import re -import transaction as transaction_management +# import transaction as transaction_management import uuid import boto3