Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
97.73% |
43 / 44 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
| ShowJobs | |
97.73% |
43 / 44 |
|
50.00% |
1 / 2 |
13 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| execute | |
97.30% |
36 / 37 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * @license GPL-2.0-or-later |
| 4 | * @file |
| 5 | */ |
| 6 | |
| 7 | use MediaWiki\JobQueue\Job; |
| 8 | use MediaWiki\Maintenance\Maintenance; |
| 9 | |
| 10 | // @codeCoverageIgnoreStart |
| 11 | require_once __DIR__ . '/Maintenance.php'; |
| 12 | // @codeCoverageIgnoreEnd |
| 13 | |
| 14 | /** |
| 15 | * Report number of jobs currently waiting in primary database. |
| 16 | * |
| 17 | * Based on runJobs.php. Note that this only works for JobQueue backends |
| 18 | * that implement JobQueue::doGetSize. Implementations based on Kafka, |
| 19 | * for example, might not have a way to obtain this. In that case, |
| 20 | * telemetry should be provided externally, e.g. with Grafana/Prometheus. |
| 21 | * |
| 22 | * @ingroup Maintenance |
| 23 | * @author Tim Starling |
| 24 | * @author Antoine Musso |
| 25 | */ |
| 26 | class ShowJobs extends Maintenance { |
| 27 | private const STATE_METHODS = [ |
| 28 | 'unclaimed' => 'getAllQueuedJobs', |
| 29 | 'delayed' => 'getAllDelayedJobs', |
| 30 | 'claimed' => 'getAllAcquiredJobs', |
| 31 | 'abandoned' => 'getAllAbandonedJobs', |
| 32 | ]; |
| 33 | |
| 34 | public function __construct() { |
| 35 | parent::__construct(); |
| 36 | $this->addDescription( 'Show number of jobs waiting in primary database' ); |
| 37 | $this->addOption( 'group', 'Show number of jobs per job type' ); |
| 38 | $this->addOption( 'list', 'Show a list of all jobs instead of counts' ); |
| 39 | $this->addOption( 'type', 'Only show/count jobs of a given type', false, true ); |
| 40 | $this->addOption( 'status', 'Filter list by state (unclaimed,delayed,claimed,abandoned)' ); |
| 41 | $this->addOption( 'limit', 'Limit of jobs listed' ); |
| 42 | } |
| 43 | |
| 44 | public function execute() { |
| 45 | $typeFilter = $this->getOption( 'type', '' ); |
| 46 | $stateFilter = $this->getOption( 'status', '' ); |
| 47 | $stateLimit = (float)$this->getOption( 'limit', INF ); |
| 48 | |
| 49 | $group = $this->getServiceContainer()->getJobQueueGroup(); |
| 50 | |
| 51 | $filteredTypes = $typeFilter |
| 52 | ? [ $typeFilter ] |
| 53 | : $group->getQueueTypes(); |
| 54 | $filteredStates = $stateFilter |
| 55 | ? array_intersect_key( self::STATE_METHODS, [ $stateFilter => 1 ] ) |
| 56 | : self::STATE_METHODS; |
| 57 | |
| 58 | if ( $this->hasOption( 'list' ) ) { |
| 59 | $count = 0; |
| 60 | foreach ( $filteredTypes as $type ) { |
| 61 | $queue = $group->get( $type ); |
| 62 | foreach ( $filteredStates as $state => $method ) { |
| 63 | foreach ( $queue->$method() as $job ) { |
| 64 | /** @var Job $job */ |
| 65 | $this->output( $job->toString() . " status=$state\n" ); |
| 66 | if ( ++$count >= $stateLimit ) { |
| 67 | return; |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | } elseif ( $this->hasOption( 'group' ) ) { |
| 73 | foreach ( $filteredTypes as $type ) { |
| 74 | $queue = $group->get( $type ); |
| 75 | $delayed = $queue->getDelayedCount(); |
| 76 | $pending = $queue->getSize(); |
| 77 | $claimed = $queue->getAcquiredCount(); |
| 78 | $abandoned = $queue->getAbandonedCount(); |
| 79 | $active = max( 0, $claimed - $abandoned ); |
| 80 | if ( ( $pending + $claimed + $delayed + $abandoned ) > 0 ) { |
| 81 | $this->output( |
| 82 | "{$type}: $pending queued; " . |
| 83 | "$claimed claimed ($active active, $abandoned abandoned); " . |
| 84 | "$delayed delayed\n" |
| 85 | ); |
| 86 | } |
| 87 | } |
| 88 | } else { |
| 89 | $count = 0; |
| 90 | foreach ( $filteredTypes as $type ) { |
| 91 | $count += $group->get( $type )->getSize(); |
| 92 | } |
| 93 | $this->output( "$count\n" ); |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // @codeCoverageIgnoreStart |
| 99 | $maintClass = ShowJobs::class; |
| 100 | require_once RUN_MAINTENANCE_IF_MAIN; |
| 101 | // @codeCoverageIgnoreEnd |