MediaWiki  master
ThumbnailRenderJob.php
Go to the documentation of this file.
1 <?php
25 
31 class ThumbnailRenderJob extends Job {
32  public function __construct( Title $title, array $params ) {
33  parent::__construct( 'ThumbnailRender', $title, $params );
34  }
35 
36  public function run() {
37  $uploadThumbnailRenderMethod = MediaWikiServices::getInstance()
38  ->getMainConfig()->get( MainConfigNames::UploadThumbnailRenderMethod );
39 
40  $transformParams = $this->params['transformParams'];
41 
42  $file = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
43  ->newFile( $this->title );
44  $file->load( File::READ_LATEST );
45 
46  if ( $file && $file->exists() ) {
47  if ( $uploadThumbnailRenderMethod === 'jobqueue' ) {
48  $thumb = $file->transform( $transformParams, File::RENDER_NOW );
49 
50  if ( !$thumb || $thumb->isError() ) {
51  if ( $thumb instanceof MediaTransformError ) {
52  $this->setLastError( __METHOD__ . ': thumbnail couldn\'t be generated:' .
53  $thumb->toText() );
54  } else {
55  $this->setLastError( __METHOD__ . ': thumbnail couldn\'t be generated' );
56  }
57  return false;
58  }
59  $this->maybeEnqueueNextPage( $transformParams );
60  return true;
61  } elseif ( $uploadThumbnailRenderMethod === 'http' ) {
62  $res = $this->hitThumbUrl( $file, $transformParams );
63  $this->maybeEnqueueNextPage( $transformParams );
64  return $res;
65  } else {
66  $this->setLastError( __METHOD__ . ': unknown thumbnail render method ' .
67  $uploadThumbnailRenderMethod );
68  return false;
69  }
70  } else {
71  $this->setLastError( __METHOD__ . ': file doesn\'t exist' );
72  return false;
73  }
74  }
75 
81  protected function hitThumbUrl( LocalFile $file, $transformParams ) {
82  $config = MediaWikiServices::getInstance()->getMainConfig();
83  $uploadThumbnailRenderHttpCustomHost =
84  $config->get( MainConfigNames::UploadThumbnailRenderHttpCustomHost );
85  $uploadThumbnailRenderHttpCustomDomain =
86  $config->get( MainConfigNames::UploadThumbnailRenderHttpCustomDomain );
87  $handler = $file->getHandler();
88  if ( !$handler ) {
89  $this->setLastError( __METHOD__ . ': could not get handler' );
90  return false;
91  } elseif ( !$handler->normaliseParams( $file, $transformParams ) ) {
92  $this->setLastError( __METHOD__ . ': failed to normalize' );
93  return false;
94  }
95  $thumbName = $file->thumbName( $transformParams );
96  $thumbUrl = $file->getThumbUrl( $thumbName );
97 
98  if ( $thumbUrl === null ) {
99  $this->setLastError( __METHOD__ . ': could not get thumb URL' );
100  return false;
101  }
102 
103  if ( $uploadThumbnailRenderHttpCustomDomain ) {
104  $parsedUrl = wfParseUrl( $thumbUrl );
105 
106  if ( !isset( $parsedUrl['path'] ) || $parsedUrl['path'] === '' ) {
107  $this->setLastError( __METHOD__ . ": invalid thumb URL: $thumbUrl" );
108  return false;
109  }
110 
111  $thumbUrl = '//' . $uploadThumbnailRenderHttpCustomDomain . $parsedUrl['path'];
112  }
113 
114  wfDebug( __METHOD__ . ": hitting url {$thumbUrl}" );
115 
116  // T203135 We don't wait for the request to complete, as this is mostly fire & forget.
117  // Looking at the HTTP status of requests that take less than 1s is a double check.
118  $request = MediaWikiServices::getInstance()->getHttpRequestFactory()->create(
119  $thumbUrl,
120  [ 'method' => 'HEAD', 'followRedirects' => true, 'timeout' => 1 ],
121  __METHOD__
122  );
123 
124  if ( $uploadThumbnailRenderHttpCustomHost ) {
125  $request->setHeader( 'Host', $uploadThumbnailRenderHttpCustomHost );
126  }
127 
128  $status = $request->execute();
129  $statusCode = $request->getStatus();
130  wfDebug( __METHOD__ . ": received status {$statusCode}" );
131 
132  // 400 happens when requesting a size greater or equal than the original
133  // TODO use proper error signaling. 400 could mean a number of other things.
134  if ( $statusCode === 200 || $statusCode === 301 || $statusCode === 302 || $statusCode === 400 ) {
135  return true;
136  } elseif ( $statusCode ) {
137  $this->setLastError( __METHOD__ . ": incorrect HTTP status $statusCode when hitting $thumbUrl" );
138  } elseif ( $status->hasMessage( 'http-timed-out' ) ) {
139  // T203135 we ignore timeouts, as it would be inefficient for this job to wait for
140  // minutes for the slower thumbnails to complete.
141  return true;
142  } else {
143  $this->setLastError( __METHOD__ . ': HTTP request failure: '
144  . Status::wrap( $status )->getWikiText( false, false, 'en' ) );
145  }
146  return false;
147  }
148 
149  private function maybeEnqueueNextPage( $transformParams ) {
150  if (
151  ( $this->params['enqueueNextPage'] ?? false ) &&
152  ( $transformParams['page'] ?? 0 ) < ( $this->params['pageLimit'] ?? 0 )
153  ) {
154  $transformParams['page'] += 1;
155  $job = new ThumbnailRenderJob(
156  $this->getTitle(),
157  [
158  'transformParams' => $transformParams,
159  'enqueueNextPage' => true,
160  'pageLimit' => $this->params['pageLimit']
161  ]
162  );
163 
164  MediaWikiServices::getInstance()->getJobQueueGroup()->lazyPush( [ $job ] );
165  }
166  }
167 
172  public function allowRetries() {
173  // ThumbnailRenderJob is a warmup for the thumbnails cache,
174  // so loosing it is not a problem. Most times the job fails
175  // for non-renderable or missing images which will not be fixed
176  // by a retry, but will create additional load on the renderer.
177  return false;
178  }
179 }
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
const RENDER_NOW
Force rendering in the current process.
Definition: File.php:80
Class to both describe a background job and handle jobs.
Definition: Job.php:40
Title $title
Definition: Job.php:51
setLastError( $error)
Definition: Job.php:432
array $params
Array of job parameters.
Definition: Job.php:45
getTitle()
Definition: Job.php:146
Local file in the wiki's own database.
Definition: LocalFile.php:64
Basic media transform error class.
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:58
Represents a title within MediaWiki.
Definition: Title.php:76
Job for asynchronous rendering of thumbnails, e.g.
__construct(Title $title, array $params)
hitThumbUrl(LocalFile $file, $transformParams)
allowRetries()
Whether to retry the job.
if(count( $args)< 1) $job
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42