feat: Port jobs table to snowflakes ids

Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
pull/56628/head
Carl Schwan 2025-11-24 18:11:53 +07:00
parent 31af870ef0
commit 0e686fc6a9
No known key found for this signature in database
GPG Key ID: 02325448204E452A
13 changed files with 147 additions and 178 deletions

@ -45,7 +45,7 @@ class RefreshWebcalJobTest extends TestCase {
#[\PHPUnit\Framework\Attributes\DataProvider('runDataProvider')]
public function testRun(int $lastRun, int $time, bool $process): void {
$backgroundJob = new RefreshWebcalJob($this->refreshWebcalService, $this->config, $this->logger, $this->timeFactory);
$backgroundJob->setId(42);
$backgroundJob->setId('42');
$backgroundJob->setArgument([
'principaluri' => 'principals/users/testuser',

@ -35,7 +35,7 @@ class Delete extends Base {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$jobId = (int)$input->getArgument('job-id');
$jobId = (string)$input->getArgument('job-id');
$job = $this->jobList->getById($jobId);
if ($job === null) {

@ -44,7 +44,7 @@ class Job extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$jobId = (int)$input->getArgument('job-id');
$jobId = (string)$input->getArgument('job-id');
$job = $this->jobList->getById($jobId);
if ($job === null) {
@ -87,7 +87,7 @@ class Job extends Command {
return 0;
}
protected function printJobInfo(int $jobId, IJob $job, OutputInterface $output): void {
protected function printJobInfo(string $jobId, IJob $job, OutputInterface $output): void {
$row = $this->jobList->getDetailsById($jobId);
$lastRun = new \DateTime();

@ -27,7 +27,7 @@ abstract class JobBase extends Base {
parent::__construct();
}
protected function printJobInfo(int $jobId, IJob $job, OutputInterface $output): void {
protected function printJobInfo(string $jobId, IJob $job, OutputInterface $output): void {
$row = $this->jobList->getDetailsById($jobId);
if ($row === null) {

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Migrations;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\Attributes\ModifyColumn;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
use Override;
#[ModifyColumn(table: 'jobs', name: 'id', description: 'Remove auto-increment')]
class Version33000Date20251124110529 extends SimpleMigrationStep {
/**
* @param Closure(): ISchemaWrapper $schemaClosure The `\Closure` returns a `ISchemaWrapper`
*/
#[Override]
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
$schema = $schemaClosure();
if ($schema->hasTable('jobs')) {
$schema->dropAutoincrementColumn('jobs', 'id');
}
return $schema;
}
}

@ -1537,6 +1537,7 @@ return array(
'OC\\Core\\Migrations\\Version33000Date20251023110529' => $baseDir . '/core/Migrations/Version33000Date20251023110529.php',
'OC\\Core\\Migrations\\Version33000Date20251023120529' => $baseDir . '/core/Migrations/Version33000Date20251023120529.php',
'OC\\Core\\Migrations\\Version33000Date20251106131209' => $baseDir . '/core/Migrations/Version33000Date20251106131209.php',
'OC\\Core\\Migrations\\Version33000Date20251124110529' => $baseDir . '/core/Migrations/Version33000Date20251124110529.php',
'OC\\Core\\Migrations\\Version33000Date20251126152410' => $baseDir . '/core/Migrations/Version33000Date20251126152410.php',
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
'OC\\Core\\ResponseDefinitions' => $baseDir . '/core/ResponseDefinitions.php',

@ -1578,6 +1578,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Migrations\\Version33000Date20251023110529' => __DIR__ . '/../../..' . '/core/Migrations/Version33000Date20251023110529.php',
'OC\\Core\\Migrations\\Version33000Date20251023120529' => __DIR__ . '/../../..' . '/core/Migrations/Version33000Date20251023120529.php',
'OC\\Core\\Migrations\\Version33000Date20251106131209' => __DIR__ . '/../../..' . '/core/Migrations/Version33000Date20251106131209.php',
'OC\\Core\\Migrations\\Version33000Date20251124110529' => __DIR__ . '/../../..' . '/core/Migrations/Version33000Date20251124110529.php',
'OC\\Core\\Migrations\\Version33000Date20251126152410' => __DIR__ . '/../../..' . '/core/Migrations/Version33000Date20251126152410.php',
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
'OC\\Core\\ResponseDefinitions' => __DIR__ . '/../../..' . '/core/ResponseDefinitions.php',

@ -7,7 +7,6 @@
*/
namespace OC\BackgroundJob;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\AutoloadNotAllowedException;
use OCP\BackgroundJob\IJob;
@ -17,6 +16,9 @@ use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Snowflake\IGenerator;
use Override;
use Psr\Container\ContainerExceptionInterface;
use Psr\Log\LoggerInterface;
use function get_class;
use function json_encode;
@ -24,18 +26,20 @@ use function min;
use function strlen;
class JobList implements IJobList {
/** @var array<string, int> */
/** @var array<string, string> */
protected array $alreadyVisitedParallelBlocked = [];
public function __construct(
protected IDBConnection $connection,
protected IConfig $config,
protected ITimeFactory $timeFactory,
protected LoggerInterface $logger,
protected readonly IDBConnection $connection,
protected readonly IConfig $config,
protected readonly ITimeFactory $timeFactory,
protected readonly LoggerInterface $logger,
protected readonly IGenerator $generator,
) {
}
public function add($job, $argument = null, ?int $firstCheck = null): void {
#[Override]
public function add(IJob|string $job, mixed $argument = null, ?int $firstCheck = null): void {
if ($firstCheck === null) {
$firstCheck = $this->timeFactory->getTime();
}
@ -51,6 +55,7 @@ class JobList implements IJobList {
if (!$this->has($job, $argument)) {
$query->insert('jobs')
->values([
'id' => $query->createNamedParameter($this->generator->nextId(), IQueryBuilder::PARAM_INT),
'class' => $query->createNamedParameter($class),
'argument' => $query->createNamedParameter($argumentJson),
'argument_hash' => $query->createNamedParameter(hash('sha256', $argumentJson)),
@ -68,15 +73,12 @@ class JobList implements IJobList {
$query->executeStatement();
}
public function scheduleAfter(string $job, int $runAfter, $argument = null): void {
public function scheduleAfter(string $job, int $runAfter, mixed $argument = null): void {
$this->add($job, $argument, $runAfter);
}
/**
* @param IJob|string $job
* @param mixed $argument
*/
public function remove($job, $argument = null): void {
#[Override]
public function remove(IJob|string $job, mixed $argument = null): void {
$class = ($job instanceof IJob) ? get_class($job) : $job;
$query = $this->connection->getQueryBuilder();
@ -104,20 +106,16 @@ class JobList implements IJobList {
}
}
public function removeById(int $id): void {
#[Override]
public function removeById(string $id): void {
$query = $this->connection->getQueryBuilder();
$query->delete('jobs')
->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
$query->executeStatement();
}
/**
* check if a job is in the list
*
* @param IJob|class-string<IJob> $job
* @param mixed $argument
*/
public function has($job, $argument): bool {
#[Override]
public function has(IJob|string $job, mixed $argument): bool {
$class = ($job instanceof IJob) ? get_class($job) : $job;
$argument = json_encode($argument);
@ -135,18 +133,16 @@ class JobList implements IJobList {
return (bool)$row;
}
public function getJobs($job, ?int $limit, int $offset): array {
#[Override]
public function getJobs(IJob|string|null $job, ?int $limit, int $offset): array {
$iterable = $this->getJobsIterator($job, $limit, $offset);
return (is_array($iterable))
? $iterable
: iterator_to_array($iterable);
}
/**
* @param IJob|class-string<IJob>|null $job
* @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.
*/
public function getJobsIterator($job, ?int $limit, int $offset): iterable {
#[Override]
public function getJobsIterator(IJob|string|null $job, ?int $limit, int $offset): iterable {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
@ -169,9 +165,7 @@ class JobList implements IJobList {
$result->closeCursor();
}
/**
* @inheritDoc
*/
#[Override]
public function getNext(bool $onlyTimeSensitive = false, ?array $jobClasses = null): ?IJob {
$query = $this->connection->getQueryBuilder();
$query->select('*')
@ -279,10 +273,8 @@ class JobList implements IJobList {
}
}
/**
* @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.
*/
public function getById(int $id): ?IJob {
#[Override]
public function getById(string $id): ?IJob {
$row = $this->getDetailsById($id);
if ($row) {
@ -292,7 +284,8 @@ class JobList implements IJobList {
return null;
}
public function getDetailsById(int $id): ?array {
#[Override]
public function getDetailsById(string $id): ?array {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
@ -320,7 +313,7 @@ class JobList implements IJobList {
// Try to load the job as a service
/** @var IJob $job */
$job = \OCP\Server::get($row['class']);
} catch (QueryException $e) {
} catch (ContainerExceptionInterface $e) {
if (class_exists($row['class'])) {
$class = $row['class'];
$job = new $class();
@ -336,7 +329,7 @@ class JobList implements IJobList {
// This most likely means an invalid job was enqueued. We can ignore it.
return null;
}
$job->setId((int)$row['id']);
$job->setId($row['id']);
$job->setLastRun((int)$row['last_run']);
$job->setArgument(json_decode($row['argument'], true));
return $job;
@ -351,12 +344,10 @@ class JobList implements IJobList {
*/
public function setLastJob(IJob $job): void {
$this->unlockJob($job);
$this->config->setAppValue('backgroundjob', 'lastjob', (string)$job->getId());
$this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
}
/**
* Remove the reservation for a job
*/
#[Override]
public function unlockJob(IJob $job): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
@ -365,9 +356,7 @@ class JobList implements IJobList {
$query->executeStatement();
}
/**
* set the lastRun of $job to now
*/
#[Override]
public function setLastRun(IJob $job): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
@ -382,9 +371,7 @@ class JobList implements IJobList {
$query->executeStatement();
}
/**
* @param int $timeTaken
*/
#[Override]
public function setExecutionTime(IJob $job, $timeTaken): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
@ -394,11 +381,7 @@ class JobList implements IJobList {
$query->executeStatement();
}
/**
* Reset the $job so it executes on the next trigger
*
* @since 23.0.0
*/
#[Override]
public function resetBackgroundJob(IJob $job): void {
$query = $this->connection->getQueryBuilder();
$query->update('jobs')
@ -408,6 +391,7 @@ class JobList implements IJobList {
$query->executeStatement();
}
#[Override]
public function hasReservedJob(?string $className = null): bool {
$query = $this->connection->getQueryBuilder();
$query->select('*')
@ -430,6 +414,7 @@ class JobList implements IJobList {
}
}
#[Override]
public function countByClass(): array {
$query = $this->connection->getQueryBuilder();
$query->select('class')
@ -444,7 +429,7 @@ class JobList implements IJobList {
while (($row = $result->fetch()) !== false) {
/**
* @var array{count:int, class:class-string} $row
* @var array{count:int, class:class-string<IJob>} $row
*/
$jobs[] = $row;
}

@ -43,43 +43,42 @@ interface IJob {
/**
* @since 7.0.0
* @since 33.0.0 Parameter $id changed from int to string
*/
public function setId(int $id);
public function setId(string $id): void;
/**
* @since 7.0.0
*/
public function setLastRun(int $lastRun);
public function setLastRun(int $lastRun): void;
/**
* @param mixed $argument
* @since 7.0.0
*/
public function setArgument($argument);
public function setArgument(mixed $argument): void;
/**
* Get the id of the background job
* This id is determined by the job list when a job is added to the list
*
* @return int
* @since 7.0.0
* @since 33.0.0 The return type changed from int to string
*/
public function getId();
public function getId(): string;
/**
* Get the last time this job was run as unix timestamp
*
* @return int
* @since 7.0.0
*/
public function getLastRun();
public function getLastRun(): int;
/**
* Get the argument associated with the background job
* This is the argument that will be passed to the background job
*
* @return mixed
* @since 7.0.0
*/
public function getArgument();
public function getArgument(): mixed;
}

@ -7,6 +7,8 @@
*/
namespace OCP\BackgroundJob;
use OCP\AppFramework\Attribute\Consumable;
/**
* Interface IJobList
*
@ -28,6 +30,7 @@ namespace OCP\BackgroundJob;
*
* @since 7.0.0
*/
#[Consumable(since: '7.0.0')]
interface IJobList {
/**
* Add a job to the list
@ -36,7 +39,7 @@ interface IJobList {
* @param mixed $argument The argument to be passed to $job->run() when the job is executed
* @since 7.0.0
*/
public function add($job, $argument = null): void;
public function add(IJob|string $job, mixed $argument = null): void;
/**
* Add a job to the list but only run it after the given timestamp
@ -49,7 +52,7 @@ interface IJobList {
* @param mixed $argument The serializable argument to be passed to $job->run() when the job is executed
* @since 28.0.0
*/
public function scheduleAfter(string $job, int $runAfter, $argument = null): void;
public function scheduleAfter(string $job, int $runAfter, mixed $argument = null): void;
/**
* Remove a job from the list
@ -58,15 +61,15 @@ interface IJobList {
* @param mixed $argument
* @since 7.0.0
*/
public function remove($job, $argument = null): void;
public function remove(IJob|string $job, mixed $argument = null): void;
/**
* Remove a job from the list by id
*
* @param int $id
* @since 30.0.0
* @since 33.0.0 Parameter $id changed from int to string
*/
public function removeById(int $id): void;
public function removeById(string $id): void;
/**
* check if a job is in the list
@ -75,7 +78,7 @@ interface IJobList {
* @param mixed $argument
* @since 7.0.0
*/
public function has($job, $argument): bool;
public function has(IJob|string $job, mixed $argument): bool;
/**
* Get jobs matching the search
@ -85,7 +88,7 @@ interface IJobList {
* @since 25.0.0
* @deprecated 26.0.0 Use getJobsIterator instead to avoid duplicated job objects
*/
public function getJobs($job, ?int $limit, int $offset): array;
public function getJobs(IJob|string|null $job, ?int $limit, int $offset): array;
/**
* Get jobs matching the search
@ -94,7 +97,7 @@ interface IJobList {
* @return iterable<IJob>
* @since 26.0.0
*/
public function getJobsIterator($job, ?int $limit, int $offset): iterable;
public function getJobsIterator(IJob|string|null $job, ?int $limit, int $offset): iterable;
/**
* Get the next job in the list
@ -108,13 +111,15 @@ interface IJobList {
/**
* @since 7.0.0
* @since 33.0.0 Parameter $id changed from int to string
*/
public function getById(int $id): ?IJob;
public function getById(string $id): ?IJob;
/**
* @since 23.0.0
* @since 33.0.0 Parameter $id changed from int to string
*/
public function getDetailsById(int $id): ?array;
public function getDetailsById(string $id): ?array;
/**
* set the job that was last ran to the current time
@ -155,7 +160,7 @@ interface IJobList {
* Checks whether a job of the passed class was reserved to run
* in the last 6h
*
* @param string|null $className
* @param class-string<IJob>|null $className
* @return bool
* @since 27.0.0
*/
@ -164,7 +169,7 @@ interface IJobList {
/**
* Returns a count of jobs per Job class
*
* @return list<array{class:class-string, count:int}>
* @return list<array{class:class-string<IJob>, count:int}>
* @since 30.0.0
*/
public function countByClass(): array;

@ -8,6 +8,7 @@ declare(strict_types=1);
namespace OCP\BackgroundJob;
use OCP\AppFramework\Utility\ITimeFactory;
use Override;
use Psr\Log\LoggerInterface;
/**
@ -21,7 +22,7 @@ use Psr\Log\LoggerInterface;
* @since 33.0.0 removed deprecated `execute()` method
*/
abstract class Job implements IJob, IParallelAwareJob {
protected int $id = 0;
protected string $id = '0';
protected int $lastRun = 0;
protected mixed $argument = null;
protected bool $allowParallelRuns = true;
@ -34,10 +35,7 @@ abstract class Job implements IJob, IParallelAwareJob {
) {
}
/**
* @inheritdoc
* @since 25.0.0
*/
#[Override]
public function start(IJobList $jobList): void {
$jobList->setLastRun($this);
$logger = \OCP\Server::get(LoggerInterface::class);
@ -61,74 +59,45 @@ abstract class Job implements IJob, IParallelAwareJob {
}
}
/**
* @since 15.0.0
*/
final public function setId(int $id) {
#[Override]
final public function setId(string $id): void {
$this->id = $id;
}
/**
* @since 15.0.0
*/
final public function setLastRun(int $lastRun) {
#[Override]
final public function setLastRun(int $lastRun): void {
$this->lastRun = $lastRun;
}
/**
* @since 15.0.0
*/
public function setArgument($argument) {
#[Override]
public function setArgument(mixed $argument): void {
$this->argument = $argument;
}
/**
* @since 15.0.0
*/
final public function getId(): int {
#[Override]
final public function getId(): string {
return $this->id;
}
/**
* @since 15.0.0
*/
#[Override]
final public function getLastRun(): int {
return $this->lastRun;
}
/**
* @since 15.0.0
*/
public function getArgument() {
#[Override]
public function getArgument(): mixed {
return $this->argument;
}
/**
* Set this to false to prevent two Jobs from this class from running in parallel
*
* @param bool $allow
* @return void
* @since 27.0.0
*/
#[Override]
public function setAllowParallelRuns(bool $allow): void {
$this->allowParallelRuns = $allow;
}
/**
* @return bool
* @since 27.0.0
*/
#[Override]
public function getAllowParallelRuns(): bool {
return $this->allowParallelRuns;
}
/**
* The actual function that is called to run the job
*
* @param $argument
* @return void
*
* @since 15.0.0
*/
abstract protected function run($argument);
}

@ -13,6 +13,7 @@ use OC\BackgroundJob\JobList;
use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\Job;
use OCP\Server;
use OCP\Snowflake\IGenerator;
/**
* Class DummyJobList
@ -31,7 +32,6 @@ class DummyJobList extends JobList {
private array $reserved = [];
private int $last = 0;
private int $lastId = 0;
public function __construct() {
}
@ -46,8 +46,7 @@ class DummyJobList extends JobList {
$job = Server::get($job);
}
$job->setArgument($argument);
$job->setId($this->lastId);
$this->lastId++;
$job->setId(Server::get(IGenerator::class)->nextId());
if (!$this->has($job, null)) {
$this->jobs[] = $job;
}
@ -70,7 +69,7 @@ class DummyJobList extends JobList {
}
}
public function removeById(int $id): void {
public function removeById(string $id): void {
foreach ($this->jobs as $index => $listJob) {
if ($listJob->getId() === $id) {
unset($this->jobs[$index]);
@ -148,7 +147,7 @@ class DummyJobList extends JobList {
}
}
public function getById(int $id): ?IJob {
public function getById(string $id): ?IJob {
foreach ($this->jobs as $job) {
if ($job->getId() === $id) {
return $job;
@ -157,7 +156,7 @@ class DummyJobList extends JobList {
return null;
}
public function getDetailsById(int $id): ?array {
public function getDetailsById(string $id): ?array {
return null;
}

@ -12,11 +12,13 @@ namespace Test\BackgroundJob;
use OC\BackgroundJob\JobList;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJob;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Server;
use OCP\Snowflake\IGenerator;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
@ -27,18 +29,10 @@ use Test\TestCase;
*/
#[\PHPUnit\Framework\Attributes\Group('DB')]
class JobListTest extends TestCase {
/** @var \OC\BackgroundJob\JobList */
protected $instance;
/** @var IDBConnection */
protected $connection;
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
protected $config;
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
protected $timeFactory;
private bool $ran = false;
protected JobList $instance;
protected IDBConnection $connection;
protected IConfig&MockObject $config;
protected ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
@ -52,16 +46,17 @@ class JobListTest extends TestCase {
$this->config,
$this->timeFactory,
Server::get(LoggerInterface::class),
Server::get(IGenerator::class),
);
}
protected function clearJobsList() {
protected function clearJobsList(): void {
$query = $this->connection->getQueryBuilder();
$query->delete('jobs');
$query->executeStatement();
}
protected function getAllSorted() {
protected function getAllSorted(): array {
$iterator = $this->instance->getJobsIterator(null, null, 0);
$jobs = [];
@ -69,10 +64,6 @@ class JobListTest extends TestCase {
$jobs[] = clone $job;
}
usort($jobs, function (IJob $job1, IJob $job2) {
return $job1->getId() - $job2->getId();
});
return $jobs;
}
@ -89,11 +80,8 @@ class JobListTest extends TestCase {
];
}
/**
* @param $argument
*/
#[\PHPUnit\Framework\Attributes\DataProvider('argumentProvider')]
public function testAddRemove($argument): void {
#[DataProvider('argumentProvider')]
public function testAddRemove(mixed $argument): void {
$existingJobs = $this->getAllSorted();
$job = new TestJob();
$this->instance->add($job, $argument);
@ -111,11 +99,8 @@ class JobListTest extends TestCase {
$this->assertEquals($existingJobs, $jobs);
}
/**
* @param $argument
*/
#[\PHPUnit\Framework\Attributes\DataProvider('argumentProvider')]
public function testRemoveDifferentArgument($argument): void {
#[DataProvider('argumentProvider')]
public function testRemoveDifferentArgument(mixed $argument): void {
$existingJobs = $this->getAllSorted();
$job = new TestJob();
$this->instance->add($job, $argument);
@ -132,11 +117,8 @@ class JobListTest extends TestCase {
$this->assertEquals($existingJobs, $jobs);
}
/**
* @param $argument
*/
#[\PHPUnit\Framework\Attributes\DataProvider('argumentProvider')]
public function testHas($argument): void {
#[DataProvider('argumentProvider')]
public function testHas(mixed $argument): void {
$job = new TestJob();
$this->assertFalse($this->instance->has($job, $argument));
$this->instance->add($job, $argument);
@ -148,11 +130,8 @@ class JobListTest extends TestCase {
$this->assertFalse($this->instance->has($job, $argument));
}
/**
* @param $argument
*/
#[\PHPUnit\Framework\Attributes\DataProvider('argumentProvider')]
public function testHasDifferentArgument($argument): void {
#[DataProvider('argumentProvider')]
public function testHasDifferentArgument(mixed $argument): void {
$job = new TestJob();
$this->instance->add($job, $argument);
@ -163,14 +142,16 @@ class JobListTest extends TestCase {
$argument,
int $reservedTime = 0,
int $lastChecked = 0,
int $lastRun = 0): int {
int $lastRun = 0): string {
if ($lastChecked === 0) {
$lastChecked = time();
}
$id = Server::get(IGenerator::class)->nextId();
$query = $this->connection->getQueryBuilder();
$query->insert('jobs')
->values([
'id' => $query->createNamedParameter($id, IQueryBuilder::PARAM_INT),
'class' => $query->createNamedParameter($class),
'argument' => $query->createNamedParameter($argument),
'last_run' => $query->createNamedParameter($lastRun, IQueryBuilder::PARAM_INT),
@ -178,7 +159,7 @@ class JobListTest extends TestCase {
'reserved_at' => $query->createNamedParameter($reservedTime, IQueryBuilder::PARAM_INT),
]);
$query->executeStatement();
return $query->getLastInsertId();
return $id;
}
public function testGetNext(): void {
@ -243,7 +224,7 @@ class JobListTest extends TestCase {
/**
* @param $argument
*/
#[\PHPUnit\Framework\Attributes\DataProvider('argumentProvider')]
#[DataProvider('argumentProvider')]
public function testGetById($argument): void {
$job = new TestJob();
$this->instance->add($job, $argument);
@ -334,8 +315,4 @@ class JobListTest extends TestCase {
$job = $this->instance->getNext();
$this->assertNull($job); // Job doesn't allow parallel runs
}
public function markRun() {
$this->ran = true;
}
}