feat: add a lock on domain update

This commit is contained in:
Maël Gangloff 2025-11-09 20:03:52 +01:00
parent d236d12cec
commit aebc90d34b
No known key found for this signature in database
GPG Key ID: 11FDC81C24A7F629
2 changed files with 39 additions and 1 deletions

View File

@ -7,7 +7,7 @@ final class UpdateDomain
public function __construct(
public string $ldhName,
public ?string $watchlistToken,
public bool $onlyNew = false,
public bool $onlyNew,
) {
}
}

View File

@ -20,6 +20,9 @@ use App\Service\ChatNotificationService;
use App\Service\RDAPService;
use Doctrine\ORM\OptimisticLockException;
use Psr\Log\LoggerInterface;
use Symfony\Component\Lock\Key;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\SharedLockInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
@ -49,6 +52,7 @@ final readonly class UpdateDomainHandler
private WatchlistRepository $watchlistRepository,
private DomainRepository $domainRepository,
private LoggerInterface $logger,
private LockFactory $lockFactory,
) {
$this->sender = new Address($mailerSenderEmail, $mailerSenderName);
}
@ -68,6 +72,7 @@ final readonly class UpdateDomainHandler
*/
public function __invoke(UpdateDomain $message): void
{
/** @var ?Domain $domain */
$domain = $this->domainRepository->findOneBy(['ldhName' => $message->ldhName]);
if (null !== $domain && $message->onlyNew) {
@ -79,12 +84,24 @@ final readonly class UpdateDomainHandler
}
if (null === $domain) {
$lock = $this->createDomainLock($message->ldhName);
if (!$lock->acquire()) {
$this->logger->notice('Update of this domain name is locked because it is already in progress', [
'ldhName' => $message->ldhName,
]);
return;
}
try {
$this->RDAPService->registerDomain($message->ldhName);
} catch (TldNotSupportedException|MalformedDomainException $exception) {
throw new UnrecoverableMessageHandlingException($exception->getMessage(), 0, $exception);
} catch (UnknownRdapServerException|DomainNotFoundException) {
return;
} finally {
$lock->release();
}
return;
@ -124,6 +141,16 @@ final readonly class UpdateDomainHandler
$updatedAt = $domain->getUpdatedAt();
$deleted = $domain->getDeleted();
$lock = $this->createDomainLock($message->ldhName);
if (!$lock->acquire()) {
$this->logger->notice('Update of this domain name is locked because it is already in progress', [
'ldhName' => $message->ldhName,
]);
return;
}
try {
/*
* Domain name update
@ -158,6 +185,17 @@ final readonly class UpdateDomainHandler
throw new UnrecoverableMessageHandlingException($exception->getMessage(), 0, $exception);
} catch (UnknownRdapServerException) {
return;
} finally {
$lock->release();
}
}
private function createDomainLock(string $ldhName): SharedLockInterface
{
return $this->lockFactory->createLockFromKey(
new Key('domain_update.'.$ldhName),
ttl: 600,
autoRelease: false
);
}
}