48 private $jobQueueGroup;
49 private const CHANNEL_NAME =
'Translate.TtmServerUpdates';
50 private LoggerInterface $logger;
58 $job =
new self( $handle->
getTitle(), [
'command' => $command ] );
69 'TTMServerMessageUpdateJob',
72 'command' =>
'rebuild',
78 $this->jobQueueGroup = MediaWikiServices::getInstance()->getJobQueueGroup();
79 $this->logger = LoggerFactory::getInstance( self::CHANNEL_NAME );
86 public function run() {
87 $services = $this->getServersToUpdate( $this->params[
'service'] );
88 foreach ( $services as $serviceId => $service ) {
89 $this->runCommandWithRetry( $service, $serviceId );
104 private function runCommandWithRetry(
WritableTtmServer $ttmServer,
string $serviceName ): void {
106 $this->runCommand( $ttmServer, $serviceName );
107 }
catch ( Exception $e ) {
108 $this->requeueError( $serviceName, $e );
116 private function requeueError( $serviceName, $e ) {
117 $this->logger->warning(
118 'Exception thrown while running {command} on ' .
119 'service {service}: {errorMessage}',
121 'command' => $this->params[
'command'],
122 'service' => $serviceName,
123 'errorMessage' => $e->getMessage(),
127 if ( $this->params[
'errorCount'] >= self::MAX_ERROR_RETRY ) {
128 $this->logger->warning(
129 'Dropping failing job {command} for service {service} ' .
130 'after repeated failure',
132 'command' => $this->params[
'command'],
133 'service' => $serviceName,
139 $delay = self::backoffDelay( $this->params[
'errorCount'] );
141 $job->params[
'errorCount']++;
142 $job->params[
'service'] = $serviceName;
143 $job->setDelay( $delay );
145 'Update job reported failure on service {service}. ' .
146 'Requeueing job with delay of {delay}.',
148 'service' => $serviceName,
152 $this->resend( $job );
160 $this->jobQueueGroup->push( $job );
163 private function runCommand(
WritableTtmServer $ttmServer,
string $serverName ) {
164 $handle = $this->getHandle();
165 $command = $this->params[
'command'];
167 if ( $command ===
'delete' ) {
168 $this->updateItem( $ttmServer, $handle,
null,
false );
169 } elseif ( $command ===
'rebuild' ) {
170 $this->updateMessage( $ttmServer, $handle );
171 } elseif ( $command ===
'refresh' ) {
172 $this->updateTranslation( $ttmServer, $handle );
176 "{command} command completed on {server} for {handle}",
178 'command' => $command,
179 'server' => $serverName,
180 'handle' => $handle->getTitle()->getPrefixedText()
201 return Utilities::getMessageContent(
210 $translations = Utilities::getTranslations( $handle );
211 foreach ( $translations as $page => $data ) {
212 $tTitle = Title::makeTitle( $this->title->getNamespace(), $page );
214 $this->updateItem( $ttmserver, $tHandle, $data[0], $tHandle->isFuzzy() );
220 $translation = $this->getTranslation( $handle );
221 $this->updateItem( $ttmserver, $handle, $translation, $handle->
isFuzzy() );
228 $ttmserver->
update( $handle, $text );
231 private function getServersToUpdate( ?
string $requestedServiceId ): array {
232 $ttmServerFactory =
Services::getInstance()->getTtmServerFactory();
233 if ( $requestedServiceId ) {
234 if ( !$ttmServerFactory->has( $requestedServiceId ) ) {
235 $this->logger->warning(
236 'Received update job for a an unknown service {service}.',
237 [
'service' => $requestedServiceId ]
242 return [ $requestedServiceId => $ttmServerFactory->create( $requestedServiceId ) ];
246 return $ttmServerFactory->getWritable();
247 }
catch ( Exception $e ) {
248 $this->logger->error(
249 'There was an error while fetching writable TTM services. Error: {error}',
250 [
'error' => $e->getMessage() ]
269 $jobQueue = $this->jobQueueGroup->get( $this->getType() );
270 if ( !$delay || !$jobQueue->delayedJobsEnabled() ) {
273 $oldTime = $this->getReleaseTimestamp();
274 $newTime = time() + $delay;
275 if ( $oldTime !==
null && $oldTime >= $newTime ) {
278 $this->params[
'jobReleaseTimestamp' ] = $newTime;
290 static::WRITE_BACKOFF_EXPONENT + rand( 0, min( $errorCount, 4 ) )