2013-04-20 21:27:46 +00:00
< ? php
2024-05-23 07:26:56 +00:00
2013-04-20 21:27:46 +00:00
/**
2024-05-23 07:26:56 +00:00
* SPDX - FileCopyrightText : 2016 - 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX - FileCopyrightText : 2016 ownCloud , Inc .
* SPDX - License - Identifier : AGPL - 3.0 - only
2013-04-20 21:27:46 +00:00
*/
namespace OC\BackgroundJob ;
2015-12-18 10:44:32 +00:00
use OCP\AppFramework\QueryException ;
2016-05-18 12:27:48 +00:00
use OCP\AppFramework\Utility\ITimeFactory ;
2019-11-22 19:52:10 +00:00
use OCP\AutoloadNotAllowedException ;
2015-12-18 09:04:30 +00:00
use OCP\BackgroundJob\IJob ;
2014-02-12 12:32:16 +00:00
use OCP\BackgroundJob\IJobList ;
2023-07-20 11:38:07 +00:00
use OCP\BackgroundJob\IParallelAwareJob ;
2023-04-20 10:55:06 +00:00
use OCP\DB\Exception ;
2016-02-29 08:44:40 +00:00
use OCP\DB\QueryBuilder\IQueryBuilder ;
2016-05-18 12:27:48 +00:00
use OCP\IConfig ;
use OCP\IDBConnection ;
2023-04-24 15:16:15 +00:00
use Psr\Log\LoggerInterface ;
2023-09-27 12:53:04 +00:00
use function get_class ;
use function json_encode ;
use function strlen ;
2014-02-12 12:32:16 +00:00
class JobList implements IJobList {
2024-08-09 20:38:33 +00:00
public function __construct (
protected IDBConnection $connection ,
protected IConfig $config ,
protected ITimeFactory $timeFactory ,
protected LoggerInterface $logger ,
2024-08-09 20:47:32 +00:00
) {
2014-02-11 13:00:24 +00:00
}
2024-03-28 15:13:19 +00:00
public function add ( $job , $argument = null , ? int $firstCheck = null ) : void {
2023-09-27 12:53:04 +00:00
if ( $firstCheck === null ) {
$firstCheck = $this -> timeFactory -> getTime ();
}
2024-08-09 20:38:33 +00:00
$class = ( $job instanceof IJob ) ? get_class ( $job ) : $job ;
2015-12-18 08:47:54 +00:00
2021-12-21 07:05:50 +00:00
$argumentJson = json_encode ( $argument );
if ( strlen ( $argumentJson ) > 4000 ) {
throw new \InvalidArgumentException ( 'Background job arguments can\'t exceed 4000 characters (json encoded)' );
}
2015-12-18 08:47:54 +00:00
2021-12-21 07:05:50 +00:00
$query = $this -> connection -> getQueryBuilder ();
if ( ! $this -> has ( $job , $argument )) {
2015-12-18 08:47:54 +00:00
$query -> insert ( 'jobs' )
-> values ([
'class' => $query -> createNamedParameter ( $class ),
2021-12-21 07:05:50 +00:00
'argument' => $query -> createNamedParameter ( $argumentJson ),
2024-08-28 15:03:53 +00:00
'argument_hash' => $query -> createNamedParameter ( hash ( 'sha256' , $argumentJson )),
2016-02-29 08:44:40 +00:00
'last_run' => $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ),
2023-09-27 12:53:04 +00:00
'last_checked' => $query -> createNamedParameter ( $firstCheck , IQueryBuilder :: PARAM_INT ),
2015-12-18 08:47:54 +00:00
]);
2021-12-21 07:05:50 +00:00
} else {
$query -> update ( 'jobs' )
-> set ( 'reserved_at' , $query -> expr () -> literal ( 0 , IQueryBuilder :: PARAM_INT ))
2023-09-27 12:53:04 +00:00
-> set ( 'last_checked' , $query -> createNamedParameter ( $firstCheck , IQueryBuilder :: PARAM_INT ))
2023-12-15 10:49:51 +00:00
-> set ( 'last_run' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
2021-12-21 07:05:50 +00:00
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )))
2024-08-28 15:03:53 +00:00
-> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( hash ( 'sha256' , $argumentJson ))));
2013-04-20 21:27:46 +00:00
}
2021-12-21 07:05:50 +00:00
$query -> executeStatement ();
2013-04-20 21:27:46 +00:00
}
2023-09-27 12:53:04 +00:00
public function scheduleAfter ( string $job , int $runAfter , $argument = null ) : void {
$this -> add ( $job , $argument , $runAfter );
}
2013-04-20 21:27:46 +00:00
/**
2015-12-18 09:04:30 +00:00
* @ param IJob | string $job
2013-04-20 21:27:46 +00:00
* @ param mixed $argument
*/
2022-05-23 09:21:22 +00:00
public function remove ( $job , $argument = null ) : void {
2024-08-09 20:38:33 +00:00
$class = ( $job instanceof IJob ) ? get_class ( $job ) : $job ;
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> delete ( 'jobs' )
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )));
2013-04-20 21:27:46 +00:00
if ( ! is_null ( $argument )) {
2022-03-02 08:23:16 +00:00
$argumentJson = json_encode ( $argument );
2024-08-28 15:03:53 +00:00
$query -> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( hash ( 'sha256' , $argumentJson ))));
2013-04-20 21:27:46 +00:00
}
2022-01-20 09:47:00 +00:00
// Add galera safe delete chunking if using mysql
// Stops us hitting wsrep_max_ws_rows when large row counts are deleted
2024-07-01 14:59:47 +00:00
if ( $this -> connection -> getDatabaseProvider () === IDBConnection :: PLATFORM_MYSQL ) {
2022-01-20 09:47:00 +00:00
// Then use chunked delete
$max = IQueryBuilder :: MAX_ROW_DELETION ;
$query -> setMaxResults ( $max );
do {
2024-08-09 20:38:33 +00:00
$deleted = $query -> executeStatement ();
2022-01-20 09:47:00 +00:00
} while ( $deleted === $max );
} else {
// Dont use chunked delete - let the DB handle the large row count natively
2024-08-09 20:38:33 +00:00
$query -> executeStatement ();
2022-01-20 09:47:00 +00:00
}
2013-04-20 21:27:46 +00:00
}
2024-05-30 13:07:26 +00:00
public function removeById ( int $id ) : void {
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> delete ( 'jobs' )
2016-02-29 08:44:40 +00:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $id , IQueryBuilder :: PARAM_INT )));
2022-05-23 09:21:22 +00:00
$query -> executeStatement ();
2015-08-19 12:16:05 +00:00
}
2013-04-20 21:27:46 +00:00
/**
* check if a job is in the list
*
2022-07-11 09:41:47 +00:00
* @ param IJob | class - string < IJob > $job
2013-04-20 21:27:46 +00:00
* @ param mixed $argument
*/
2022-05-23 09:21:22 +00:00
public function has ( $job , $argument ) : bool {
2024-08-09 20:38:33 +00:00
$class = ( $job instanceof IJob ) ? get_class ( $job ) : $job ;
2013-04-20 21:27:46 +00:00
$argument = json_encode ( $argument );
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( 'id' )
-> from ( 'jobs' )
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )))
2024-08-28 15:03:53 +00:00
-> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( hash ( 'sha256' , $argument ))))
2015-12-18 08:47:54 +00:00
-> setMaxResults ( 1 );
2022-05-23 09:21:22 +00:00
$result = $query -> executeQuery ();
2015-12-18 08:47:54 +00:00
$row = $result -> fetch ();
$result -> closeCursor ();
return ( bool ) $row ;
2013-04-20 21:27:46 +00:00
}
2023-01-12 16:18:59 +00:00
public function getJobs ( $job , ? int $limit , int $offset ) : array {
$iterable = $this -> getJobsIterator ( $job , $limit , $offset );
2024-08-09 20:38:33 +00:00
return ( is_array ( $iterable ))
? $iterable
: iterator_to_array ( $iterable );
2023-01-12 16:18:59 +00:00
}
2022-06-27 09:53:10 +00:00
/**
* @ param IJob | class - string < IJob >| null $job
2023-01-10 17:20:31 +00:00
* @ return iterable < IJob > Avoid to store these objects as they may share a Singleton instance . You should instead use these IJobs instances while looping on the iterable .
2022-06-27 09:53:10 +00:00
*/
2023-01-12 16:18:59 +00:00
public function getJobsIterator ( $job , ? int $limit , int $offset ) : iterable {
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
2022-05-23 10:30:26 +00:00
-> from ( 'jobs' )
-> setMaxResults ( $limit )
-> setFirstResult ( $offset );
if ( $job !== null ) {
2024-08-09 20:38:33 +00:00
$class = ( $job instanceof IJob ) ? get_class ( $job ) : $job ;
2022-05-23 10:30:26 +00:00
$query -> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )));
}
2022-05-23 09:21:22 +00:00
$result = $query -> executeQuery ();
2015-12-18 08:47:54 +00:00
while ( $row = $result -> fetch ()) {
2014-07-25 16:02:02 +00:00
$job = $this -> buildJob ( $row );
if ( $job ) {
2023-01-10 17:20:31 +00:00
yield $job ;
2014-07-25 16:02:02 +00:00
}
2013-04-20 21:27:46 +00:00
}
2015-12-18 08:47:54 +00:00
$result -> closeCursor ();
2013-04-20 21:27:46 +00:00
}
/**
2024-04-09 09:12:48 +00:00
* @ inheritDoc
2013-04-20 21:27:46 +00:00
*/
2024-04-08 15:25:51 +00:00
public function getNext ( bool $onlyTimeSensitive = false , ? array $jobClasses = null ) : ? IJob {
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2018-11-01 11:52:09 +00:00
-> where ( $query -> expr () -> lte ( 'reserved_at' , $query -> createNamedParameter ( $this -> timeFactory -> getTime () - 12 * 3600 , IQueryBuilder :: PARAM_INT )))
2018-06-26 14:24:08 +00:00
-> andWhere ( $query -> expr () -> lte ( 'last_checked' , $query -> createNamedParameter ( $this -> timeFactory -> getTime (), IQueryBuilder :: PARAM_INT )))
2016-05-18 12:27:48 +00:00
-> orderBy ( 'last_checked' , 'ASC' )
2015-12-18 08:47:54 +00:00
-> setMaxResults ( 1 );
2016-05-18 12:27:48 +00:00
2022-01-31 16:56:43 +00:00
if ( $onlyTimeSensitive ) {
$query -> andWhere ( $query -> expr () -> eq ( 'time_sensitive' , $query -> createNamedParameter ( IJob :: TIME_SENSITIVE , IQueryBuilder :: PARAM_INT )));
}
2024-07-04 09:26:17 +00:00
if ( ! empty ( $jobClasses )) {
$orClasses = [];
2024-04-08 15:25:51 +00:00
foreach ( $jobClasses as $jobClass ) {
2024-07-04 09:26:17 +00:00
$orClasses [] = $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $jobClass , IQueryBuilder :: PARAM_STR ));
2024-04-08 15:25:51 +00:00
}
2024-07-04 09:26:17 +00:00
$query -> andWhere ( $query -> expr () -> orX ( ... $orClasses ));
2021-12-21 07:57:53 +00:00
}
2022-05-23 09:21:22 +00:00
$result = $query -> executeQuery ();
2015-12-18 08:47:54 +00:00
$row = $result -> fetch ();
$result -> closeCursor ();
if ( $row ) {
2023-07-20 11:38:07 +00:00
$job = $this -> buildJob ( $row );
if ( $job instanceof IParallelAwareJob && ! $job -> getAllowParallelRuns () && $this -> hasReservedJob ( get_class ( $job ))) {
2024-07-05 07:47:40 +00:00
$this -> logger -> info ( 'Skipping ' . get_class ( $job ) . ' job with ID ' . $job -> getId () . ' because another job with the same class is already running' , [ 'app' => 'cron' ]);
2023-07-20 11:38:07 +00:00
$update = $this -> connection -> getQueryBuilder ();
$update -> update ( 'jobs' )
-> set ( 'last_checked' , $update -> createNamedParameter ( $this -> timeFactory -> getTime () + 1 ))
-> where ( $update -> expr () -> eq ( 'id' , $update -> createParameter ( 'jobid' )));
$update -> setParameter ( 'jobid' , $row [ 'id' ]);
$update -> executeStatement ();
return $this -> getNext ( $onlyTimeSensitive );
}
$update = $this -> connection -> getQueryBuilder ();
$update -> update ( 'jobs' )
-> set ( 'reserved_at' , $update -> createNamedParameter ( $this -> timeFactory -> getTime ()))
-> set ( 'last_checked' , $update -> createNamedParameter ( $this -> timeFactory -> getTime ()))
-> where ( $update -> expr () -> eq ( 'id' , $update -> createParameter ( 'jobid' )))
-> andWhere ( $update -> expr () -> eq ( 'reserved_at' , $update -> createParameter ( 'reserved_at' )))
-> andWhere ( $update -> expr () -> eq ( 'last_checked' , $update -> createParameter ( 'last_checked' )));
2016-05-18 12:27:48 +00:00
$update -> setParameter ( 'jobid' , $row [ 'id' ]);
2017-04-07 10:53:44 +00:00
$update -> setParameter ( 'reserved_at' , $row [ 'reserved_at' ]);
$update -> setParameter ( 'last_checked' , $row [ 'last_checked' ]);
2022-05-23 09:21:22 +00:00
$count = $update -> executeStatement ();
2016-05-18 12:27:48 +00:00
2017-04-07 10:53:44 +00:00
if ( $count === 0 ) {
// Background job already executed elsewhere, try again.
2024-04-08 15:25:51 +00:00
return $this -> getNext ( $onlyTimeSensitive , $jobClasses );
2017-04-07 10:53:44 +00:00
}
2016-05-18 12:27:48 +00:00
if ( $job === null ) {
2018-06-26 14:24:08 +00:00
// set the last_checked to 12h in the future to not check failing jobs all over again
$reset = $this -> connection -> getQueryBuilder ();
$reset -> update ( 'jobs' )
-> set ( 'reserved_at' , $reset -> expr () -> literal ( 0 , IQueryBuilder :: PARAM_INT ))
-> set ( 'last_checked' , $reset -> createNamedParameter ( $this -> timeFactory -> getTime () + 12 * 3600 , IQueryBuilder :: PARAM_INT ))
-> where ( $reset -> expr () -> eq ( 'id' , $reset -> createNamedParameter ( $row [ 'id' ], IQueryBuilder :: PARAM_INT )));
2022-05-23 09:21:22 +00:00
$reset -> executeStatement ();
2018-06-26 14:24:08 +00:00
2016-05-18 12:27:48 +00:00
// Background job from disabled app, try again.
2024-04-08 15:25:51 +00:00
return $this -> getNext ( $onlyTimeSensitive , $jobClasses );
2013-04-20 21:27:46 +00:00
}
2015-12-18 08:47:54 +00:00
2015-08-19 12:16:05 +00:00
return $job ;
2016-05-18 12:27:48 +00:00
} else {
return null ;
2015-08-19 12:16:05 +00:00
}
2013-04-20 21:27:46 +00:00
}
2023-01-10 17:20:31 +00:00
/**
* @ return ? IJob The job matching the id . Beware that this object may be a singleton and may be modified by the next call to buildJob .
*/
2022-07-11 09:41:47 +00:00
public function getById ( int $id ) : ? IJob {
2021-05-31 15:15:26 +00:00
$row = $this -> getDetailsById ( $id );
if ( $row ) {
return $this -> buildJob ( $row );
}
return null ;
}
public function getDetailsById ( int $id ) : ? array {
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2016-02-29 08:44:40 +00:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $id , IQueryBuilder :: PARAM_INT )));
2021-05-31 15:15:26 +00:00
$result = $query -> executeQuery ();
2015-12-18 08:47:54 +00:00
$row = $result -> fetch ();
$result -> closeCursor ();
if ( $row ) {
2021-05-31 15:15:26 +00:00
return $row ;
2013-04-24 12:38:41 +00:00
}
2021-05-31 15:15:26 +00:00
return null ;
2013-04-24 12:38:41 +00:00
}
2013-04-20 21:27:46 +00:00
/**
* get the job object from a row in the db
*
2022-05-23 09:21:22 +00:00
* @ param array { class : class - string < IJob > , id : mixed , last_run : mixed , argument : string } $row
2023-01-10 17:20:31 +00:00
* @ return ? IJob the next job to run . Beware that this object may be a singleton and may be modified by the next call to buildJob .
2013-04-20 21:27:46 +00:00
*/
2022-05-23 09:21:22 +00:00
private function buildJob ( array $row ) : ? IJob {
2015-09-05 15:50:02 +00:00
try {
2015-12-18 10:44:32 +00:00
try {
// Try to load the job as a service
2015-12-18 13:16:32 +00:00
/** @var IJob $job */
2022-06-27 09:53:10 +00:00
$job = \OCP\Server :: get ( $row [ 'class' ]);
2015-12-18 10:44:32 +00:00
} catch ( QueryException $e ) {
if ( class_exists ( $row [ 'class' ])) {
$class = $row [ 'class' ];
$job = new $class ();
} else {
2024-10-16 13:29:25 +00:00
$this -> logger -> warning ( 'failed to create instance of background job: ' . $row [ 'class' ], [ 'app' => 'cron' , 'exception' => $e ]);
2023-04-26 13:11:47 +00:00
// Remove job from disabled app or old version of an app
$this -> removeById ( $row [ 'id' ]);
2015-12-18 10:44:32 +00:00
return null ;
}
2015-09-05 15:50:02 +00:00
}
2015-12-18 10:44:32 +00:00
2022-05-31 06:31:38 +00:00
if ( ! ( $job instanceof IJob )) {
// This most likely means an invalid job was enqueued. We can ignore it.
return null ;
}
2019-01-15 13:36:03 +00:00
$job -> setId (( int ) $row [ 'id' ]);
2020-01-30 11:00:41 +00:00
$job -> setLastRun (( int ) $row [ 'last_run' ]);
2015-09-05 15:50:02 +00:00
$job -> setArgument ( json_decode ( $row [ 'argument' ], true ));
return $job ;
} catch ( AutoloadNotAllowedException $e ) {
// job is from a disabled app, ignore
2015-12-18 10:44:32 +00:00
return null ;
2014-06-26 20:39:40 +00:00
}
2013-04-20 21:27:46 +00:00
}
/**
* set the job that was last ran
*/
2022-05-23 09:21:22 +00:00
public function setLastJob ( IJob $job ) : void {
2016-05-18 12:27:48 +00:00
$this -> unlockJob ( $job );
2022-05-23 09:21:22 +00:00
$this -> config -> setAppValue ( 'backgroundjob' , 'lastjob' , ( string ) $job -> getId ());
2013-04-20 21:27:46 +00:00
}
2016-05-18 12:27:48 +00:00
/**
* Remove the reservation for a job
*/
2022-05-23 09:21:22 +00:00
public function unlockJob ( IJob $job ) : void {
2016-05-18 12:27:48 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
-> set ( 'reserved_at' , $query -> expr () -> literal ( 0 , IQueryBuilder :: PARAM_INT ))
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId (), IQueryBuilder :: PARAM_INT )));
2022-05-23 09:21:22 +00:00
$query -> executeStatement ();
2016-05-18 12:27:48 +00:00
}
2013-04-20 21:27:46 +00:00
/**
* set the lastRun of $job to now
*/
2022-05-23 09:21:22 +00:00
public function setLastRun ( IJob $job ) : void {
2015-12-18 08:47:54 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
2016-02-29 08:44:40 +00:00
-> set ( 'last_run' , $query -> createNamedParameter ( time (), IQueryBuilder :: PARAM_INT ))
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId (), IQueryBuilder :: PARAM_INT )));
2022-01-31 16:56:43 +00:00
if ( $job instanceof \OCP\BackgroundJob\TimedJob
&& ! $job -> isTimeSensitive ()) {
$query -> set ( 'time_sensitive' , $query -> createNamedParameter ( IJob :: TIME_INSENSITIVE ));
}
2022-05-23 09:21:22 +00:00
$query -> executeStatement ();
2013-04-20 21:27:46 +00:00
}
2017-04-25 15:39:58 +00:00
/**
2022-05-23 09:21:22 +00:00
* @ param int $timeTaken
2017-04-25 15:39:58 +00:00
*/
2022-05-23 09:21:22 +00:00
public function setExecutionTime ( IJob $job , $timeTaken ) : void {
2017-04-25 15:39:58 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
-> set ( 'execution_duration' , $query -> createNamedParameter ( $timeTaken , IQueryBuilder :: PARAM_INT ))
2023-12-20 09:07:41 +00:00
-> set ( 'reserved_at' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
2017-04-25 15:39:58 +00:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId (), IQueryBuilder :: PARAM_INT )));
2022-05-23 09:21:22 +00:00
$query -> executeStatement ();
2017-04-25 15:39:58 +00:00
}
2021-05-31 15:15:26 +00:00
/**
* Reset the $job so it executes on the next trigger
*
2021-10-13 09:46:48 +00:00
* @ since 23.0 . 0
2021-05-31 15:15:26 +00:00
*/
public function resetBackgroundJob ( IJob $job ) : void {
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
2022-01-12 19:44:38 +00:00
-> set ( 'last_run' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
-> set ( 'reserved_at' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
2021-05-31 15:15:26 +00:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId ()), IQueryBuilder :: PARAM_INT ));
$query -> executeStatement ();
}
2023-04-20 10:55:06 +00:00
2023-04-20 11:18:28 +00:00
public function hasReservedJob ( ? string $className = null ) : bool {
2023-04-20 10:55:06 +00:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2023-11-06 09:47:40 +00:00
-> where ( $query -> expr () -> gt ( 'reserved_at' , $query -> createNamedParameter ( $this -> timeFactory -> getTime () - 6 * 3600 , IQueryBuilder :: PARAM_INT )))
2023-04-20 11:34:16 +00:00
-> setMaxResults ( 1 );
2023-04-20 10:55:06 +00:00
if ( $className !== null ) {
$query -> andWhere ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $className )));
}
try {
2023-04-20 13:29:47 +00:00
$result = $query -> executeQuery ();
2023-04-21 08:34:24 +00:00
$hasReservedJobs = $result -> fetch () !== false ;
$result -> closeCursor ();
return $hasReservedJobs ;
2023-04-20 10:55:06 +00:00
} catch ( Exception $e ) {
2023-04-24 15:16:15 +00:00
$this -> logger -> debug ( 'Querying reserved jobs failed' , [ 'exception' => $e ]);
2023-04-20 10:55:06 +00:00
return false ;
}
}
2022-07-14 12:50:12 +00:00
public function countByClass () : array {
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( 'class' )
-> selectAlias ( $query -> func () -> count ( 'id' ), 'count' )
-> from ( 'jobs' )
-> orderBy ( 'count' )
-> groupBy ( 'class' );
$result = $query -> executeQuery ();
$jobs = [];
2023-12-20 13:29:44 +00:00
2023-12-20 13:12:27 +00:00
while (( $row = $result -> fetch ()) !== false ) {
2023-12-20 13:29:44 +00:00
/**
* @ var array { count : int , class : class - string } $row
*/
2022-07-14 12:50:12 +00:00
$jobs [] = $row ;
}
return $jobs ;
}
2013-04-20 21:27:46 +00:00
}