/** * Accepts a result set as sent out to the CategoryViewer::doCategoryQuery * hook. * * @param ResultWrapper|array $rows */ public function loadMetadataBatch($rows) { $neededPosts = array(); $neededWorkflows = array(); foreach ($rows as $row) { if ($row->page_namespace != NS_TOPIC) { continue; } $uuid = UUID::create(strtolower($row->page_title)); if ($uuid) { $alpha = $uuid->getAlphadecimal(); $neededPosts[$alpha] = array('rev_type_id' => $uuid); $neededWorkflows[$alpha] = $uuid; } } if (!$neededPosts) { return; } $this->posts = $this->storage->findMulti('PostRevision', $neededPosts, array('sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1)); $workflows = $this->storage->getMulti('Workflow', $neededWorkflows); // @todo fixme: these should have come back with the apropriate array // key since we passed it in above, but didn't. foreach ($workflows as $workflow) { $this->workflows[$workflow->getId()->getAlphadecimal()] = $workflow; } }
/** * Overwriting default writer because I want to use Flow storage methods so * the updates also affect cache, not just DB. * * @param array[] $updates */ public function write(array $updates) { /* * from: * array( * 'primaryKey' => array( 'workflow_id' => $id ), * 'updates' => array( 'workflow_last_update_timestamp' => $timestamp ), * ) * to: * array( $id => $timestamp ); */ $timestamps = array_combine($this->arrayColumn($this->arrayColumn($updates, 'primaryKey'), 'workflow_id'), $this->arrayColumn($this->arrayColumn($updates, 'changes'), 'workflow_last_update_timestamp')); /** @var UUID[] $uuids */ $uuids = array_map(array('Flow\\Model\\UUID', 'create'), array_keys($timestamps)); /** @var Workflow[] $workflows */ $workflows = $this->storage->getMulti('Workflow', $uuids); foreach ($workflows as $workflow) { $timestamp = $timestamps[$workflow->getId()->getBinary()]; $workflow->updateLastModified(UUID::getComparisonUUID($timestamp)); } $this->storage->multiPut($workflows); // prevent memory from filling up $this->storage->clear(); wfWaitForSlaves(false, false, $this->clusterName); }
/** * Entry point for batch loading metadata for a variety of revisions * into the internal cache. * * @param AbstractRevision[]|ResultWrapper $results */ protected function loadMetadataBatch($results) { // Batch load data related to a list of revisions $postIds = array(); $workflowIds = array(); $revisions = array(); $previousRevisionIds = array(); $collectionIds = array(); foreach ($results as $result) { if ($result instanceof PostRevision) { // If top-level, then just get the workflow. // Otherwise we need to find the root post. $id = $result->getPostId(); $alpha = $id->getAlphadecimal(); if ($result->isTopicTitle()) { $workflowIds[] = $id; } else { $postIds[$alpha] = $id; } $this->postCache[$alpha] = $result; } elseif ($result instanceof Header) { $workflowIds[] = $result->getWorkflowId(); } elseif ($result instanceof PostSummary) { // This would be the post id for the summary $id = $result->getSummaryTargetId(); $postIds[$id->getAlphadecimal()] = $id; } $revisions[$result->getRevisionId()->getAlphadecimal()] = $result; if ($this->needsPreviousRevision($result)) { $previousRevisionIds[get_class($result)][] = $result->getPrevRevisionId(); } $collection = $result->getCollection(); $collectionIds[get_class($result)][] = $collection->getId(); } // map from post Id to the related root post id $rootPostIds = array_filter($this->treeRepository->findRoots($postIds)); $rootPostRequests = array(); foreach ($rootPostIds as $postId) { $rootPostRequests[] = array('rev_type_id' => $postId); } // these tree identity maps are required for determining where a reply goes when // // replying to a specific post. $identityMap = $this->treeRepository->fetchSubtreeIdentityMap(array_unique($rootPostIds, SORT_REGULAR)); $rootPostResult = $this->storage->findMulti('PostRevision', $rootPostRequests, array('SORT' => 'rev_id', 'ORDER' => 'DESC', 'LIMIT' => 1)); $rootPosts = array(); if (count($rootPostResult) > 0) { foreach ($rootPostResult as $found) { $root = reset($found); $rootPosts[$root->getPostId()->getAlphadecimal()] = $root; $revisions[$root->getRevisionId()->getAlphadecimal()] = $root; } } // Workflow IDs are the same as root post IDs // So any post IDs that *are* root posts + found root post IDs + header workflow IDs // should cover the lot. $workflows = $this->storage->getMulti('Workflow', array_merge($rootPostIds, $workflowIds)); $workflows = $workflows ?: array(); // preload all requested previous revisions foreach ($previousRevisionIds as $revisionType => $ids) { // get rid of null-values (for original revisions, without previous revision) $ids = array_filter($ids); /** @var AbstractRevision[] $found */ $found = $this->storage->getMulti($revisionType, $ids); foreach ($found as $rev) { $revisions[$rev->getRevisionId()->getAlphadecimal()] = $rev; } } // preload all current versions foreach ($collectionIds as $revisionType => $ids) { $queries = array(); foreach ($ids as $uuid) { $queries[] = array('rev_type_id' => $uuid); } $found = $this->storage->findMulti($revisionType, $queries, array('sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1)); /** @var AbstractRevision[] $result */ foreach ($found as $result) { $rev = reset($result); $this->currentRevisionsCache[$rev->getCollectionId()->getAlphadecimal()] = $rev->getRevisionId(); $revisions[$rev->getRevisionId()->getAlphadecimal()] = $rev; } } $this->revisionCache = array_merge($this->revisionCache, $revisions); $this->postCache = array_merge($this->postCache, $rootPosts); $this->rootPostIdCache = array_merge($this->rootPostIdCache, $rootPostIds); $this->workflowCache = array_merge($this->workflowCache, $workflows); $this->identityMap = array_merge($this->identityMap, $identityMap); }