9use InvalidArgumentException;
40 private $localJobClasses;
42 private $jobTypeConfiguration;
44 private $jobTypesExcludedFromDefaultQueue;
46 private $statsFactory;
48 private $localClusterCache;
50 private $globalIdGenerator;
56 private const TYPE_ANY = 2;
60 private const PROC_CACHE_TTL = 15;
75 ?array $localJobClasses,
76 array $jobTypeConfiguration,
77 array $jobTypesExcludedFromDefaultQueue,
85 $this->localJobClasses = $localJobClasses;
86 $this->jobTypeConfiguration = $jobTypeConfiguration;
87 $this->jobTypesExcludedFromDefaultQueue = $jobTypesExcludedFromDefaultQueue;
88 $this->statsFactory = $statsFactory;
89 $this->localClusterCache = $localClusterCache;
90 $this->globalIdGenerator = $globalIdGenerator;
99 public function get( $type ) {
101 $conf += $this->jobTypeConfiguration[$type] ?? $this->jobTypeConfiguration[
'default'];
102 if ( !isset( $conf[
'readOnlyReason'] ) ) {
103 $conf[
'readOnlyReason'] = $this->readOnlyMode->getConfiguredReason();
106 $conf[
'stats'] = $this->statsFactory;
107 $conf[
'localClusterCache'] = $this->localClusterCache;
108 $conf[
'idGenerator'] = $this->globalIdGenerator;
122 public function push( $jobs ) {
123 $jobs = is_array( $jobs ) ? $jobs : [ $jobs ];
124 if ( $jobs === [] ) {
128 $this->assertValidJobs( $jobs );
131 foreach ( $jobs as
$job ) {
132 $type =
$job->getType();
133 if ( isset( $this->jobTypeConfiguration[$type] ) ) {
134 $jobsByType[$type][] =
$job;
137 isset( $this->jobTypeConfiguration[
'default'][
'typeAgnostic'] ) &&
138 $this->jobTypeConfiguration[
'default'][
'typeAgnostic']
140 $jobsByType[
'default'][] =
$job;
142 $jobsByType[$type][] =
$job;
147 foreach ( $jobsByType as $type => $jobs ) {
148 $this->
get( $type )->
push( $jobs );
151 if ( $this->cache->hasField(
'queues-ready',
'list' ) ) {
152 $list = $this->cache->getField(
'queues-ready',
'list' );
153 if ( count( array_diff( array_keys( $jobsByType ), $list ) ) ) {
154 $this->cache->clear(
'queues-ready' );
160 $cache->makeGlobalKey(
'jobqueue-hasjobs', $this->domain, self::TYPE_ANY ),
164 if ( array_diff( array_keys( $jobsByType ), $this->jobTypesExcludedFromDefaultQueue ) ) {
166 $cache->makeGlobalKey(
'jobqueue-hasjobs', $this->domain, self::TYPE_DEFAULT ),
181 if ( PHP_SAPI ===
'cli' || PHP_SAPI ===
'phpdbg' ) {
182 $this->
push( $jobs );
186 $jobs = is_array( $jobs ) ? $jobs : [ $jobs ];
189 $this->assertValidJobs( $jobs );
208 public function pop( $qtype = self::TYPE_DEFAULT, $flags = 0, array $ignored = [] ) {
211 if ( !$this->localJobClasses ) {
213 "Cannot pop '{$qtype}' job off foreign '{$this->domain}' wiki queue." );
215 if ( is_string( $qtype ) && !isset( $this->localJobClasses[$qtype] ) ) {
217 throw new JobQueueError(
"Unrecognized job type '$qtype'." );
220 if ( is_string( $qtype ) ) {
221 if ( !in_array( $qtype, $ignored ) ) {
222 $job = $this->
get( $qtype )->
pop();
225 if ( $flags & self::USE_CACHE ) {
226 if ( !$this->cache->hasField(
'queues-ready',
'list', self::PROC_CACHE_TTL ) ) {
229 $types = $this->cache->getField(
'queues-ready',
'list' );
234 if ( $qtype == self::TYPE_DEFAULT ) {
238 $types = array_diff( $types, $ignored );
241 foreach ( $types as $type ) {
242 $job = $this->
get( $type )->
pop();
246 $this->cache->clear(
'queues-ready' );
272 if ( !$this->localJobClasses ) {
273 throw new LogicException(
'Cannot inspect job queue from foreign wiki' );
275 return array_keys( $this->localJobClasses );
286 return array_diff( $this->
getQueueTypes(), $this->jobTypesExcludedFromDefaultQueue );
300 $key =
$cache->makeGlobalKey(
'jobqueue-hasjobs', $this->domain, $type );
303 if ( $value ===
false ) {
305 if ( $type == self::TYPE_DEFAULT ) {
308 $value = count( $queues ) ?
'true' :
'false';
309 $cache->add( $key, $value, 15 );
312 return ( $value ===
'true' );
326 $queue = $info[
'queue'];
327 $nonEmpty = $queue->getSiblingQueuesWithJobs( $this->
getQueueTypes() );
328 if ( is_array( $nonEmpty ) ) {
329 $types = array_merge( $types, $nonEmpty );
331 foreach ( $info[
'types'] as $type ) {
332 if ( !$this->
get( $type )->isEmpty() ) {
353 $queue = $info[
'queue'];
354 $sizes = $queue->getSiblingQueueSizes( $this->
getQueueTypes() );
355 if ( is_array( $sizes ) ) {
358 foreach ( $info[
'types'] as $type ) {
359 $sizeMap[$type] = $this->
get( $type )->getSize();
372 if ( $this->coalescedQueues ===
null ) {
373 $this->coalescedQueues = [];
374 foreach ( $this->jobTypeConfiguration as $type => $conf ) {
376 $conf[
'type'] =
'null';
377 $conf[
'stats'] = $this->statsFactory;
378 $conf[
'localClusterCache'] = $this->localClusterCache;
379 $conf[
'idGenerator'] = $this->globalIdGenerator;
382 $loc = $queue->getCoalesceLocationInternal() ??
'';
383 if ( !isset( $this->coalescedQueues[$loc] ) ) {
384 $this->coalescedQueues[$loc][
'queue'] = $queue;
385 $this->coalescedQueues[$loc][
'types'] = [];
387 if ( $type ===
'default' ) {
388 $this->coalescedQueues[$loc][
'types'] = array_merge(
389 $this->coalescedQueues[$loc][
'types'],
390 array_diff( $this->
getQueueTypes(), array_keys( $this->jobTypeConfiguration ) )
393 $this->coalescedQueues[$loc][
'types'][] = $type;
401 private function assertValidJobs( array $jobs ) {
402 foreach ( $jobs as
$job ) {
404 $type = get_debug_type(
$job );
405 throw new InvalidArgumentException(
"Expected IJobSpecification objects, got " . $type );
412class_alias( JobQueueGroup::class,
'JobQueueGroup' );
if(count( $args)< 1) $job