Capture error on real-time update when creating short URL

This commit is contained in:
Alejandro Celaya
2023-04-12 09:15:36 +02:00
parent 33911afcd6
commit f078d95588
9 changed files with 71 additions and 19 deletions

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Shlinkio\Shlink\Core\ShortUrl\Model;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Throwable;
final class UrlShorteningResult
{
private function __construct(
public readonly ShortUrl $shortUrl,
private readonly ?Throwable $errorOnEventDispatching,
) {
}
/**
* @param callable(Throwable $errorOnEventDispatching): void $handler
*/
public function onEventDispatchingError(callable $handler): void
{
if ($this->errorOnEventDispatching !== null) {
$handler($this->errorOnEventDispatching);
}
}
public static function withoutErrorOnEventDispatching(ShortUrl $shortUrl): self
{
return new self($shortUrl, null);
}
public static function withErrorOnEventDispatching(ShortUrl $shortUrl, Throwable $errorOnEventDispatching): self
{
return new self($shortUrl, $errorOnEventDispatching);
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\ShortUrl;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Shlinkio\Shlink\Core\EventDispatcher\Event\ShortUrlCreated;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
@@ -13,6 +14,7 @@ use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortCodeUniquenessHelperInterface;
use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlTitleResolutionHelperInterface;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlRepositoryInterface;
use Shlinkio\Shlink\Core\ShortUrl\Resolver\ShortUrlRelationResolverInterface;
@@ -31,12 +33,12 @@ class UrlShortener implements UrlShortenerInterface
* @throws NonUniqueSlugException
* @throws InvalidUrlException
*/
public function shorten(ShortUrlCreation $creation): ShortUrl
public function shorten(ShortUrlCreation $creation): UrlShorteningResult
{
// First, check if a short URL exists for all provided params
$existingShortUrl = $this->findExistingShortUrlIfExists($creation);
if ($existingShortUrl !== null) {
return $existingShortUrl;
return UrlShorteningResult::withoutErrorOnEventDispatching($existingShortUrl);
}
$creation = $this->titleResolutionHelper->processTitleAndValidateUrl($creation);
@@ -51,9 +53,17 @@ class UrlShortener implements UrlShortenerInterface
return $shortUrl;
});
$this->eventDispatcher->dispatch(new ShortUrlCreated($newShortUrl->getId()));
try {
$this->eventDispatcher->dispatch(new ShortUrlCreated($newShortUrl->getId()));
} catch (ContainerExceptionInterface $e) {
// Ignore container errors when dispatching the event.
// When using openswoole, this event will try to enqueue a task, which cannot be done outside an HTTP
// request.
// If the short URL is created from CLI, the event dispatching will fail.
return UrlShorteningResult::withErrorOnEventDispatching($newShortUrl, $e);
}
return $newShortUrl;
return UrlShorteningResult::withoutErrorOnEventDispatching($newShortUrl);
}
private function findExistingShortUrlIfExists(ShortUrlCreation $creation): ?ShortUrl

View File

@@ -6,8 +6,8 @@ namespace Shlinkio\Shlink\Core\ShortUrl;
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
interface UrlShortenerInterface
{
@@ -15,5 +15,5 @@ interface UrlShortenerInterface
* @throws NonUniqueSlugException
* @throws InvalidUrlException
*/
public function shorten(ShortUrlCreation $creation): ShortUrl;
public function shorten(ShortUrlCreation $creation): UrlShorteningResult;
}

View File

@@ -58,9 +58,9 @@ class UrlShortenerTest extends TestCase
)->willReturnArgument(0);
$this->shortCodeHelper->method('ensureShortCodeUniqueness')->willReturn(true);
$shortUrl = $this->urlShortener->shorten($meta);
$result = $this->urlShortener->shorten($meta);
self::assertEquals($longUrl, $shortUrl->getLongUrl());
self::assertEquals($longUrl, $result->shortUrl->getLongUrl());
}
#[Test]
@@ -91,7 +91,7 @@ class UrlShortenerTest extends TestCase
$result = $this->urlShortener->shorten($meta);
self::assertSame($expected, $result);
self::assertSame($expected, $result->shortUrl);
}
public static function provideExistingShortUrls(): iterable