ApiQueryTags: Use cached statistics instead of querying hit counts ourselves

The hit count query was quite slow. Unfortunately, it seems that we do need
tagUsageStatistics() even when hitcounts are not requested, because it
might list additional tags that aren't listed by the list*Tags() functions.
I don't know if this can happen in practice, but all the code around tags
seems to operate as if it might.

Bug: T164552
Change-Id: Ifccf7f5ac7a1220ff67a68589398cbf30aefd3ad
This commit is contained in:
Roan Kattouw 2017-05-04 18:04:58 -07:00
parent 0c339a6167
commit 08f746478a

View file

@ -53,37 +53,24 @@ class ApiQueryTags extends ApiQueryBase {
$softwareDefinedTags = array_fill_keys( ChangeTags::listSoftwareDefinedTags(), 0 );
$explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 );
$softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 );
$tagStats = ChangeTags::tagUsageStatistics();
$definedTags = array_merge( $softwareDefinedTags, $explicitlyDefinedTags );
$tagHitcounts = array_merge( $softwareDefinedTags, $explicitlyDefinedTags, $tagStats );
$tags = array_keys( $tagHitcounts );
# Fetch defined tags that aren't past the continuation
if ( $params['continue'] !== null ) {
$cont = $params['continue'];
$tags = array_filter( array_keys( $definedTags ), function ( $v ) use ( $cont ) {
$tags = array_filter( $tags, function ( $v ) use ( $cont ) {
return $v >= $cont;
} );
$tags = array_fill_keys( $tags, 0 );
} else {
$tags = $definedTags;
}
# Merge in all used tags
$this->addTables( 'change_tag' );
$this->addFields( 'ct_tag' );
$this->addFields( [ 'hitcount' => $fld_hitcount ? 'COUNT(*)' : '0' ] );
$this->addOption( 'LIMIT', $limit + 1 );
$this->addOption( 'GROUP BY', 'ct_tag' );
$this->addWhereRange( 'ct_tag', 'newer', $params['continue'], null );
$res = $this->select( __METHOD__ );
foreach ( $res as $row ) {
$tags[$row->ct_tag] = (int)$row->hitcount;
}
# Now make sure the array is sorted for proper continuation
ksort( $tags );
sort( $tags );
$count = 0;
foreach ( $tags as $tagName => $hitcount ) {
foreach ( $tags as $tagName ) {
if ( ++$count > $limit ) {
$this->setContinueEnumParameter( 'continue', $tagName );
break;
@ -102,7 +89,7 @@ class ApiQueryTags extends ApiQueryBase {
}
if ( $fld_hitcount ) {
$tag['hitcount'] = $hitcount;
$tag['hitcount'] = intval( $tagHitcounts[$tagName] );
}
$isSoftware = isset( $softwareDefinedTags[$tagName] );