Initialize long URL hash to empty string so that it's not necessary to set it as non-nullable afterwards

This commit is contained in:
Alejandro Celaya
2026-06-10 12:06:39 +02:00
parent b099166ac8
commit 1ae2ce9e01
5 changed files with 13 additions and 35 deletions
+4 -4
View File
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\CLI\Util;
use Closure;
use Shlinkio\Shlink\CLI\Command\Util\LockConfig;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\ProcessHelper;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
@@ -18,13 +17,15 @@ use function str_replace;
class ProcessRunner implements ProcessRunnerInterface
{
private const int TIMEOUT = 1_200; // 20 minutes
private Closure $createProcess;
public function __construct(private ProcessHelper $helper, callable|null $createProcess = null)
public function __construct(private readonly ProcessHelper $helper, callable|null $createProcess = null)
{
$this->createProcess = $createProcess !== null
? $createProcess(...)
: static fn (array $cmd) => new Process($cmd, timeout: LockConfig::DEFAULT_TTL);
: static fn (array $cmd) => new Process($cmd, timeout: self::TIMEOUT);
}
public function run(OutputInterface $output, array $cmd): void
@@ -35,7 +36,6 @@ class ProcessRunner implements ProcessRunnerInterface
/** @var DebugFormatterHelper $formatter */
$formatter = $this->helper->getHelperSet()?->get('debug_formatter') ?? new DebugFormatterHelper();
/** @var Process $process */
$process = ($this->createProcess)($cmd);
if ($output->isVeryVerbose()) {
@@ -26,7 +26,7 @@ final class Version20260524105410 extends AbstractMigration
$shortUrls->addColumn(self::COLUMN_NAME, Types::BINARY, [
'length' => 32,
'notnull' => false, // Temporarily nullable until values have been filled
'default' => '', // Temporary value until they have been filled by next migration
]);
$shortUrls->addIndex([self::COLUMN_NAME], self::INDEX_NAME);
}
@@ -20,15 +20,19 @@ final class Version20260607082210 extends AbstractMigration
$qb = $this->connection->createQueryBuilder();
$qb
->select('id', 'original_url')
->from('short_urls');
->from('short_urls')
// If this migration times out, this will ensure it can be rerun, and it will continue where it was left, so
// it can be run multiple times until all short URLs have been processed
->where($qb->expr()->eq('long_url_hash', ':longUrlHash'))
->setParameters(['longUrlHash' => '']);
$shortUrlsResult = $qb->executeQuery();
$iteration = 0;
$iteration = 1;
$this->connection->beginTransaction();
while ($row = $shortUrlsResult->fetchAssociative()) {
// Every few updates, commit the transaction and begin a new one
if (($iteration % 2000) === 0) {
if (($iteration % 10_000) === 0) {
$this->connection->commit();
$this->connection->beginTransaction();
}
@@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace ShlinkMigrations;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Makes long_url_hash non-nullable, now that previous migration has set the values for all existing entries
*/
final class Version20260609093926 extends AbstractMigration
{
public function up(Schema $schema): void
{
$shortUrls = $schema->getTable('short_urls');
$shortUrls->getColumn('long_url_hash')->setNotnull(true);
}
public function isTransactional(): bool
{
return !$this->connection->getDatabasePlatform() instanceof MySQLPlatform;
}
}