Resolve LDDA <-> Library Dataset circular dependency

This eliminates a lot of excessive flushes that were needed to persist
new `LibraryDatasetDatasetAssociation` (LDDA) and `LibraryDataset` (LD) objects.  These
intermittent flushes would make LD objects visible before
they are associated with a LDDA, causing the
Exception in
https://github.com/galaxyproject/galaxy/pull/10556#issuecomment-717175641

```
galaxy.web.framework.decorators ERROR 2020-10-27 17:26:25,817 Uncaught exception in exposed API method:
Traceback (most recent call last):
  File "/Users/mvandenb/src/galaxy/lib/galaxy/web/framework/decorators.py", line 294, in decorator
    rval = func(self, trans, *args, **kwargs)
  File "/Users/mvandenb/src/galaxy/lib/galaxy/webapps/galaxy/api/folder_contents.py", line 111, in index
    dataset = content_item.library_dataset_dataset_association.dataset
AttributeError: 'NoneType' object has no attribute 'dataset'
```

The trick here is to use `post_update=True`, so that ldda and ld rows
are INSERTED, followed by an UPDATE to create the link.
This is explained at
https://docs.sqlalchemy.org/en/13/orm/relationship_persistence.html.

This is also the groundwork for speeding up library additions by
batching flushes.
This commit is contained in:
mvdbeek
2020-10-29 11:21:53 +01:00
parent 4ed40df8ce
commit 6e2aad1416
3 changed files with 44 additions and 21 deletions
+31
View File
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import collections
import unittest
import uuid
@@ -154,6 +155,36 @@ class MappingTests(unittest.TestCase):
assert isinstance(history.get_display_name(), text_type)
assert history.get_display_name() == u'Hello₩◎ґʟⅾ'
def test_hda_to_library_dataset_dataset_association(self):
u = self.model.User(email="mary@example.com", password="password")
hda = self.model.HistoryDatasetAssociation(name='hda_name')
self.persist(hda)
trans = collections.namedtuple('trans', 'user')
target_folder = self.model.LibraryFolder(name='library_folder')
ldda = hda.to_library_dataset_dataset_association(
trans=trans(user=u),
target_folder=target_folder,
)
assert target_folder.item_count == 1
assert ldda.id
assert ldda.library_dataset.id
assert ldda.library_dataset_id
assert ldda.library_dataset.library_dataset_dataset_association
assert ldda.library_dataset.library_dataset_dataset_association_id
library_dataset_id = ldda.library_dataset_id
replace_dataset = ldda.library_dataset
new_ldda = hda.to_library_dataset_dataset_association(
trans=trans(user=u),
target_folder=target_folder,
replace_dataset=replace_dataset
)
assert new_ldda.id != ldda.id
assert new_ldda.library_dataset_id == library_dataset_id
assert new_ldda.library_dataset.library_dataset_dataset_association_id == new_ldda.id
assert len(new_ldda.library_dataset.expired_datasets) == 1
assert new_ldda.library_dataset.expired_datasets[0] == ldda
assert target_folder.item_count == 1
def test_tags(self):
model = self.model