fix(bg_jobs): store job argument as a text, increase length cap from 4000 to 32000

Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
This commit is contained in:
Maksim Sukharev 2026-03-18 11:26:36 +01:00
parent b7a6bd9fa4
commit 1c5334f890
4 changed files with 64 additions and 3 deletions

View file

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Migrations;
use Closure;
use Doctrine\DBAL\Types\Type;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\Attributes\ColumnType;
use OCP\Migration\Attributes\ModifyColumn;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
use Override;
#[ModifyColumn(table: 'jobs', name: 'argument', type: ColumnType::TEXT, description: 'Migrate background job arguments to a text column')]
class Version34000Date20260318095645 extends SimpleMigrationStep {
#[Override]
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if ($schema->hasTable('jobs')) {
$table = $schema->getTable('jobs');
$argumentColumn = $table->getColumn('argument');
if ($argumentColumn->getType() !== Type::getType(Types::TEXT)) {
$argumentColumn->setType(Type::getType(Types::TEXT));
return $schema;
}
}
return null;
}
}

View file

@ -26,6 +26,8 @@ use function min;
use function strlen;
class JobList implements IJobList {
public const MAX_ARGUMENT_JSON_LENGTH = 32000;
/** @var array<string, string> */
protected array $alreadyVisitedParallelBlocked = [];
@ -47,8 +49,8 @@ class JobList implements IJobList {
$class = ($job instanceof IJob) ? get_class($job) : $job;
$argumentJson = json_encode($argument);
if (strlen($argumentJson) > 4000) {
throw new \InvalidArgumentException('Background job arguments can\'t exceed 4000 characters (json encoded)');
if (strlen($argumentJson) > self::MAX_ARGUMENT_JSON_LENGTH) {
throw new \InvalidArgumentException('Background job arguments can\'t exceed ' . self::MAX_ARGUMENT_JSON_LENGTH . ' characters (json encoded)');
}
$query = $this->connection->getQueryBuilder();

View file

@ -99,6 +99,24 @@ class JobListTest extends TestCase {
$this->assertEquals($existingJobs, $jobs);
}
public function testAddAcceptsArgumentUnderMaxLength(): void {
$argument = str_repeat('a', $this->instance::MAX_ARGUMENT_JSON_LENGTH - 100);
$job = new TestJob();
$this->assertFalse($this->instance->has($job, $argument));
$this->instance->add($job, $argument);
$this->assertTrue($this->instance->has($job, $argument));
}
public function testAddRejectsArgumentAboveMaxLength(): void {
$argument = str_repeat('a', $this->instance::MAX_ARGUMENT_JSON_LENGTH + 100);
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Background job arguments can\'t exceed ' . $this->instance::MAX_ARGUMENT_JSON_LENGTH . ' characters (json encoded)');
$this->instance->add(new TestJob(), $argument);
}
#[DataProvider('argumentProvider')]
public function testRemoveDifferentArgument(mixed $argument): void {
$existingJobs = $this->getAllSorted();

View file

@ -9,7 +9,7 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patch level
// when updating major/minor version number.
$OC_Version = [33, 0, 0, 16];
$OC_Version = [33, 0, 0, 17];
// The human-readable string
$OC_VersionString = '33.0.0';