2013-04-20 17:27:46 -04:00
< ? php
/**
2016-07-21 11:07:57 -04:00
* @ copyright Copyright ( c ) 2016 , ownCloud , Inc .
*
2019-12-03 13:57:53 -05:00
* @ author Christoph Wurst < christoph @ winzerhof - wurst . at >
2020-03-31 04:49:10 -04:00
* @ author Georg Ehrke < oc . list @ georgehrke . com >
2016-07-21 11:07:57 -04:00
* @ author Joas Schilling < coding @ schilljs . com >
2017-11-06 09:56:42 -05:00
* @ author Jörn Friedrich Dreyer < jfd @ butonic . de >
2015-03-26 06:44:34 -04:00
* @ author Morris Jobke < hey @ morrisjobke . de >
2017-11-06 09:56:42 -05:00
* @ author Noveen Sachdeva < noveen . sachdeva @ research . iiit . ac . in >
2016-07-21 12:13:36 -04:00
* @ author Robin Appelman < robin @ icewind . nl >
2016-01-12 09:02:16 -05:00
* @ author Robin McCorkell < robin @ mccorkell . me . uk >
2019-12-03 13:57:53 -05:00
* @ author Roeland Jago Douma < roeland @ famdouma . nl >
2015-03-26 06:44:34 -04:00
*
* @ license AGPL - 3.0
*
* This code is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License , version 3 ,
2019-12-03 13:57:53 -05:00
* along with this program . If not , see < http :// www . gnu . org / licenses />
2015-03-26 06:44:34 -04:00
*
2013-04-20 17:27:46 -04:00
*/
namespace OC\BackgroundJob ;
2022-01-20 04:47:00 -05:00
use Doctrine\DBAL\Platforms\MySQLPlatform ;
2015-12-18 05:44:32 -05:00
use OCP\AppFramework\QueryException ;
2016-05-18 08:27:48 -04:00
use OCP\AppFramework\Utility\ITimeFactory ;
2019-11-22 14:52:10 -05:00
use OCP\AutoloadNotAllowedException ;
2015-12-18 04:04:30 -05:00
use OCP\BackgroundJob\IJob ;
2014-02-12 07:32:16 -05:00
use OCP\BackgroundJob\IJobList ;
2023-07-20 07:38:07 -04:00
use OCP\BackgroundJob\IParallelAwareJob ;
2023-04-20 06:55:06 -04:00
use OCP\DB\Exception ;
2016-02-29 03:44:40 -05:00
use OCP\DB\QueryBuilder\IQueryBuilder ;
2016-05-18 08:27:48 -04:00
use OCP\IConfig ;
use OCP\IDBConnection ;
2023-04-24 11:16:15 -04:00
use Psr\Log\LoggerInterface ;
2023-09-27 08:53:04 -04:00
use function get_class ;
use function json_encode ;
use function md5 ;
use function strlen ;
2014-02-12 07:32:16 -05:00
class JobList implements IJobList {
2022-05-23 05:21:22 -04:00
protected IDBConnection $connection ;
protected IConfig $config ;
protected ITimeFactory $timeFactory ;
2023-04-24 11:16:15 -04:00
protected LoggerInterface $logger ;
2014-02-11 08:00:24 -05:00
2023-04-24 11:16:15 -04:00
public function __construct ( IDBConnection $connection , IConfig $config , ITimeFactory $timeFactory , LoggerInterface $logger ) {
2015-12-18 03:47:54 -05:00
$this -> connection = $connection ;
2014-02-11 08:00:24 -05:00
$this -> config = $config ;
2016-05-18 08:27:48 -04:00
$this -> timeFactory = $timeFactory ;
2023-04-24 11:16:15 -04:00
$this -> logger = $logger ;
2014-02-11 08:00:24 -05:00
}
2023-09-27 08:53:04 -04:00
public function add ( $job , $argument = null , int $firstCheck = null ) : void {
if ( $firstCheck === null ) {
$firstCheck = $this -> timeFactory -> getTime ();
}
2021-12-21 02:05:50 -05:00
if ( $job instanceof IJob ) {
$class = get_class ( $job );
} else {
$class = $job ;
}
2015-12-18 03:47:54 -05:00
2021-12-21 02:05:50 -05: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 03:47:54 -05:00
2021-12-21 02:05:50 -05:00
$query = $this -> connection -> getQueryBuilder ();
if ( ! $this -> has ( $job , $argument )) {
2015-12-18 03:47:54 -05:00
$query -> insert ( 'jobs' )
-> values ([
'class' => $query -> createNamedParameter ( $class ),
2021-12-21 02:05:50 -05:00
'argument' => $query -> createNamedParameter ( $argumentJson ),
2022-01-03 05:17:28 -05:00
'argument_hash' => $query -> createNamedParameter ( md5 ( $argumentJson )),
2016-02-29 03:44:40 -05:00
'last_run' => $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ),
2023-09-27 08:53:04 -04:00
'last_checked' => $query -> createNamedParameter ( $firstCheck , IQueryBuilder :: PARAM_INT ),
2015-12-18 03:47:54 -05:00
]);
2021-12-21 02:05:50 -05:00
} else {
$query -> update ( 'jobs' )
-> set ( 'reserved_at' , $query -> expr () -> literal ( 0 , IQueryBuilder :: PARAM_INT ))
2023-09-27 08:53:04 -04:00
-> set ( 'last_checked' , $query -> createNamedParameter ( $firstCheck , IQueryBuilder :: PARAM_INT ))
2023-12-15 05:49:51 -05:00
-> set ( 'last_run' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
2021-12-21 02:05:50 -05:00
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )))
2022-01-03 05:17:28 -05:00
-> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( md5 ( $argumentJson ))));
2013-04-20 17:27:46 -04:00
}
2021-12-21 02:05:50 -05:00
$query -> executeStatement ();
2013-04-20 17:27:46 -04:00
}
2023-09-27 08:53:04 -04:00
public function scheduleAfter ( string $job , int $runAfter , $argument = null ) : void {
$this -> add ( $job , $argument , $runAfter );
}
2013-04-20 17:27:46 -04:00
/**
2015-12-18 04:04:30 -05:00
* @ param IJob | string $job
2013-04-20 17:27:46 -04:00
* @ param mixed $argument
*/
2022-05-23 05:21:22 -04:00
public function remove ( $job , $argument = null ) : void {
2015-12-18 04:04:30 -05:00
if ( $job instanceof IJob ) {
2013-04-20 17:27:46 -04:00
$class = get_class ( $job );
} else {
$class = $job ;
}
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> delete ( 'jobs' )
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )));
2013-04-20 17:27:46 -04:00
if ( ! is_null ( $argument )) {
2022-03-02 03:23:16 -05:00
$argumentJson = json_encode ( $argument );
$query -> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( md5 ( $argumentJson ))));
2013-04-20 17:27:46 -04:00
}
2022-01-20 04:47:00 -05:00
// Add galera safe delete chunking if using mysql
// Stops us hitting wsrep_max_ws_rows when large row counts are deleted
if ( $this -> connection -> getDatabasePlatform () instanceof MySQLPlatform ) {
// Then use chunked delete
$max = IQueryBuilder :: MAX_ROW_DELETION ;
$query -> setMaxResults ( $max );
do {
$deleted = $query -> execute ();
} while ( $deleted === $max );
} else {
// Dont use chunked delete - let the DB handle the large row count natively
$query -> execute ();
}
2013-04-20 17:27:46 -04:00
}
2022-05-23 05:21:22 -04:00
protected function removeById ( int $id ) : void {
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> delete ( 'jobs' )
2016-02-29 03:44:40 -05:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $id , IQueryBuilder :: PARAM_INT )));
2022-05-23 05:21:22 -04:00
$query -> executeStatement ();
2015-08-19 08:16:05 -04:00
}
2013-04-20 17:27:46 -04:00
/**
* check if a job is in the list
*
2022-07-11 05:41:47 -04:00
* @ param IJob | class - string < IJob > $job
2013-04-20 17:27:46 -04:00
* @ param mixed $argument
*/
2022-05-23 05:21:22 -04:00
public function has ( $job , $argument ) : bool {
2015-12-18 04:04:30 -05:00
if ( $job instanceof IJob ) {
2013-04-20 17:27:46 -04:00
$class = get_class ( $job );
} else {
$class = $job ;
}
$argument = json_encode ( $argument );
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( 'id' )
-> from ( 'jobs' )
-> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )))
2022-01-03 05:17:28 -05:00
-> andWhere ( $query -> expr () -> eq ( 'argument_hash' , $query -> createNamedParameter ( md5 ( $argument ))))
2015-12-18 03:47:54 -05:00
-> setMaxResults ( 1 );
2022-05-23 05:21:22 -04:00
$result = $query -> executeQuery ();
2015-12-18 03:47:54 -05:00
$row = $result -> fetch ();
$result -> closeCursor ();
return ( bool ) $row ;
2013-04-20 17:27:46 -04:00
}
2023-01-12 11:18:59 -05:00
public function getJobs ( $job , ? int $limit , int $offset ) : array {
$iterable = $this -> getJobsIterator ( $job , $limit , $offset );
if ( is_array ( $iterable )) {
return $iterable ;
} else {
return iterator_to_array ( $iterable );
}
}
2022-06-27 05:53:10 -04:00
/**
* @ param IJob | class - string < IJob >| null $job
2023-01-10 12:20:31 -05: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 05:53:10 -04:00
*/
2023-01-12 11:18:59 -05:00
public function getJobsIterator ( $job , ? int $limit , int $offset ) : iterable {
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
2022-05-23 06:30:26 -04:00
-> from ( 'jobs' )
-> setMaxResults ( $limit )
-> setFirstResult ( $offset );
if ( $job !== null ) {
if ( $job instanceof IJob ) {
$class = get_class ( $job );
} else {
$class = $job ;
}
$query -> where ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $class )));
}
2022-05-23 05:21:22 -04:00
$result = $query -> executeQuery ();
2015-12-18 03:47:54 -05:00
while ( $row = $result -> fetch ()) {
2014-07-25 12:02:02 -04:00
$job = $this -> buildJob ( $row );
if ( $job ) {
2023-01-10 12:20:31 -05:00
yield $job ;
2014-07-25 12:02:02 -04:00
}
2013-04-20 17:27:46 -04:00
}
2015-12-18 03:47:54 -05:00
$result -> closeCursor ();
2013-04-20 17:27:46 -04:00
}
/**
2023-01-10 12:20:31 -05:00
* Get the next job in the list
* @ 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 17:27:46 -04:00
*/
2022-04-23 09:42:37 -04:00
public function getNext ( bool $onlyTimeSensitive = false ) : ? IJob {
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2018-11-01 07:52:09 -04:00
-> where ( $query -> expr () -> lte ( 'reserved_at' , $query -> createNamedParameter ( $this -> timeFactory -> getTime () - 12 * 3600 , IQueryBuilder :: PARAM_INT )))
2018-06-26 10:24:08 -04:00
-> andWhere ( $query -> expr () -> lte ( 'last_checked' , $query -> createNamedParameter ( $this -> timeFactory -> getTime (), IQueryBuilder :: PARAM_INT )))
2016-05-18 08:27:48 -04:00
-> orderBy ( 'last_checked' , 'ASC' )
2015-12-18 03:47:54 -05:00
-> setMaxResults ( 1 );
2016-05-18 08:27:48 -04:00
2022-01-31 11:56:43 -05:00
if ( $onlyTimeSensitive ) {
$query -> andWhere ( $query -> expr () -> eq ( 'time_sensitive' , $query -> createNamedParameter ( IJob :: TIME_SENSITIVE , IQueryBuilder :: PARAM_INT )));
}
2022-05-23 05:21:22 -04:00
$result = $query -> executeQuery ();
2015-12-18 03:47:54 -05:00
$row = $result -> fetch ();
$result -> closeCursor ();
if ( $row ) {
2023-07-20 07:38:07 -04:00
$job = $this -> buildJob ( $row );
if ( $job instanceof IParallelAwareJob && ! $job -> getAllowParallelRuns () && $this -> hasReservedJob ( get_class ( $job ))) {
$this -> logger -> debug ( 'Skipping ' . get_class ( $job ) . ' job with ID ' . $job -> getId () . ' because another job with the same class is already running' , [ 'app' => 'cron' ]);
$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 08:27:48 -04:00
$update -> setParameter ( 'jobid' , $row [ 'id' ]);
2017-04-07 06:53:44 -04:00
$update -> setParameter ( 'reserved_at' , $row [ 'reserved_at' ]);
$update -> setParameter ( 'last_checked' , $row [ 'last_checked' ]);
2022-05-23 05:21:22 -04:00
$count = $update -> executeStatement ();
2016-05-18 08:27:48 -04:00
2017-04-07 06:53:44 -04:00
if ( $count === 0 ) {
// Background job already executed elsewhere, try again.
2022-01-31 11:56:43 -05:00
return $this -> getNext ( $onlyTimeSensitive );
2017-04-07 06:53:44 -04:00
}
2016-05-18 08:27:48 -04:00
if ( $job === null ) {
2018-06-26 10:24:08 -04: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 05:21:22 -04:00
$reset -> executeStatement ();
2018-06-26 10:24:08 -04:00
2016-05-18 08:27:48 -04:00
// Background job from disabled app, try again.
2022-01-31 11:56:43 -05:00
return $this -> getNext ( $onlyTimeSensitive );
2013-04-20 17:27:46 -04:00
}
2015-12-18 03:47:54 -05:00
2015-08-19 08:16:05 -04:00
return $job ;
2016-05-18 08:27:48 -04:00
} else {
return null ;
2015-08-19 08:16:05 -04:00
}
2013-04-20 17:27:46 -04:00
}
2023-01-10 12:20:31 -05: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 05:41:47 -04:00
public function getById ( int $id ) : ? IJob {
2021-05-31 11:15:26 -04:00
$row = $this -> getDetailsById ( $id );
if ( $row ) {
return $this -> buildJob ( $row );
}
return null ;
}
public function getDetailsById ( int $id ) : ? array {
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2016-02-29 03:44:40 -05:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $id , IQueryBuilder :: PARAM_INT )));
2021-05-31 11:15:26 -04:00
$result = $query -> executeQuery ();
2015-12-18 03:47:54 -05:00
$row = $result -> fetch ();
$result -> closeCursor ();
if ( $row ) {
2021-05-31 11:15:26 -04:00
return $row ;
2013-04-24 08:38:41 -04:00
}
2021-05-31 11:15:26 -04:00
return null ;
2013-04-24 08:38:41 -04:00
}
2013-04-20 17:27:46 -04:00
/**
* get the job object from a row in the db
*
2022-05-23 05:21:22 -04:00
* @ param array { class : class - string < IJob > , id : mixed , last_run : mixed , argument : string } $row
2023-01-10 12:20:31 -05: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 17:27:46 -04:00
*/
2022-05-23 05:21:22 -04:00
private function buildJob ( array $row ) : ? IJob {
2015-09-05 11:50:02 -04:00
try {
2015-12-18 05:44:32 -05:00
try {
// Try to load the job as a service
2015-12-18 08:16:32 -05:00
/** @var IJob $job */
2022-06-27 05:53:10 -04:00
$job = \OCP\Server :: get ( $row [ 'class' ]);
2015-12-18 05:44:32 -05:00
} catch ( QueryException $e ) {
if ( class_exists ( $row [ 'class' ])) {
$class = $row [ 'class' ];
$job = new $class ();
} else {
2023-04-26 09:11:47 -04:00
// Remove job from disabled app or old version of an app
$this -> removeById ( $row [ 'id' ]);
2015-12-18 05:44:32 -05:00
return null ;
}
2015-09-05 11:50:02 -04:00
}
2015-12-18 05:44:32 -05:00
2022-05-31 02:31:38 -04:00
if ( ! ( $job instanceof IJob )) {
// This most likely means an invalid job was enqueued. We can ignore it.
return null ;
}
2019-01-15 08:36:03 -05:00
$job -> setId (( int ) $row [ 'id' ]);
2020-01-30 06:00:41 -05:00
$job -> setLastRun (( int ) $row [ 'last_run' ]);
2015-09-05 11:50:02 -04:00
$job -> setArgument ( json_decode ( $row [ 'argument' ], true ));
return $job ;
} catch ( AutoloadNotAllowedException $e ) {
// job is from a disabled app, ignore
2015-12-18 05:44:32 -05:00
return null ;
2014-06-26 16:39:40 -04:00
}
2013-04-20 17:27:46 -04:00
}
/**
* set the job that was last ran
*/
2022-05-23 05:21:22 -04:00
public function setLastJob ( IJob $job ) : void {
2016-05-18 08:27:48 -04:00
$this -> unlockJob ( $job );
2022-05-23 05:21:22 -04:00
$this -> config -> setAppValue ( 'backgroundjob' , 'lastjob' , ( string ) $job -> getId ());
2013-04-20 17:27:46 -04:00
}
2016-05-18 08:27:48 -04:00
/**
* Remove the reservation for a job
*/
2022-05-23 05:21:22 -04:00
public function unlockJob ( IJob $job ) : void {
2016-05-18 08:27:48 -04: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 05:21:22 -04:00
$query -> executeStatement ();
2016-05-18 08:27:48 -04:00
}
2013-04-20 17:27:46 -04:00
/**
* set the lastRun of $job to now
*/
2022-05-23 05:21:22 -04:00
public function setLastRun ( IJob $job ) : void {
2015-12-18 03:47:54 -05:00
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
2016-02-29 03:44:40 -05: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 11:56:43 -05:00
if ( $job instanceof \OCP\BackgroundJob\TimedJob
&& ! $job -> isTimeSensitive ()) {
$query -> set ( 'time_sensitive' , $query -> createNamedParameter ( IJob :: TIME_INSENSITIVE ));
}
2022-05-23 05:21:22 -04:00
$query -> executeStatement ();
2013-04-20 17:27:46 -04:00
}
2017-04-25 11:39:58 -04:00
/**
2022-05-23 05:21:22 -04:00
* @ param int $timeTaken
2017-04-25 11:39:58 -04:00
*/
2022-05-23 05:21:22 -04:00
public function setExecutionTime ( IJob $job , $timeTaken ) : void {
2017-04-25 11:39:58 -04:00
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
-> set ( 'execution_duration' , $query -> createNamedParameter ( $timeTaken , IQueryBuilder :: PARAM_INT ))
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId (), IQueryBuilder :: PARAM_INT )));
2022-05-23 05:21:22 -04:00
$query -> executeStatement ();
2017-04-25 11:39:58 -04:00
}
2021-05-31 11:15:26 -04:00
/**
* Reset the $job so it executes on the next trigger
*
2021-10-13 05:46:48 -04:00
* @ since 23.0 . 0
2021-05-31 11:15:26 -04:00
*/
public function resetBackgroundJob ( IJob $job ) : void {
$query = $this -> connection -> getQueryBuilder ();
$query -> update ( 'jobs' )
2022-01-12 14:44:38 -05:00
-> set ( 'last_run' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
-> set ( 'reserved_at' , $query -> createNamedParameter ( 0 , IQueryBuilder :: PARAM_INT ))
2021-05-31 11:15:26 -04:00
-> where ( $query -> expr () -> eq ( 'id' , $query -> createNamedParameter ( $job -> getId ()), IQueryBuilder :: PARAM_INT ));
$query -> executeStatement ();
}
2023-04-20 06:55:06 -04:00
2023-04-20 07:18:28 -04:00
public function hasReservedJob ( ? string $className = null ) : bool {
2023-04-20 06:55:06 -04:00
$query = $this -> connection -> getQueryBuilder ();
$query -> select ( '*' )
-> from ( 'jobs' )
2023-11-06 04:47:40 -05:00
-> where ( $query -> expr () -> gt ( 'reserved_at' , $query -> createNamedParameter ( $this -> timeFactory -> getTime () - 6 * 3600 , IQueryBuilder :: PARAM_INT )))
2023-04-20 07:34:16 -04:00
-> setMaxResults ( 1 );
2023-04-20 06:55:06 -04:00
if ( $className !== null ) {
$query -> andWhere ( $query -> expr () -> eq ( 'class' , $query -> createNamedParameter ( $className )));
}
try {
2023-04-20 09:29:47 -04:00
$result = $query -> executeQuery ();
2023-04-21 04:34:24 -04:00
$hasReservedJobs = $result -> fetch () !== false ;
$result -> closeCursor ();
return $hasReservedJobs ;
2023-04-20 06:55:06 -04:00
} catch ( Exception $e ) {
2023-04-24 11:16:15 -04:00
$this -> logger -> debug ( 'Querying reserved jobs failed' , [ 'exception' => $e ]);
2023-04-20 06:55:06 -04:00
return false ;
}
}
2013-04-20 17:27:46 -04:00
}