Repository: allura
Updated Branches:
  refs/heads/master 40ee1b5c9 -> 612eccae9


[#8194] store merge requests' new commits


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/612eccae
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/612eccae
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/612eccae

Branch: refs/heads/master
Commit: 612eccae9bb00f913c823aea9fbea2d12f18c35b
Parents: 40ee1b5
Author: Dave Brondsema <d...@brondsema.net>
Authored: Thu Mar 8 14:30:39 2018 -0500
Committer: Kenton Taylor <ktay...@slashdotmedia.com>
Committed: Fri Mar 9 15:28:59 2018 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/repository.py |  6 ++----
 Allura/allura/model/repository.py       | 22 ++++++++++++++--------
 Allura/allura/tests/model/test_repo.py  | 25 +++++++++++++++++++++----
 3 files changed, 37 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/612eccae/Allura/allura/controllers/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/repository.py 
b/Allura/allura/controllers/repository.py
index 8dcfd46..84c0baa 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -466,15 +466,12 @@ class MergeRequestController(object):
         if self.req.description != kw['description']:
             changes['Description'] = h.unidiff(self.req.description, 
kw['description'])
             self.req.description = kw['description']
-        with self.req.push_downstream_context():
-            self.req.downstream['commit_id'] = 
c.app.repo.commit(kw['source_branch'])._id
 
         if changes:
             self.req.add_meta_post(changes=changes)
             g.director.create_activity(c.user, 'updated', self.req,
                                        related_nodes=[c.project], 
tags=['merge-request'])
-
-        redirect(self.req.url())
+        self.refresh()
 
     @expose()
     @require_post()
@@ -493,6 +490,7 @@ class MergeRequestController(object):
     def refresh(self, **kw):
         require_access(self.req, 'read')
         with self.req.push_downstream_context():
+            self.req.new_commits = None  # invalidate this cache
             self.req.downstream['commit_id'] = 
c.app.repo.commit(self.req.source_branch)._id
         redirect(self.req.url())
 

http://git-wip-us.apache.org/repos/asf/allura/blob/612eccae/Allura/allura/model/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repository.py 
b/Allura/allura/model/repository.py
index fe898e9..a859c6d 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -802,6 +802,7 @@ class MergeRequest(VersionedArtifact, ActivityObject):
     summary = FieldProperty(str)
     description = FieldProperty(str)
     can_merge_cache = FieldProperty({str: bool})
+    new_commits = FieldProperty([S.Anything], if_missing=None)  # don't access 
directly, use `commits` property
 
     @property
     def activity_name(self):
@@ -839,13 +840,17 @@ class MergeRequest(VersionedArtifact, ActivityObject):
     def push_downstream_context(self):
         return h.push_context(self.downstream.project_id, 
self.downstream.mount_point)
 
-    @LazyProperty
+    @property
     def commits(self):
-        return self._commits()
+        if self.new_commits is not None:
+            return self.new_commits
 
-    def _commits(self):
         with self.push_downstream_context():
-            return c.app.repo.merge_request_commits(self)
+            # update the cache key only, being careful not to touch anything 
else that ming will try to flush later
+            # this avoids race conditions with the `set_can_merge_cache()` 
caching and clobbering fields
+            new_commits = c.app.repo.merge_request_commits(self)
+            self.query.update({'$set': {'new_commits': new_commits}})
+            return new_commits
 
     @classmethod
     def upsert(cls, **kw):
@@ -908,11 +913,12 @@ class MergeRequest(VersionedArtifact, ActivityObject):
         return self.can_merge_cache.get(key)
 
     def set_can_merge_cache(self, val):
-        from allura import model as M
         key = self.can_merge_cache_key()
-        with utils.skip_mod_date(M.MergeRequest):
-            self.can_merge_cache[key] = val
-            session(self).flush(self)
+        # update the cache key only, being careful not to touch anything else 
that ming will try to flush later
+        # this avoids race conditions with the `commits()` caching and 
clobbering fields
+        can_merge_cache = self.can_merge_cache._deinstrument()
+        can_merge_cache[key] = val
+        self.query.update({'$set': {'can_merge_cache': can_merge_cache}})
 
     def can_merge(self):
         """

http://git-wip-us.apache.org/repos/asf/allura/blob/612eccae/Allura/allura/tests/model/test_repo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_repo.py 
b/Allura/allura/tests/model/test_repo.py
index 189fdf4..efbbb4d 100644
--- a/Allura/allura/tests/model/test_repo.py
+++ b/Allura/allura/tests/model/test_repo.py
@@ -677,6 +677,7 @@ class TestModelCache(unittest.TestCase):
 
 
 class TestMergeRequest(object):
+
     def setUp(self):
         setup_basic_test()
         setup_global_objects()
@@ -685,10 +686,19 @@ class TestMergeRequest(object):
             downstream={'commit_id': '12345'},
             request_number=1,
         )
-        self.mr.app = mock.Mock(forkable=True, url='/mock-app-url/')
-        self.mr.app.repo.commit.return_value = mock.Mock(_id='09876')
-        self.mr.merge_allowed = mock.Mock(return_value=True)
-        self.mr.discussion_thread = mock.Mock()
+        self._set_mr_mock_attrs(self.mr)
+
+    def _set_mr_mock_attrs(self, mr):
+        mr.app = mock.Mock(forkable=True, url='/mock-app-url/')
+        mr.app.repo.commit.return_value = mock.Mock(_id='09876')
+        mr.merge_allowed = mock.Mock(return_value=True)
+        mr.discussion_thread = mock.Mock()
+
+    def _reload_mr_from_db(self, mr):
+        session(mr).refresh(mr)
+        mr = M.MergeRequest.query.get(_id=mr._id)
+        self._set_mr_mock_attrs(mr)
+        return mr
 
     def test_can_merge_cache_key(self):
         key = self.mr.can_merge_cache_key()
@@ -720,9 +730,16 @@ class TestMergeRequest(object):
 
     @mock.patch('allura.tasks.repo_tasks.can_merge', autospec=True)
     def test_can_merge_cached(self, can_merge_task):
+        # this test has to flush `mr` to the db and then reload it after 
changes, because set_can_merge_cache
+        # does a $set to the db and doesn't update the in-memory copy
+        session(self.mr).flush(self.mr)
+
         self.mr.set_can_merge_cache(False)
+        self.mr = self._reload_mr_from_db(self.mr)
         assert_equal(self.mr.can_merge(), False)
+
         self.mr.set_can_merge_cache(True)
+        self.mr = self._reload_mr_from_db(self.mr)
         assert_equal(self.mr.can_merge(), True)
         assert_equal(can_merge_task.post.call_count, 0)
 

Reply via email to