r66560 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66559‎ | r66560 | r66561 >
Date:12:21, 17 May 2010
Author:nikerabbit
Status:ok
Tags:
Comment:
Implement a temporary translation service suspending

If the number of failures in defined time period is exceeded,
the service will not be used until the same time period has
elapsed. Unavailable services slow down considerably the
synchronous loading, which harm user experience.
Modified paths:
  • /trunk/extensions/Translate/utils/TranslationHelpers.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Translate/utils/TranslationHelpers.php
@@ -139,10 +139,14 @@
140140 */
141141 protected function getTmBox() {
142142 global $wgTranslateTM;
 143+
143144 if ( $wgTranslateTM === false ) return null;
144145 if ( !$this->targetLanguage ) return null;
145146 if ( strval( $this->getDefinition() ) === '' ) return null;
146147
 148+ $serviceName = 'tmserver';
 149+ if ( self::checkTranslationServiceFailure( $serviceName ) ) return null;
 150+
147151 // Needed data
148152 $code = $this->targetLanguage;
149153 $definition = $this->getDefinition();
@@ -191,6 +195,9 @@
192196 $legend = implode( ' | ', $legend );
193197 $boxes[] = Html::rawElement( 'div', $params, self::legend( $legend ) . $text . self::clear() ) . "\n";
194198 }
 199+ } else {
 200+ // Assume timeout
 201+ self::reportTranslationSerficeFailure( $serviceName );
195202 }
196203
197204 // Limit to three max
@@ -217,6 +224,9 @@
218225 protected function getGoogleSuggestion() {
219226 global $wgProxyKey, $wgGoogleApiKey, $wgMemc;
220227
 228+ $serviceName = 'Google';
 229+ if ( self::checkTranslationServiceFailure( $serviceName ) ) return null;
 230+
221231 $code = $this->targetLanguage;
222232 $definition = trim( strval( $this->getDefinition() ) ) ;
223233
@@ -246,6 +256,8 @@
247257
248258 if ( $google_json === false ) {
249259 wfWarn( __METHOD__ . ': Http::get failed' );
 260+ // Most likely a timeout or other general error
 261+ self::reportTranslationSerficeFailure( $serviceName );
250262 return null;
251263 } elseif ( !is_object( $response ) ) {
252264 wfWarn( __METHOD__ . ': Unable to parse reply: ' . strval( $google_json ) );
@@ -259,6 +271,8 @@
260272 $unsupported[$code] = true;
261273 $wgMemc->set( $memckey, $unsupported, 60 * 60 * 8 );
262274 } else {
 275+ // Unknown error, assume the worst
 276+ self::reportTranslationSerficeFailure( $serviceName );
263277 wfWarn( __METHOD__ . ': ' . $response->responseDetails );
264278 error_log( __METHOD__ . ': ' . $response->responseDetails );
265279 return null;
@@ -269,6 +283,8 @@
270284 global $wgTranslateApertium, $wgMemc;
271285
272286 if ( !$wgTranslateApertium ) return null;
 287+ $serviceName = 'Apertium';
 288+ if ( self::checkTranslationServiceFailure( $serviceName ) ) return null;
273289
274290 $page = $this->page;
275291 $code = $this->targetLanguage;
@@ -323,6 +339,7 @@
324340
325341 $response = Http::get( "$wgTranslateApertium?" . wfArrayToCgi( $query ), 3 );
326342 if ( $response === false ) {
 343+ self::reportTranslationSerficeFailure( $serviceName );
327344 break; // Too slow, back off
328345 } else {
329346 $response = $this->suggestionField( Sanitizer::decodeCharReferences( $response ) );
@@ -625,4 +642,42 @@
626643
627644 return $wgUser->getSkin()->link( $target, $text, $jsEdit, $params );
628645 }
 646+
 647+ /**
 648+ * How many failures during failure period need to happen to consider
 649+ * the service being temporarily off-line. */
 650+ protected static $serviceFailureCount = 5;
 651+ /**
 652+ * How long after the last detected failure we clear the status and
 653+ * try again.
 654+ */
 655+ protected static $serviceFailurePeriod = 300;
 656+
 657+ /**
 658+ * Checks whether the given service has exceeded failure count */
 659+ public static function checkTranslationServiceFailure( $service ) {
 660+ global $wgMemc;
 661+ $key = wfMemckey( "translate-service-$service" );
 662+ // Both false and null are converted to zero, which is desirable
 663+ return intval( $wgMemc->get( $key ) ) >= self::$serviceFailureCount;
 664+ }
 665+
 666+ /**
 667+ * Increases the failure count for a given service */
 668+ public static function reportTranslationSerficeFailure( $service ) {
 669+ global $wgMemc;
 670+ $key = wfMemckey( "translate-service-$service" );
 671+ // Both false and null are converted to zero, which is desirable.
 672+ /* FIXME: not atomic, but the default incr() implemention seems to
 673+ * ignore expiry time */
 674+ $count = intval( $wgMemc->get( $key ) );
 675+ $wgMemc->set( $key, $count + 1, self::$serviceFailurePeriod );
 676+ /* By using >= we expose if something is still increasing failure
 677+ * count if we are over the limit */
 678+ if ( $count + 1 >= self::$serviceFailureCount ) {
 679+ $language = Language::factory( 'en' );
 680+ $period = $language->formatTimePeriod( self::$serviceFailurePeriod );
 681+ error_log( "Translation service $service suspended for $period" );
 682+ }
 683+ }
629684 }

Status & tagging log