51 private $jobQueueGroup;
52 private const CHANNEL_NAME =
'Translate.TtmServerUpdates';
53 private LoggerInterface $logger;
61 $job =
new self( $handle->
getTitle(), [
'command' => $command ] );
75 'command' =>
'rebuild',
81 $this->jobQueueGroup = MediaWikiServices::getInstance()->getJobQueueGroup();
82 $this->logger = LoggerFactory::getInstance( self::CHANNEL_NAME );
89 public function run() {
90 $services = $this->getServersToUpdate( $this->params[
'service'] );
91 foreach ( $services as $serviceId => $service ) {
92 $this->runCommandWithRetry( $service, $serviceId );
107 private function runCommandWithRetry(
WritableTtmServer $ttmServer,
string $serviceName ): void {
109 $this->runCommand( $ttmServer, $serviceName );
110 }
catch ( Exception $e ) {
111 $this->requeueError( $serviceName, $e );
119 private function requeueError( $serviceName, $e ) {
120 $this->logger->warning(
121 'Exception thrown while running {command} on ' .
122 'service {service}: {errorMessage}',
124 'command' => $this->params[
'command'],
125 'service' => $serviceName,
126 'errorMessage' => $e->getMessage(),
130 if ( $this->params[
'errorCount'] >= self::MAX_ERROR_RETRY ) {
131 $this->logger->warning(
132 'Dropping failing job {command} for service {service} ' .
133 'after repeated failure',
135 'command' => $this->params[
'command'],
136 'service' => $serviceName,
142 $delay = self::backoffDelay( $this->params[
'errorCount'] );
144 $job->params[
'errorCount']++;
145 $job->params[
'service'] = $serviceName;
146 $job->setDelay( $delay );
148 'Update job reported failure on service {service}. ' .
149 'Requeueing job with delay of {delay}.',
151 'service' => $serviceName,
155 $this->resend( $job );
163 $this->jobQueueGroup->push( $job );
166 private function runCommand(
WritableTtmServer $ttmServer,
string $serverName ) {
167 $handle = $this->getHandle();
168 $command = $this->params[
'command'];
170 if ( $command ===
'delete' ) {
171 $this->updateItem( $ttmServer, $handle,
null,
false );
172 } elseif ( $command ===
'rebuild' ) {
173 $this->updateMessage( $ttmServer, $handle );
174 } elseif ( $command ===
'refresh' ) {
175 $this->updateTranslation( $ttmServer, $handle );
179 "{command} command completed on {server} for {handle}",
181 'command' => $command,
182 'server' => $serverName,
183 'handle' => $handle->getTitle()->getPrefixedText()
204 return Utilities::getMessageContent(
213 $translations = Utilities::getTranslations( $handle );
214 foreach ( $translations as $page => $data ) {
215 $tTitle = Title::makeTitle( $this->title->getNamespace(), $page );
217 $this->updateItem( $ttmserver, $tHandle, $data[0], $tHandle->isFuzzy() );
223 $translation = $this->getTranslation( $handle );
224 $this->updateItem( $ttmserver, $handle, $translation, $handle->
isFuzzy() );
231 $ttmserver->
update( $handle, $text );
234 private function getServersToUpdate( ?
string $requestedServiceId ): array {
235 $ttmServerFactory =
Services::getInstance()->getTtmServerFactory();
236 if ( $requestedServiceId ) {
237 if ( !$ttmServerFactory->has( $requestedServiceId ) ) {
238 $this->logger->warning(
239 'Received update job for a an unknown service {service}.',
240 [
'service' => $requestedServiceId ]
245 return [ $requestedServiceId => $ttmServerFactory->create( $requestedServiceId ) ];
249 return $ttmServerFactory->getWritable();
250 }
catch ( Exception $e ) {
251 $this->logger->error(
252 'There was an error while fetching writable TTM services. Error: {error}',
253 [
'error' => $e->getMessage() ]
272 $jobQueue = $this->jobQueueGroup->get( $this->getType() );
273 if ( !$delay || !$jobQueue->delayedJobsEnabled() ) {
276 $oldTime = $this->getReleaseTimestamp();
277 $newTime = time() + $delay;
278 if ( $oldTime !==
null && $oldTime >= $newTime ) {
281 $this->params[
'jobReleaseTimestamp' ] = $newTime;
293 static::WRITE_BACKOFF_EXPONENT + rand( 0, min( $errorCount, 4 ) )