jenkins-bot has submitted this change and it was merged.

Change subject: Track the root of a post tree explicitly
......................................................................


Track the root of a post tree explicitly

Querying the TreeRepository from the TopicHistoryIndex is open
to slave-lag issues, the just-added post may not actually
be available in the slave yet.

Anything we are saving we already know the root for, we just didn't
have the information available in the TopicHistoryIndex.  This patch
adds another field, rootPost, which is set when loading the posts. That
allows the information to make it into the TopicHistoryIndex
and remove the need for the TreeRepository there.

Bug: 58996
Bug: 59803
Bug: 59804
Bug: 59642
Change-Id: I23854ac0e36d8b892eba0d1202c1fd81dc05bd6e
---
M container.php
M includes/Block/Topic.php
M includes/Data/RecentChanges.php
M includes/Data/RevisionStorage.php
M includes/Data/RootPostLoader.php
M includes/Log/PostModerationLogger.php
M includes/Model/PostRevision.php
M includes/View/History/HistoryRenderer.php
8 files changed, 71 insertions(+), 42 deletions(-)

Approvals:
  Matthias Mullie: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/container.php b/container.php
index be03b55..6db1690 100644
--- a/container.php
+++ b/container.php
@@ -311,7 +311,7 @@
                // topic history -- to keep a history by topic we have to know 
what topic every post
                // belongs to, not just its parent. TopicHistoryIndex is a 
slight tweak to TopKIndex
                // using TreeRepository for extra information and stuffing it 
into topic_root while indexing
-               new TopicHistoryIndex( $cache, $storage, $c['repository.tree'], 
'flow_revision:topic',
+               new TopicHistoryIndex( $cache, $storage, 'flow_revision:topic',
                        array( 'topic_root_id' ),
                        array(
                                'limit' => 500,
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index 5b86f97..2a0feed 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -869,6 +869,7 @@
                        // looking for loadRootPost
                        $this->topicTitle->setChildren( array() );
                        $this->topicTitle->setDepth( 0 );
+                       $this->topicTitle->setRootPost( $this->topicTitle );
 
                        if ( !$this->permissions->isAllowed( $this->topicTitle, 
'view' ) ) {
                                $this->topicTitle = null;
@@ -931,6 +932,7 @@
                        // using the path to the root post, we can know the 
post's depth
                        $rootPath = $this->rootLoader->treeRepo->findRootPath( 
$postId );
                        $post->setDepth( count( $rootPath ) - 1 );
+                       $post->setRootPost( $found['root'] );
                }
 
                if ( $this->permissions->isAllowed( $topicTitle, 'view' )
@@ -974,13 +976,16 @@
                if ( !$found ) {
                        throw new InvalidInputException( 'Should have found 
revisions', 'missing-revision' );
                }
-               // Because storage returns a new object for every query
-               // We need to find $post in the array and replace it
                $revId = $post->getRevisionId();
+               $rootPost = $post->getRootPost();
                foreach ( $found as $idx => $revision ) {
                        if ( $revId->equals( $revision->getRevisionId() ) ) {
+                               // Because storage returns a new object for 
every query
+                               // We need to find $post in the array and 
replace it
                                $found[$idx] = $post;
-                               break;
+                       } else {
+                               // Root post needs to propogate from $post to 
found revisions
+                               $revision->setRootPost( $rootPost );
                        }
                }
                return $found;
diff --git a/includes/Data/RecentChanges.php b/includes/Data/RecentChanges.php
index 5c43ee2..8b86223 100644
--- a/includes/Data/RecentChanges.php
+++ b/includes/Data/RecentChanges.php
@@ -158,12 +158,8 @@
        }
 
        public function onAfterInsert( $object, array $row ) {
-               // There might be a more efficient way to get this workflow id
-               $workflowId = $this->tree->findRoot( $object->getPostId() );
-               if ( !$workflowId ) {
-                       wfWarn( __METHOD__ . ": could not locate root for post 
" . $object->getPostId()->getHex() );
-                       return;
-               }
+               // The workflow id is the same as the root's post id
+               $workflowId = $object->getRootPost()->getPostId();
                // These are likely already in the in-process cache
                $workflow = $this->storage->get( 'Workflow', $workflowId );
                if ( !$workflow ) {
@@ -187,23 +183,7 @@
        }
 
        protected function getTopicTitle( PostRevision $rev ) {
-               if ( $rev->isTopicTitle() ) {
-                       return $rev->getContent( 'wikitext' );
-               }
-               $topicTitleId = $this->tree->findRoot( $rev->getPostId() );
-               if ( $topicTitleId === null ) {
-                       return null;
-               }
-               $found = $this->storage->find(
-                       'PostRevision',
-                       array( 'tree_rev_descendant_id' => $topicTitleId ),
-                       array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' 
=> 1 )
-               );
-               if ( !$found ) {
-                       return null;
-               }
-
-               $content = reset( $found )->getContent( 'wikitext' );
+               $content = $rev->getRootPost()->getContent( 'wikitext' );
                if ( is_object( $content ) ) {
                        // moderated
                        return null;
diff --git a/includes/Data/RevisionStorage.php 
b/includes/Data/RevisionStorage.php
index e21441f..be4e1a0 100644
--- a/includes/Data/RevisionStorage.php
+++ b/includes/Data/RevisionStorage.php
@@ -513,26 +513,25 @@
 
        protected $treeRepository;
 
-       public function __construct( BufferedCache $cache, PostRevisionStorage 
$storage, TreeRepository $treeRepo, $prefix, array $indexed, array $options = 
array() ) {
+       public function __construct( BufferedCache $cache, PostRevisionStorage 
$storage, $prefix, array $indexed, array $options = array() ) {
                if ( $indexed !== array( 'topic_root_id' ) ) {
                        throw new \MWException( __CLASS__ . ' is hardcoded to 
only index topic_root_id: ' . print_r( $indexed, true ) );
                }
                parent::__construct( $cache, $storage, $prefix, $indexed, 
$options );
-               $this->treeRepository = $treeRepo;
        }
 
        public function onAfterInsert( $object, array $new ) {
-               $new['topic_root_id'] = $this->treeRepository->findRoot( 
UUID::create( $new['tree_rev_descendant_id'] ) )->getBinary();
+               $new['topic_root_id'] = 
$object->getRootPost()->getPostId()->getBinary();
                parent::onAfterInsert( $object, $new );
        }
 
        public function onAfterUpdate( $object, array $old, array $new ) {
-               $old['topic_root_id'] = $new['topic_root_id'] = 
$this->treeRepository->findRoot( UUID::create( $old['tree_rev_descendant_id'] ) 
)->getBinary();
+               $old['topic_root_id'] = $new['topic_root_id'] = 
$object->getRootPost()->getPostId()->getBinary();
                parent::onAfterUpdate( $object, $old, $new );
        }
 
        public function onAfterRemove( $object, array $old ) {
-               $old['topic_root_id'] = $this->treeRepository->findRoot( 
UUID::create( $old['tree_rev_descendant_id'] ) );
+               $old['topic_root_id'] = 
$object->getRootPost()->getPostId()->getBinary();
                parent::onAfterRemove( $object, $old );
        }
 
diff --git a/includes/Data/RootPostLoader.php b/includes/Data/RootPostLoader.php
index c01a285..f43a4d6 100644
--- a/includes/Data/RootPostLoader.php
+++ b/includes/Data/RootPostLoader.php
@@ -11,7 +11,9 @@
 
 /**
  * I'm pretty sure this will generally work for any subtree, not just the topic
- * root.  The problem is once you allow any subtree you need to handle things 
like
+ * root.  The problem is once you allow any subtree you need to handle the
+ * depth and root post setters better, they make the assumption the root 
provided
+ * is actually a root.
  */
 class RootPostLoader {
        public function __construct( ManagerGroup $storage, TreeRepository 
$treeRepo ) {
@@ -168,6 +170,11 @@
                foreach ( $topicIds as $id ) {
                        $roots[$id->getHex()] = $posts[$id->getHex()];
                }
+               // Attach every post in the tree to its root. setRootPost
+               // recursivly applies it to all children as well.
+               foreach ( $roots as $hex => $post ) {
+                       $post->setRootPost( $post );
+               }
                return $roots;
        }
 
diff --git a/includes/Log/PostModerationLogger.php 
b/includes/Log/PostModerationLogger.php
index 29ffc89..4a56234 100644
--- a/includes/Log/PostModerationLogger.php
+++ b/includes/Log/PostModerationLogger.php
@@ -23,9 +23,8 @@
                }
 
                if ( $this->logger->canLog( $object, $object->getChangeType() ) 
) {
-                       // This is awful but it's all I can think of
-                       $rootPost = $this->treeRepo->findRoot( 
$object->getPostId() );
-                       $workflow = $this->storage->get( 'Workflow', $rootPost 
);
+                       $rootPostId = $object->getRootPost()->getPostId();
+                       $workflow = $this->storage->get( 'Workflow', 
$rootPostId );
                        $logParams = array();
 
                        if ( $object->isTopicTitle() ) {
@@ -74,4 +73,4 @@
 
                return $changeTypes;
        }
-}
\ No newline at end of file
+}
diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php
index 01cc800..023d602 100644
--- a/includes/Model/PostRevision.php
+++ b/includes/Model/PostRevision.php
@@ -17,9 +17,22 @@
        protected $origUserIp;
        protected $replyToId;
 
-       // Data that is loaded externally and set
+       /**
+        * @var array|null Optionally loaded list of children for this post.
+        */
        protected $children;
+
+       /**
+        * @var int|null Optionally loaded distance of this post from the
+        *   root of this post tree.
+        */
        protected $depth;
+
+       /**
+        * @var PostRevision|null Optionally loaded root of this posts tree.
+        *   This is always a topic title.
+        */
+       protected $rootPost;
 
        /**
         * Variables to which callback functions and their results will be 
saved.
@@ -57,9 +70,11 @@
                $obj = static::newFromId( $topic->getId(), $user, $content );
 
                $obj->changeType = 'new-post';
-               // A newly created post has no children and a depth of 0
+               // A newly created post has no children, a depth of 0, and
+               // is the root of its tree.
                $obj->setChildren( array() );
                $obj->setDepth( 0 );
+               $obj->rootPost = $obj;
 
                return $obj;
        }
@@ -139,6 +154,7 @@
                $reply->changeType = $changeType;
                $reply->setChildren( array() );
                $reply->setDepth( $this->getDepth() + 1 );
+               $reply->rootPost = $this->rootPost;
 
                return $reply;
        }
@@ -180,6 +196,10 @@
 
        public function setChildren( array $children ) {
                $this->children = $children;
+               if ( $this->rootPost ) {
+                       // Propagate root post into children.
+                       $this->setRootPost( $this->rootPost );
+               }
        }
 
        public function getChildren() {
@@ -190,7 +210,7 @@
        }
 
        public function setDepth( $depth ) {
-               $this->depth = $depth;
+               $this->depth = (int)$depth;
        }
 
        public function getDepth() {
@@ -200,6 +220,25 @@
                return $this->depth;
        }
 
+       public function setRootPost( PostRevision $root ) {
+               $this->rootPost = $root;
+               if ( $this->children ) {
+                       // Propagate root post into children.
+                       foreach ( $this->children as $child ) {
+                               $child->setRootPost( $root );
+                       }
+               }
+       }
+
+       public function getRootPost() {
+               if ( $this->isTopicTitle() ) {
+                       return $this;
+               } elseif ( $this->rootPost === null ) {
+                       throw new DataModelException( 'Root not loaded for 
post: ' . $this->postId->getHex(), 'process-data' );
+               }
+               return $this->rootPost;
+       }
+
        /**
         * Get the amount of posts in this topic.
         *
diff --git a/includes/View/History/HistoryRenderer.php 
b/includes/View/History/HistoryRenderer.php
index 01da775..2335af4 100644
--- a/includes/View/History/HistoryRenderer.php
+++ b/includes/View/History/HistoryRenderer.php
@@ -196,9 +196,9 @@
                } else {
                        $revision = $record->getRevision();
                        if ( isset( 
$this->workflows[$revision->getRevisionId()->getHex()] ) ) {
-                               $workFlowId = 
$this->workflows[$revision->getRevisionId()->getHex()];
+                               $workflowId = 
$this->workflows[$revision->getRevisionId()->getHex()];
                                $historicalLink = 
$this->templating->getUrlGenerator()->generateBlockUrl(
-                                       $workFlowId,
+                                       $workflowId,
                                        $revision,
                                        true
                                );

-- 
To view, visit https://gerrit.wikimedia.org/r/106449
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I23854ac0e36d8b892eba0d1202c1fd81dc05bd6e
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <ebernhard...@wikimedia.org>
Gerrit-Reviewer: Bsitu <bs...@wikimedia.org>
Gerrit-Reviewer: EBernhardson <ebernhard...@wikimedia.org>
Gerrit-Reviewer: Matthias Mullie <mmul...@wikimedia.org>
Gerrit-Reviewer: Spage <sp...@wikimedia.org>
Gerrit-Reviewer: Werdna <agarr...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to