public function testCanConstructEntityIdListRelevanceDetectionFilter() { $store = $this->getMockBuilder('\\SMW\\Store')->disableOriginalConstructor()->getMockForAbstractClass(); $compositePropertyTableDiffIterator = $this->getMockBuilder('\\SMW\\SQLStore\\CompositePropertyTableDiffIterator')->disableOriginalConstructor()->getMock(); $instance = new QueryDependencyLinksStoreFactory(); $this->assertInstanceOf('\\SMW\\SQLStore\\QueryDependency\\EntityIdListRelevanceDetectionFilter', $instance->newEntityIdListRelevanceDetectionFilter($store, $compositePropertyTableDiffIterator)); }
private function registerHooksForInternalUse(ApplicationFactory $applicationFactory, DeferredRequestDispatchManager $deferredRequestDispatchManager) { $queryDependencyLinksStoreFactory = new QueryDependencyLinksStoreFactory(); $queryDependencyLinksStore = $queryDependencyLinksStoreFactory->newQueryDependencyLinksStore($applicationFactory->getStore()); $transitionalDiffStore = $applicationFactory->singleton('TransitionalDiffStore'); /** * @see https://www.semantic-mediawiki.org/wiki/Hooks#SMW::SQLStore::AfterDataUpdateComplete */ $this->handlers['SMW::SQLStore::AfterDataUpdateComplete'] = function ($store, $semanticData, $compositePropertyTableDiffIterator) use($queryDependencyLinksStoreFactory, $queryDependencyLinksStore, $deferredRequestDispatchManager, $transitionalDiffStore) { // When in commandLine mode avoid deferred execution and run a process // within the same transaction $deferredRequestDispatchManager->isCommandLineMode($store->getOptions()->has('isCommandLineMode') ? $store->getOptions()->get('isCommandLineMode') : $GLOBALS['wgCommandLineMode']); $queryDependencyLinksStore->setStore($store); $subject = $semanticData->getSubject(); $slot = $transitionalDiffStore->createSlotFrom($compositePropertyTableDiffIterator); $queryDependencyLinksStore->pruneOutdatedTargetLinks($subject, $compositePropertyTableDiffIterator); $entityIdListRelevanceDetectionFilter = $queryDependencyLinksStoreFactory->newEntityIdListRelevanceDetectionFilter($store, $compositePropertyTableDiffIterator); $jobParameters = $queryDependencyLinksStore->buildParserCachePurgeJobParametersFrom($entityIdListRelevanceDetectionFilter); $deferredRequestDispatchManager->scheduleParserCachePurgeJobWith($subject->getTitle(), $jobParameters); $fulltextSearchTableFactory = new FulltextSearchTableFactory(); $textByChangeUpdater = $fulltextSearchTableFactory->newTextByChangeUpdater($store); $textByChangeUpdater->pushUpdates($compositePropertyTableDiffIterator, $deferredRequestDispatchManager, $slot); // Since we cannot predict as to when the slot is used and by whom, // schedule a job to ensure to be the last in-line to clean-up // any remaining slots for this transaction $deferredRequestDispatchManager->scheduleChronologyPurgeJobWith($subject->getTitle(), array('slot:id' => $slot)); return true; }; /** * @see https://www.semantic-mediawiki.org/wiki/Hooks#SMW::Store::AfterQueryResultLookupComplete */ $this->handlers['SMW::Store::AfterQueryResultLookupComplete'] = function ($store, &$result) use($queryDependencyLinksStore, $applicationFactory) { $queryDependencyLinksStore->setStore($store); $queryDependencyLinksStore->doUpdateDependenciesFrom($result); $applicationFactory->singleton('CachedQueryResultPrefetcher')->recordStats(); return true; }; }
/** * Based on the CHUNK_SIZE, target links are purged in an instant if those * selected entities are < CHUNK_SIZE which should be enough for most * common queries that only share a limited amount of dependencies, yet for * queries that expect a large subject/dependency pool, doing an online update * for all at once is not feasible hence the iterative process of creating * batches that run through the job scheduler. * * @param array|string $idList */ private function findEmbeddedQueryTargetLinksBatches($idList) { if (is_string($idList) && strpos($idList, '|') !== false) { $idList = explode('|', $idList); } if ($idList === array()) { return true; } $queryDependencyLinksStoreFactory = new QueryDependencyLinksStoreFactory(); $queryDependencyLinksStore = $queryDependencyLinksStoreFactory->newQueryDependencyLinksStore($this->store); $requestOptions = new RequestOptions(); // +1 to look ahead $requestOptions->setLimit($this->limit + 1); $requestOptions->setOffset($this->offset); $hashList = $queryDependencyLinksStore->findEmbeddedQueryTargetLinksHashListFor($idList, $requestOptions); if ($hashList === array()) { return true; } $countedHashListEntries = count($hashList); // If more results are available then use an iterative increase to fetch // the remaining updates by creating successive jobs if ($countedHashListEntries > $this->limit) { $job = new self($this->getTitle(), array('idlist' => $idList, 'limit' => $this->limit, 'offset' => $this->offset + self::CHUNK_SIZE)); $job->run(); } wfDebugLog('smw', __METHOD__ . " counted: {$countedHashListEntries} | offset: {$this->offset} for " . $this->getTitle()->getPrefixedDBKey() . "\n"); list($hashList, $queryList) = $this->doBuildUniqueTargetLinksHashList($hashList); $this->applicationFactory->singleton('CachedQueryResultPrefetcher')->resetCacheBy($queryList); $this->addPagesToUpdater($hashList); }