You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by di...@apache.org on 2022/06/30 20:07:34 UTC

[allura] 01/01: [#8422] greedily prefetch thread artifact refs and attachments in batches

This is an automated email from the ASF dual-hosted git repository.

dill0wn pushed a commit to branch dw/8422
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 87aa6e03ed48b3333ebdd39e940772ca5feafd5b
Author: Dillon Walls <di...@slashdotmedia.com>
AuthorDate: Thu Jun 30 20:07:16 2022 +0000

    [#8422] greedily prefetch thread artifact refs and attachments in batches
---
 Allura/allura/lib/widgets/discuss.py | 25 +++++++++++++++++++++----
 Allura/allura/model/artifact.py      | 10 ++++++++--
 Allura/allura/model/discuss.py       |  6 ------
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index 60e1222a4..35328780f 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -351,10 +351,27 @@ class Thread(HierWidget):
         # bulk fetch backrefs to save on many queries within EW
         thread: M.Thread = context['value']
         posts = thread.posts
-        index_ids = [a.index_id() for a in posts]
-        q = M.ArtifactReference.query.find(dict(references={'$in': index_ids})).all()
-        for a in posts:
-            a._backrefs = [aref._id for aref in q if a.index_id() in (aref.references or [])]
+        post_ids = [post._id for post in posts]
+        post_index_ids = [post.index_id() for post in posts]
+
+        # prefill refs
+        refs = M.ArtifactReference.query.find(dict(_id={'$in': post_index_ids})).all()
+        for post in posts:
+            for ref in refs:
+                if post.index_id() == ref._id:
+                    post._ref = ref
+                    break
+
+        # prefill backrefs
+        refs = M.ArtifactReference.query.find(dict(references={'$in': post_index_ids})).all()
+        for post in posts:
+            post._backrefs = [ref._id for ref in refs if post.index_id() in (ref.references or [])]
+
+        # prefill attachments
+        refs = thread.attachment_class().query.find(
+            dict(app_config_id=thread.app_config_id, artifact_id={'$in': post_ids}, type='attachment')).all()
+        for post in posts:
+            post._attachments = [ref for ref in refs if post._id == ref.post_id]
         return context
 
     def resources(self):
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index fe9beb8c6..6ff629e68 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -145,6 +145,9 @@ class Artifact(MappedClass, SearchIndexable):
         Artifact.
 
         """
+        if hasattr(self, '_ref'):
+            return self._ref
+
         return ArtifactReference.from_artifact(self)
 
     @LazyProperty
@@ -452,8 +455,11 @@ class Artifact(MappedClass, SearchIndexable):
 
     @LazyProperty
     def attachments(self):
-        atts = self.attachment_class().query.find(dict(
-            app_config_id=self.app_config_id, artifact_id=self._id, type='attachment')).all()
+        if hasattr(self, '_attachments'):
+            atts = self._attachments
+        else:
+            atts = self.attachment_class().query.find(dict(
+                app_config_id=self.app_config_id, artifact_id=self._id, type='attachment')).all()
         return utils.unique_attachments(atts)
 
     def delete(self):
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 6709f6e52..a91ea93d7 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -635,12 +635,6 @@ class Post(Message, VersionedArtifact, ActivityObject, ReactableArtifact):
                     subject = getattr(artifact, 'email_subject', '')
         return subject or '(no subject)'
 
-    @LazyProperty
-    def attachments(self):
-        atts = self.attachment_class().query.find(dict(
-            post_id=self._id, type='attachment')).all()
-        return utils.unique_attachments(atts)
-
     def add_multiple_attachments(self, file_info):
         if isinstance(file_info, list):
             for fi in file_info: