summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Evans <grknight@gentoo.org>2022-09-27 18:53:03 -0400
committerBrian Evans <grknight@gentoo.org>2022-09-27 19:02:02 -0400
commit5ca8d30155e11d97b20f79acec40632c2e06fcd5 (patch)
tree7531fb116791f8328c0bb0cabe42265ca67e6df9 /MLEB/Translate/utils/MessageGroupStats.php
parentMerge branch 'master' into wikitest (diff)
downloadextensions-5ca8d30155e11d97b20f79acec40632c2e06fcd5.tar.gz
extensions-5ca8d30155e11d97b20f79acec40632c2e06fcd5.tar.bz2
extensions-5ca8d30155e11d97b20f79acec40632c2e06fcd5.zip
Update MLEB to 2021.12v1.35.2
This is the final version for MW 1.35 Signed-off-by: Brian Evans <grknight@gentoo.org>
Diffstat (limited to 'MLEB/Translate/utils/MessageGroupStats.php')
-rw-r--r--MLEB/Translate/utils/MessageGroupStats.php131
1 files changed, 61 insertions, 70 deletions
diff --git a/MLEB/Translate/utils/MessageGroupStats.php b/MLEB/Translate/utils/MessageGroupStats.php
index dc7b1133..43eee5e7 100644
--- a/MLEB/Translate/utils/MessageGroupStats.php
+++ b/MLEB/Translate/utils/MessageGroupStats.php
@@ -38,7 +38,7 @@ class MessageGroupStats {
/** @var array[] */
protected static $updates = [];
/** @var string[] */
- private static $languages;
+ private static $languages;
/**
* Returns empty stats array. Useful because the number of elements
@@ -175,24 +175,28 @@ class MessageGroupStats {
* Hook: TranslateEventTranslationReview
* @param MessageHandle $handle
*/
- public static function clear( MessageHandle $handle ) {
+ public static function clear( MessageHandle $handle ): void {
$code = $handle->getCode();
+ if ( !self::isValidLanguage( $code ) ) {
+ return;
+ }
$groups = self::getSortedGroupsForClearing( $handle->getGroupIds() );
- self::internalClearGroups( $code, $groups );
+ self::internalClearGroups( $code, $groups, 0 );
}
/**
* Recalculate stats for given group(s).
*
* @param string|string[] $id Message group ids.
+ * @param int $flags Combination of FLAG_* constants.
*/
- public static function clearGroup( $id ) {
+ public static function clearGroup( $id, int $flags = 0 ): void {
$languages = self::getLanguages();
$groups = self::getSortedGroupsForClearing( (array)$id );
// Do one language at a time, to save memory
foreach ( $languages as $code ) {
- self::internalClearGroups( $code, $groups );
+ self::internalClearGroups( $code, $groups, $flags );
}
}
@@ -201,12 +205,13 @@ class MessageGroupStats {
*
* @param string $code
* @param MessageGroup[] $groups
+ * @param int $flags Combination of FLAG_* constants.
*/
- private static function internalClearGroups( $code, array $groups ) {
+ private static function internalClearGroups( $code, array $groups, int $flags ): void {
$stats = [];
foreach ( $groups as $group ) {
// $stats is modified by reference
- self::forItemInternal( $stats, $group, $code, 0 );
+ self::forItemInternal( $stats, $group, $code, $flags );
}
self::queueUpdates( 0 );
}
@@ -259,7 +264,7 @@ class MessageGroupStats {
if ( !count( $code ) ) {
return;
}
- $dbw = wfGetDB( DB_MASTER );
+ $dbw = wfGetDB( DB_PRIMARY );
$conds = [ 'tgs_lang' => $code ];
$dbw->delete( self::TABLE, $conds, __METHOD__ );
wfDebugLog( 'messagegroupstats', 'Cleared ' . serialize( $conds ) );
@@ -267,9 +272,11 @@ class MessageGroupStats {
/**
* Purges all cached stats.
+ *
+ * Mostly for testing purposes. Calling this in normal operation will cause performance issues.
*/
public static function clearAll() {
- $dbw = wfGetDB( DB_MASTER );
+ $dbw = wfGetDB( DB_PRIMARY );
$dbw->delete( self::TABLE, '*', __METHOD__ );
wfDebugLog( 'messagegroupstats', 'Cleared everything :(' );
}
@@ -278,7 +285,7 @@ class MessageGroupStats {
* Use this to extract results returned from selectRowsIdLang. You must pass the
* message group ids you want to retrieve. Entries that do not match are not returned.
*
- * @param Traversable $res Database result object
+ * @param iterable $res Database result object
* @param string[] $ids List of message group ids
* @param array[] $stats Optional array to append results to.
* @return array[]
@@ -301,26 +308,6 @@ class MessageGroupStats {
return $stats;
}
- public static function update( MessageHandle $handle, array $changes = [] ) {
- $dbids = array_map( 'self::getDatabaseIdForGroupId', $handle->getGroupIds() );
-
- $dbw = wfGetDB( DB_MASTER );
- $conds = [
- 'tgs_group' => $dbids,
- 'tgs_lang' => $handle->getCode(),
- ];
-
- $values = [];
- foreach ( [ 'total', 'translated', 'fuzzy', 'proofread' ] as $type ) {
- if ( isset( $changes[$type] ) ) {
- $values[] = "tgs_$type=tgs_$type" .
- self::stringifyNumber( $changes[$type] );
- }
- }
-
- $dbw->update( self::TABLE, $values, $conds, __METHOD__ );
- }
-
/**
* Returns an array of needed database fields.
* @param stdClass $row
@@ -412,7 +399,7 @@ class MessageGroupStats {
* @param ?string[] $ids List of message group ids
* @param ?string[] $codes List of language codes
* @param int $flags Combination of FLAG_* constants.
- * @return Traversable Database result object
+ * @return iterable Database result object
*/
protected static function selectRowsIdLang( ?array $ids, ?array $codes, $flags ) {
if ( $flags & self::FLAG_NO_CACHE ) {
@@ -450,6 +437,23 @@ class MessageGroupStats {
return $stats[$id][$code];
}
+ // It may happen that caches are requested repeatedly for a group before we get a chance
+ // to write the values to the database. Check for queued updates first. This has the
+ // benefit of avoiding duplicate rows for inserts. Ideally this would be checked before we
+ // query the database for missing values. This code is somewhat ugly as it needs to
+ // reverse engineer the values from the row format.
+ $databaseGroupId = self::getDatabaseIdForGroupId( $id );
+ $uniqueKey = "$databaseGroupId|$code";
+ $queuedValue = self::$updates[$uniqueKey] ?? null;
+ if ( $queuedValue && !( $flags & self::FLAG_NO_CACHE ) ) {
+ return [
+ self::TOTAL => $queuedValue['tgs_total'],
+ self::TRANSLATED => $queuedValue['tgs_translated'],
+ self::FUZZY => $queuedValue['tgs_fuzzy'],
+ self::PROOFREAD => $queuedValue['tgs_proofread'],
+ ];
+ }
+
if ( $group instanceof AggregateMessageGroup ) {
$aggregates = self::calculateAggregageGroup( $stats, $group, $code, $flags );
} else {
@@ -463,8 +467,8 @@ class MessageGroupStats {
return $aggregates;
}
- self::$updates[] = [
- 'tgs_group' => self::getDatabaseIdForGroupId( $id ),
+ self::$updates[$uniqueKey] = [
+ 'tgs_group' => $databaseGroupId,
'tgs_lang' => $code,
'tgs_total' => $aggregates[self::TOTAL],
'tgs_translated' => $aggregates[self::TRANSLATED],
@@ -510,8 +514,7 @@ class MessageGroupStats {
$stats[$sid][$code] = self::forItemInternal( $stats, $subgroup, $code, $flags );
}
- $include = Hooks::run( 'Translate:MessageGroupStats:isIncluded', [ $sid, $code ] );
- if ( $include ) {
+ if ( !TranslateMetadata::isExcluded( $sid, $code ) ) {
$aggregates = self::multiAdd( $aggregates, $stats[$sid][$code] );
}
}
@@ -540,22 +543,20 @@ class MessageGroupStats {
// Calculate if missing and store in the db
$collection = $group->initCollection( $code );
- if ( $code === $wgTranslateDocumentationLanguageCode ) {
- $ffs = $group->getFFS();
- if ( $ffs instanceof GettextFFS ) {
- /** @var FileBasedMessageGroup $group */
- '@phan-var FileBasedMessageGroup $group';
- $cache = $group->getMessageGroupCache( $group->getSourceLanguage() );
- if ( $cache->exists() ) {
- $template = $cache->getExtra()['TEMPLATE'] ?? [];
- $infile = [];
- foreach ( $template as $key => $data ) {
- if ( isset( $data['comments']['.'] ) ) {
- $infile[$key] = '1';
- }
+ if (
+ $code === $wgTranslateDocumentationLanguageCode
+ && $group instanceof FileBasedMessageGroup
+ ) {
+ $cache = $group->getMessageGroupCache( $group->getSourceLanguage() );
+ if ( $cache->exists() ) {
+ $template = $cache->getExtra()['TEMPLATE'] ?? [];
+ $infile = [];
+ foreach ( $template as $key => $data ) {
+ if ( isset( $data['comments']['.'] ) ) {
+ $infile[$key] = '1';
}
- $collection->setInFile( $infile );
}
+ $collection->setInFile( $infile );
}
}
@@ -585,17 +586,6 @@ class MessageGroupStats {
];
}
- /**
- * Converts input to "+2" "-4" type of string.
- * @param int $number
- * @return string
- */
- protected static function stringifyNumber( $number ) {
- $number = (int)$number;
-
- return $number < 0 ? "$number" : "+$number";
- }
-
protected static function queueUpdates( $flags ) {
if ( wfReadOnly() ) {
return;
@@ -606,35 +596,36 @@ class MessageGroupStats {
}
$lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
- $dbw = $lb->getLazyConnectionRef( DB_MASTER ); // avoid connecting yet
+ $dbw = $lb->getLazyConnectionRef( DB_PRIMARY ); // avoid connecting yet
$table = self::TABLE;
- $updates = &self::$updates;
+ $callers = wfGetAllCallers( 50 );
$updateOp = self::withLock(
$dbw,
'updates',
__METHOD__,
- function ( IDatabase $dbw, $method ) use ( $table, &$updates ) {
+ static function ( IDatabase $dbw, $method ) use ( $table, $callers ) {
// Maybe another deferred update already processed these
- if ( $updates === [] ) {
+ if ( self::$updates === [] ) {
return;
}
// This path should only be hit during web requests
- if ( count( $updates ) > 100 ) {
- $groups = array_unique( array_column( $updates, 'tgs_group' ) );
+ if ( count( self::$updates ) > 100 ) {
+ $groups = array_unique( array_column( self::$updates, 'tgs_group' ) );
LoggerFactory::getInstance( 'Translate' )->warning(
"Huge translation update of {count} rows for group(s) {groups}",
[
- 'count' => count( $updates ),
+ 'count' => count( self::$updates ),
'groups' => implode( ', ', $groups ),
+ 'callers' => $callers,
]
);
}
$primaryKey = [ 'tgs_group', 'tgs_lang' ];
- $dbw->replace( $table, [ $primaryKey ], $updates, $method );
- $updates = [];
+ $dbw->replace( $table, [ $primaryKey ], array_values( self::$updates ), $method );
+ self::$updates = [];
}
);
@@ -647,7 +638,7 @@ class MessageGroupStats {
protected static function withLock( IDatabase $dbw, $key, $method, $callback ) {
$fname = __METHOD__;
- return function () use ( $dbw, $key, $method, $callback, $fname ) {
+ return static function () use ( $dbw, $key, $method, $callback, $fname ) {
$lockName = 'MessageGroupStats:' . $key;
if ( !$dbw->lock( $lockName, $fname, 1 ) ) {
return; // raced out